Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commita376e8d

Browse files
authored
fix: include a link and more useful error details for 403 response codes (#16644)
Currently if a user gets to a page they don't have permission to viewthey're greeted with a vague error alert and no actionable items. ThisPR adds a link back to _/workspaces_ within the alert as well as morehelpful error details.Before:![Screenshot 2025-02-20 at 11 0606 AM](https://github.com/user-attachments/assets/cea5b86d-673b-482b-ac0b-f132eb518910)After:![Screenshot 2025-02-20 at 11 0619 AM](https://github.com/user-attachments/assets/6bf0e9fd-fc51-4d9a-afbc-fea9f0439aff)
1 parentf8a49f4 commita376e8d

File tree

7 files changed

+48
-23
lines changed

7 files changed

+48
-23
lines changed

‎coderd/httpapi/httpapi.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,7 @@ func ResourceNotFound(rw http.ResponseWriter) {
154154
funcForbidden(rw http.ResponseWriter) {
155155
Write(context.Background(),rw,http.StatusForbidden, codersdk.Response{
156156
Message:"Forbidden.",
157+
Detail:"You don't have permission to view this content. If you believe this is a mistake, please contact your administrator or try signing in with different credentials.",
157158
})
158159
}
159160

‎site/e2e/setup/addUsersAndLicense.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import{expect,test}from"@playwright/test";
22
import{API}from"api/api";
3-
import{Language}from"pages/CreateUserPage/CreateUserForm";
3+
import{Language}from"pages/CreateUserPage/Language";
44
import{coderPort,license,premiumTestsRequired,users}from"../constants";
55
import{expectUrl}from"../expectUrl";
66
import{createUser}from"../helpers";

‎site/src/api/errors.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,14 @@ export const getErrorDetail = (error: unknown): string | undefined => {
133133
returnundefined;
134134
};
135135

136+
exportconstgetErrorStatus=(error:unknown):number|undefined=>{
137+
if(isApiError(error)){
138+
returnerror.status;
139+
}
140+
141+
returnundefined;
142+
};
143+
136144
exportclassDetailedErrorextendsError{
137145
constructor(
138146
message:string,
Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,44 @@
11
importAlertTitlefrom"@mui/material/AlertTitle";
2-
import{getErrorDetail,getErrorMessage}from"api/errors";
2+
import{getErrorDetail,getErrorMessage,getErrorStatus}from"api/errors";
33
importtype{FC}from"react";
4+
import{Link}from"../Link/Link";
45
import{Alert,AlertDetail,typeAlertProps}from"./Alert";
56

67
exportconstErrorAlert:FC<
78
Omit<AlertProps,"severity"|"children">&{error:unknown}
89
>=({ error, ...alertProps})=>{
910
constmessage=getErrorMessage(error,"Something went wrong.");
1011
constdetail=getErrorDetail(error);
12+
conststatus=getErrorStatus(error);
1113

1214
// For some reason, the message and detail can be the same on the BE, but does
1315
// not make sense in the FE to showing them duplicated
1416
constshouldDisplayDetail=message!==detail;
1517

1618
return(
1719
<Alertseverity="error"{...alertProps}>
18-
{detail ?(
19-
<>
20-
<AlertTitle>{message}</AlertTitle>
21-
{shouldDisplayDetail&&<AlertDetail>{detail}</AlertDetail>}
22-
</>
23-
) :(
24-
message
25-
)}
20+
{
21+
// When the error is a Forbidden response we include a link for the user to
22+
// go back to a known viewable page.
23+
status===403 ?(
24+
<>
25+
<AlertTitle>{message}</AlertTitle>
26+
<AlertDetail>
27+
{detail}{" "}
28+
<Linkhref="/workspaces"className="w-fit">
29+
Go to workspaces
30+
</Link>
31+
</AlertDetail>
32+
</>
33+
) :detail ?(
34+
<>
35+
<AlertTitle>{message}</AlertTitle>
36+
{shouldDisplayDetail&&<AlertDetail>{detail}</AlertDetail>}
37+
</>
38+
) :(
39+
message
40+
)
41+
}
2642
</Alert>
2743
);
2844
};

‎site/src/pages/CreateUserPage/CreateUserForm.tsx

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -19,18 +19,7 @@ import {
1919
onChangeTrimmed,
2020
}from"utils/formUtils";
2121
import*asYupfrom"yup";
22-
23-
exportconstLanguage={
24-
emailLabel:"Email",
25-
passwordLabel:"Password",
26-
usernameLabel:"Username",
27-
nameLabel:"Full name",
28-
emailInvalid:"Please enter a valid email address.",
29-
emailRequired:"Please enter an email address.",
30-
passwordRequired:"Please enter a password.",
31-
createUser:"Create",
32-
cancel:"Cancel",
33-
};
22+
import{Language}from"./Language";
3423

3524
exportconstauthMethodLanguage={
3625
password:{

‎site/src/pages/CreateUserPage/CreateUserPage.test.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ import {
44
renderWithAuth,
55
waitForLoaderToBeRemoved,
66
}from"testHelpers/renderHelpers";
7-
import{LanguageasFormLanguage}from"./CreateUserForm";
87
import{CreateUserPage}from"./CreateUserPage";
8+
import{LanguageasFormLanguage}from"./Language";
99

1010
constrenderCreateUserPage=async()=>{
1111
renderWithAuth(<CreateUserPage/>,{
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
exportconstLanguage={
2+
emailLabel:"Email",
3+
passwordLabel:"Password",
4+
usernameLabel:"Username",
5+
nameLabel:"Full name",
6+
emailInvalid:"Please enter a valid email address.",
7+
emailRequired:"Please enter an email address.",
8+
passwordRequired:"Please enter a password.",
9+
createUser:"Create",
10+
cancel:"Cancel",
11+
};

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp