@saltcorn/mobile-app 1.6.0-beta.3 → 1.6.0-beta.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/helpers/api.js +25 -1
- package/src/helpers/auth.js +40 -19
- package/src/init.js +16 -10
package/package.json
CHANGED
package/src/helpers/api.js
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
/*global saltcorn, splashConfig*/
|
|
2
2
|
|
|
3
3
|
import axios from "axios";
|
|
4
|
+
import { jwtDecode } from "jwt-decode";
|
|
5
|
+
import { router } from "../routing/index";
|
|
6
|
+
import { replaceIframe, clearHistory } from "./navigation";
|
|
4
7
|
|
|
5
8
|
export async function apiCall({
|
|
6
9
|
method,
|
|
@@ -24,7 +27,28 @@ export async function apiCall({
|
|
|
24
27
|
};
|
|
25
28
|
if (config.tenantAppName) headers["X-Saltcorn-App"] = config.tenantAppName;
|
|
26
29
|
const token = config.jwt;
|
|
27
|
-
if (token)
|
|
30
|
+
if (token) {
|
|
31
|
+
try {
|
|
32
|
+
const decoded = jwtDecode(token);
|
|
33
|
+
if (decoded.exp && decoded.exp < Date.now() / 1000 && typeof saltcorn !== "undefined" && !path.startsWith("/auth/")) {
|
|
34
|
+
const mobileConfig = saltcorn.data.state.getState().mobileConfig;
|
|
35
|
+
mobileConfig.jwt = undefined;
|
|
36
|
+
await saltcorn.data.db.deleteWhere("jwt_table");
|
|
37
|
+
clearHistory();
|
|
38
|
+
const page = await router.resolve({
|
|
39
|
+
pathname: "get/auth/login",
|
|
40
|
+
alerts: [
|
|
41
|
+
{ type: "warning", msg: "Your session has expired, please log in again." },
|
|
42
|
+
],
|
|
43
|
+
});
|
|
44
|
+
await replaceIframe(page.content);
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
} catch {
|
|
48
|
+
// malformed token, let the request proceed and fail naturally
|
|
49
|
+
}
|
|
50
|
+
headers.Authorization = `jwt ${token}`;
|
|
51
|
+
}
|
|
28
52
|
try {
|
|
29
53
|
const result = await axios({
|
|
30
54
|
url: url,
|
package/src/helpers/auth.js
CHANGED
|
@@ -26,22 +26,22 @@ async function loginRequest({ email, password, isSignup, isPublic }) {
|
|
|
26
26
|
path: "/auth/login-with/jwt",
|
|
27
27
|
}
|
|
28
28
|
: isSignup
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
29
|
+
? {
|
|
30
|
+
method: "POST",
|
|
31
|
+
path: "/auth/signup",
|
|
32
|
+
body: {
|
|
33
|
+
email,
|
|
34
|
+
password,
|
|
35
|
+
},
|
|
36
|
+
}
|
|
37
|
+
: {
|
|
38
|
+
method: "POST",
|
|
39
|
+
path: "/auth/login-with/jwt",
|
|
40
|
+
body: {
|
|
41
|
+
email,
|
|
42
|
+
password,
|
|
43
|
+
},
|
|
44
|
+
};
|
|
45
45
|
const response = await apiCall(opts);
|
|
46
46
|
return response.data;
|
|
47
47
|
}
|
|
@@ -241,13 +241,34 @@ export async function setJwt(jwt) {
|
|
|
241
241
|
await saltcorn.data.db.insert("jwt_table", { jwt: jwt });
|
|
242
242
|
}
|
|
243
243
|
|
|
244
|
-
|
|
245
|
-
|
|
244
|
+
async function renewJwt() {
|
|
245
|
+
try {
|
|
246
|
+
const response = await apiCall({
|
|
247
|
+
method: "POST",
|
|
248
|
+
path: "/auth/renew-jwt",
|
|
249
|
+
});
|
|
250
|
+
if (typeof response.data === "string") {
|
|
251
|
+
const config = saltcorn.data.state.getState().mobileConfig;
|
|
252
|
+
await setJwt(response.data);
|
|
253
|
+
config.jwt = response.data;
|
|
254
|
+
}
|
|
255
|
+
} catch (e) {
|
|
256
|
+
console.error("JWT renewal failed:", e.message);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
export async function checkJWT(jwtStr) {
|
|
261
|
+
if (jwtStr && jwtStr !== "undefined") {
|
|
246
262
|
const response = await apiCall({
|
|
247
263
|
method: "GET",
|
|
248
264
|
path: "/auth/authenticated",
|
|
249
265
|
timeout: 10000,
|
|
250
266
|
});
|
|
251
|
-
|
|
267
|
+
if (!response.data.authenticated) return false;
|
|
268
|
+
const decoded = jwtDecode(jwtStr);
|
|
269
|
+
if (decoded.exp && decoded.exp - Date.now() / 1000 < 7 * 24 * 3600) {
|
|
270
|
+
await renewJwt();
|
|
271
|
+
}
|
|
272
|
+
return true;
|
|
252
273
|
} else return false;
|
|
253
274
|
}
|
package/src/init.js
CHANGED
|
@@ -211,10 +211,14 @@ const showErrorPage = async (error) => {
|
|
|
211
211
|
const onResume = async () => {
|
|
212
212
|
if (typeof saltcorn === "undefined") return;
|
|
213
213
|
const mobileConfig = saltcorn.data.state.getState().mobileConfig;
|
|
214
|
-
if (mobileConfig?.
|
|
214
|
+
if (mobileConfig?.jwt) {
|
|
215
215
|
const netStatus = await Network.getStatus();
|
|
216
216
|
mobileConfig.networkState = netStatus.connectionType;
|
|
217
|
-
if (
|
|
217
|
+
if (
|
|
218
|
+
mobileConfig.allowOfflineMode &&
|
|
219
|
+
mobileConfig.networkState === "none" &&
|
|
220
|
+
!mobileConfig.isOfflineMode
|
|
221
|
+
) {
|
|
218
222
|
try {
|
|
219
223
|
await startOfflineMode();
|
|
220
224
|
clearHistory();
|
|
@@ -222,14 +226,16 @@ const onResume = async () => {
|
|
|
222
226
|
} catch (error) {
|
|
223
227
|
await showErrorPage(error);
|
|
224
228
|
}
|
|
225
|
-
} else if (
|
|
226
|
-
mobileConfig.
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
229
|
+
} else if (mobileConfig.networkState !== "none") {
|
|
230
|
+
if (!mobileConfig.isOfflineMode && !isPublicJwt(mobileConfig.jwt)) {
|
|
231
|
+
await checkJWT(mobileConfig.jwt);
|
|
232
|
+
}
|
|
233
|
+
if (mobileConfig.allowOfflineMode && mobileConfig.syncOnAppResume) {
|
|
234
|
+
try {
|
|
235
|
+
await sync(false, false, []);
|
|
236
|
+
} catch (error) {
|
|
237
|
+
await showErrorPage(error);
|
|
238
|
+
}
|
|
233
239
|
}
|
|
234
240
|
}
|
|
235
241
|
}
|