Skip to content

Commit a06453e

Browse files
refactor: Replace jQuery AJAX calls with custom fetch-based API utilities.
1 parent 8873b71 commit a06453e

10 files changed

Lines changed: 192 additions & 155 deletions

File tree

src/public/components/2fa.js

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { ConfigurationContext } from "../context/configuration.js";
22
import { afterLogin, errorTextTimeout, getPlaceholder, useTitle } from "../utils/utils.js";
3+
import { post } from "../utils/api.js";
34

45
export default function TwoFactorAuthentication() {
56
const submitButtonText = i18next.t("button.submit");
@@ -15,28 +16,24 @@ export default function TwoFactorAuthentication() {
1516
setErrorMessage(props.errorText);
1617
};
1718

18-
function submit2fa(event) {
19+
async function submit2fa(event) {
1920
event.preventDefault();
2021
setErrorMessage("");
2122
const code = document.getElementById("code").value;
2223
const urlParams = new URLSearchParams(window.location.search);
2324
const target = urlParams.get("target");
2425
const sessionHash = urlParams.get("session_hash");
2526
setSubmitting(true);
26-
$.post("/user/do-2fa", {
27-
target,
28-
code,
29-
sessionHash,
30-
})
31-
.done(function () {
27+
try {
28+
const result = await post("/user/do-2fa", { target, code, sessionHash });
29+
if (result.ok) {
3230
afterLogin(configuration);
33-
})
34-
.fail(function () {
31+
} else {
3532
onSubmitError({ errorText: i18next.t("error.invalid-code") });
36-
})
37-
.always(function () {
38-
setSubmitting(false);
39-
});
33+
}
34+
} finally {
35+
setSubmitting(false);
36+
}
4037
}
4138

4239
return (

src/public/components/consent.js

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { ConfigurationContext } from "../context/configuration.js";
22
import { ThemeContext } from "../context/theme.js";
33
import { prepareAuthorizationParams, getPlaceholder, useTitle } from "../utils/utils.js";
4+
import { get } from "../utils/api.js";
45

56
export default function ConsentScreen() {
67
const configuration = React.useContext(ConfigurationContext);
@@ -17,12 +18,12 @@ export default function ConsentScreen() {
1718

1819
React.useEffect(() => {
1920
(async () => {
20-
const clientInformation = await $.get(`/client/${authParams.client_id}`);
21-
const permissionsInformation = await $.get("/user/scopes");
22-
setClientInfo(clientInformation.data.client);
21+
const clientResult = await get(`/client/${authParams.client_id}`);
22+
const permissionsResult = await get("/user/scopes");
23+
setClientInfo(clientResult.data.data.client);
2324
setRequiredScopes(authParams.scope.split(","));
24-
setPermissionsInfo(permissionsInformation.data.scopes);
25-
console.log(clientInformation.data, permissionsInformation.data);
25+
setPermissionsInfo(permissionsResult.data.data.scopes);
26+
console.log(clientResult.data.data, permissionsResult.data.data);
2627
})();
2728
}, []);
2829

@@ -33,9 +34,9 @@ export default function ConsentScreen() {
3334

3435
const onDeny = () => {
3536
const redirectUri = new URL(authParams.redirect_uri);
36-
redirectUri.searchParams.append('error', 'access_denied');
37-
redirectUri.searchParams.append('error_description', 'Access was denied by the user');
38-
redirectUri.searchParams.append('state', authParams.state);
37+
redirectUri.searchParams.append("error", "access_denied");
38+
redirectUri.searchParams.append("error_description", "Access was denied by the user");
39+
redirectUri.searchParams.append("state", authParams.state);
3940
window.location = redirectUri;
4041
};
4142

@@ -45,7 +46,8 @@ export default function ConsentScreen() {
4546
<div className="form">
4647
<div className="noselect">
4748
<h3 className="long-header">
48-
{i18next.t("heading.consent")}<span className="header-separator">&nbsp;&#x2022;&nbsp;</span>
49+
{i18next.t("heading.consent")}
50+
<span className="header-separator">&nbsp;&#x2022;&nbsp;</span>
4951
{configuration[`assets.header-icon-${theme}`] ? (
5052
<div className="app-icon-header">
5153
<div style={{ display: miniIconLoaded ? "none" : "block" }} className="spinner" />
@@ -61,9 +63,7 @@ export default function ConsentScreen() {
6163
)}
6264
</h3>
6365
<div className="consent-form">
64-
<p>
65-
{i18next.t("message.consent", { app_name: clientInfo.displayName })}
66-
</p>
66+
<p>{i18next.t("message.consent", { app_name: clientInfo.displayName })}</p>
6767
<ul className="scope-container">
6868
{requiredScopes.map((scope) => (
6969
<li className="scope-item" key={scope}>
@@ -74,9 +74,7 @@ export default function ConsentScreen() {
7474
</li>
7575
))}
7676
</ul>
77-
<p className="fineprint">
78-
{i18next.t("message.consent-warning")}
79-
</p>
77+
<p className="fineprint">{i18next.t("message.consent-warning")}</p>
8078
</div>
8179
</div>
8280
<div className="page-links"></div>

src/public/components/get-code.js

Lines changed: 15 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { ConfigurationContext } from "../context/configuration.js";
22
import { errorTextTimeout, getPlaceholder, useTitle } from "../utils/utils.js";
3+
import { get } from "../utils/api.js";
34

45
export default function GetCode() {
56
const submitButtonText = i18next.t("button.get-code");
@@ -13,33 +14,30 @@ export default function GetCode() {
1314
React.useEffect(() => useTitle(configuration["content.app-name"], i18next.t("title.verify-your-identity")), []);
1415

1516
const onSubmitError = (props) => {
16-
1717
setErrorMessage(props.errorText);
1818
};
1919

20-
function getCode(event) {
20+
async function getCode(event) {
2121
event.preventDefault();
2222
setErrorMessage("");
23-
23+
2424
const email = document.getElementById("email").value;
2525
setSubmitting(true);
26-
$.get("/user/code", {
27-
email,
28-
})
29-
.done(function (response) {
26+
try {
27+
const result = await get("/user/code", { email });
28+
if (result.ok) {
3029
const urlParams = new URLSearchParams(window.location.search);
31-
urlParams.set("target", response.data.target);
30+
urlParams.set("target", result.data.data.target);
3231
window.location = `/reset-password?${urlParams.toString()}`;
33-
})
34-
.fail(function (response) {
35-
if (response.responseJSON.additionalInfo && response.status === 400) {
36-
return onFieldError({ response });
32+
} else {
33+
if (result.error.additionalInfo && result.status === 400) {
34+
return onFieldError({ response: { responseJSON: result.error, status: result.status } });
3735
}
3836
onSubmitError({ errorText: i18next.t("error.invalid-login") });
39-
})
40-
.always(function () {
41-
setSubmitting(false);
42-
});
37+
}
38+
} finally {
39+
setSubmitting(false);
40+
}
4341
}
4442

4543
if (!configuration["privilege.can-reset-password"]) {
@@ -78,12 +76,7 @@ export default function GetCode() {
7876
</a>
7977
</span>
8078
</div>
81-
<input
82-
type="submit"
83-
disabled={submitting}
84-
className="button"
85-
value={submitButtonText}
86-
/>
79+
<input type="submit" disabled={submitting} className="button" value={submitButtonText} />
8780
<div className="form-error-message">{errorMessage}</div>
8881
</form>
8982
);

src/public/components/login.js

Lines changed: 28 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import {
1010
afterLogin,
1111
humanReadableToSnakeCase,
1212
} from "../utils/utils.js";
13+
import { post } from "../utils/api.js";
1314

1415
export default function Login() {
1516
const submitButtonText = i18next.t("button.login");
@@ -50,10 +51,10 @@ export default function Login() {
5051
setErrorMessage(props.errorText);
5152
};
5253

53-
function onFieldError({ response, buttonText }) {
54-
let errorField = response.responseJSON.additionalInfo.errors[0].path;
54+
function onFieldError({ response }) {
55+
let errorField = response.error.additionalInfo.errors[0].path;
5556
errorField = errorField.charAt(0).toUpperCase() + errorField.slice(1);
56-
onSubmitError({ errorText: "Invalid " + errorField, buttonText });
57+
onSubmitError({ errorText: "Invalid " + errorField });
5758
return;
5859
}
5960

@@ -81,27 +82,27 @@ export default function Login() {
8182
} else {
8283
data.username = username;
8384
}
84-
$.post("/user/login", data)
85-
.done(async function (response) {
86-
onLogin(response.data);
87-
})
88-
.fail(function (response) {
89-
if (response.responseJSON.error === "RateLimitError") {
85+
try {
86+
const result = await post("/user/login", data);
87+
if (result.ok) {
88+
onLogin(result.data.data);
89+
} else {
90+
if (result.error.error === "RateLimitError") {
9091
onSubmitError({ errorText: i18next.t("error.too-many-retries") });
9192
return;
9293
}
93-
if (response.responseJSON.error === "ResourceNotActive") {
94+
if (result.error.error === "ResourceNotActive") {
9495
onSubmitError({ errorText: i18next.t("error.account-not-verified") });
9596
return;
9697
}
97-
if (response.status === 400 && response.responseJSON.additionalInfo) {
98-
return onFieldError({ response });
98+
if (result.status === 400 && result.error.additionalInfo) {
99+
return onFieldError({ response: result });
99100
}
100101
onSubmitError({ errorText: i18next.t("error.invalid-login") });
101-
})
102-
.always(function () {
103-
setSubmitting(false);
104-
});
102+
}
103+
} finally {
104+
setSubmitting(false);
105+
}
105106
}
106107

107108
const handleSSOClick = (event) => {
@@ -131,22 +132,20 @@ export default function Login() {
131132
} catch (e) {
132133
console.error("Failed to parse authorization params", e);
133134
}
134-
$.ajax({
135-
url: "/sso/google/success",
136-
type: "POST",
137-
contentType: "application/json",
138-
data: JSON.stringify({
135+
const result = await post(
136+
"/sso/google/success",
137+
{
139138
ssoToken: ssoToken,
140139
userAgent: window.navigator.userAgent,
141-
}),
142-
success: function () {
143-
afterLogin(configuration);
144-
},
145-
error: function () {
146-
setIsLoggedIn(false);
147-
onSubmitError({ errorText: i18next.t("error.invalid-login") });
148140
},
149-
});
141+
{ json: true },
142+
);
143+
if (result.ok) {
144+
afterLogin(configuration);
145+
} else {
146+
setIsLoggedIn(false);
147+
onSubmitError({ errorText: i18next.t("error.invalid-login") });
148+
}
150149
};
151150

152151
if (isLoggedIn) {

src/public/components/reset-password.js

Lines changed: 12 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { ConfigurationContext } from "../context/configuration.js";
22
import { errorTextTimeout, getPlaceholder, useTitle } from "../utils/utils.js";
3+
import { post } from "../utils/api.js";
34

45
export default function ResetPassword() {
56
const submitButtonText = i18next.t("button.change-password");
@@ -13,33 +14,28 @@ export default function ResetPassword() {
1314
React.useEffect(() => useTitle(configuration["content.app-name"], i18next.t("title.reset-password")), []);
1415

1516
const onSubmitError = (props) => {
16-
1717
setErrorMessage(props.errorText);
1818
};
1919

20-
function resetPassword(event) {
20+
async function resetPassword(event) {
2121
event.preventDefault();
2222
setErrorMessage("");
23-
23+
2424
const code = document.getElementById("code").value;
2525
const password = document.getElementById("password").value;
2626
const urlParams = new URLSearchParams(window.location.search);
2727
const target = urlParams.get("target");
2828
setSubmitting(true);
29-
$.post("/user/reset-password", {
30-
target,
31-
code,
32-
password,
33-
})
34-
.done(function () {
29+
try {
30+
const result = await post("/user/reset-password", { target, code, password });
31+
if (result.ok) {
3532
window.location = `/login${window.location.search}`;
36-
})
37-
.fail(function () {
33+
} else {
3834
onSubmitError({ errorText: i18next.t("error.invalid-code") });
39-
})
40-
.always(function () {
41-
setSubmitting(false);
42-
});
35+
}
36+
} finally {
37+
setSubmitting(false);
38+
}
4339
}
4440

4541
if (!configuration["privilege.can-reset-password"]) {
@@ -83,12 +79,7 @@ export default function ResetPassword() {
8379
/>
8480
</div>
8581
<div className="page-links"></div>
86-
<input
87-
type="submit"
88-
disabled={submitting}
89-
className="button"
90-
value={submitButtonText}
91-
/>
82+
<input type="submit" disabled={submitting} className="button" value={submitButtonText} />
9283
<div className="form-error-message">{errorMessage}</div>
9384
</form>
9485
);

0 commit comments

Comments
 (0)