2017-06-29 12:54:02 -06:00
|
|
|
import { AuthState } from "./auth/interfaces";
|
|
|
|
import { box } from "boxed_value";
|
2017-08-25 09:32:38 -06:00
|
|
|
import { BooleanSetting, NumericSetting } from "./session_keys";
|
2019-09-23 12:56:35 -06:00
|
|
|
import {
|
2020-02-28 09:35:32 -07:00
|
|
|
BooleanConfigKey, NumberConfigKey,
|
2019-09-23 12:56:35 -06:00
|
|
|
} from "farmbot/dist/resources/configs/web_app";
|
2017-06-29 12:54:02 -06:00
|
|
|
|
2017-08-27 09:19:23 -06:00
|
|
|
/** The `Session` namespace is a wrapper for `localStorage`.
|
|
|
|
* Use this to avoid direct access of `localStorage` where possible.
|
|
|
|
*
|
|
|
|
* Problems this namespace aims to solve:
|
|
|
|
* - Avoid duplication of localStorage key names.
|
|
|
|
* - Avoid duplication of de-serialization logic.
|
|
|
|
* - Avoid type errors by explicitly naming keys as (Boolean|Numeric)Setting
|
|
|
|
* - Create an upgrade path for the eventual server side storage
|
|
|
|
*/
|
2017-06-29 12:54:02 -06:00
|
|
|
export namespace Session {
|
2017-08-27 09:19:23 -06:00
|
|
|
/** Key that holds the user's JWT */
|
2017-06-29 12:54:02 -06:00
|
|
|
const KEY = "session";
|
|
|
|
|
|
|
|
/** Replace the contents of session storage. */
|
2017-10-12 14:28:19 -06:00
|
|
|
export function replaceToken(nextState: AuthState) {
|
2018-08-02 16:18:54 -06:00
|
|
|
localStorage.setItem(KEY, JSON.stringify(nextState));
|
2017-06-29 12:54:02 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
/** Fetch the previous session. */
|
2017-10-12 14:28:19 -06:00
|
|
|
export function fetchStoredToken(): AuthState | undefined {
|
2017-06-29 12:54:02 -06:00
|
|
|
try {
|
2018-08-02 16:18:54 -06:00
|
|
|
const v: AuthState = JSON.parse(localStorage.getItem(KEY) || "");
|
2017-06-29 12:54:02 -06:00
|
|
|
if (box(v).kind === "object") {
|
|
|
|
return v;
|
|
|
|
} else {
|
2018-05-15 20:38:52 -06:00
|
|
|
throw new Error("Expected object or undefined"); // unreachable?
|
2017-06-29 12:54:02 -06:00
|
|
|
}
|
|
|
|
} catch (error) {
|
|
|
|
return undefined;
|
2017-08-02 09:14:08 -06:00
|
|
|
}
|
2017-06-29 12:54:02 -06:00
|
|
|
}
|
|
|
|
|
2018-12-18 11:25:17 -07:00
|
|
|
/** Clear localStorage and sessionStorage. */
|
2017-10-12 15:48:41 -06:00
|
|
|
export function clear(): never {
|
2019-02-04 09:31:52 -07:00
|
|
|
localStorage.clear();
|
|
|
|
sessionStorage.clear();
|
|
|
|
location.assign(window.location.origin || "/");
|
|
|
|
return undefined as never;
|
2017-06-29 12:54:02 -06:00
|
|
|
}
|
|
|
|
}
|
2017-08-30 15:18:44 -06:00
|
|
|
|
2017-12-27 09:24:50 -07:00
|
|
|
export const isBooleanSetting =
|
2018-09-18 12:35:43 -06:00
|
|
|
(k: unknown): k is BooleanConfigKey => !!BooleanSetting[k as BooleanConfigKey];
|
2017-08-30 15:18:44 -06:00
|
|
|
|
2020-02-28 09:34:28 -07:00
|
|
|
export function safeBooleanSetting(settingName: string): BooleanConfigKey {
|
|
|
|
if (isBooleanSetting(settingName)) {
|
|
|
|
return settingName;
|
2017-08-30 15:18:44 -06:00
|
|
|
} else {
|
2020-02-28 09:34:28 -07:00
|
|
|
throw new Error(`Expected BooleanConfigKey but got '${settingName}'`);
|
2017-08-30 15:18:44 -06:00
|
|
|
}
|
|
|
|
}
|
2017-12-11 04:50:41 -07:00
|
|
|
|
2017-12-27 09:24:50 -07:00
|
|
|
export const isNumericSetting =
|
2018-11-06 09:33:24 -07:00
|
|
|
(x: unknown): x is NumberConfigKey => !!NumericSetting[x as NumberConfigKey];
|
2017-12-11 04:50:41 -07:00
|
|
|
|
2020-02-28 09:34:28 -07:00
|
|
|
export function safeNumericSetting(settingName: string): NumberConfigKey {
|
|
|
|
if (isNumericSetting(settingName)) {
|
|
|
|
return settingName;
|
2017-12-11 04:50:41 -07:00
|
|
|
} else {
|
2020-02-28 09:34:28 -07:00
|
|
|
throw new Error(`Expected NumberConfigKey but got '${settingName}'`);
|
2017-12-11 04:50:41 -07:00
|
|
|
}
|
|
|
|
}
|