code refactor

This commit is contained in:
MaysWind
2025-01-05 21:39:39 +08:00
parent 49f1f3c86b
commit 6dc0ebcac6
22 changed files with 279 additions and 229 deletions
+3 -2
View File
@@ -30,6 +30,7 @@ import { APPLICATION_LOGO_PATH } from '@/consts/asset.ts';
import { ThemeType } from '@/core/theme.ts'; import { ThemeType } from '@/core/theme.ts';
import { isProduction } from '@/lib/version.ts'; import { isProduction } from '@/lib/version.ts';
import { initMapProvider } from '@/lib/map/index.ts'; import { initMapProvider } from '@/lib/map/index.ts';
import { isUserLogined, isUserUnlocked } from '@/lib/userstate.ts';
import { getSystemTheme, setExpenseAndIncomeAmountColor } from '@/lib/ui/common.ts'; import { getSystemTheme, setExpenseAndIncomeAmountColor } from '@/lib/ui/common.ts';
export default { export default {
@@ -79,8 +80,8 @@ export default {
setExpenseAndIncomeAmountColor(self.userStore.currentUserExpenseAmountColor, self.userStore.currentUserIncomeAmountColor); setExpenseAndIncomeAmountColor(self.userStore.currentUserExpenseAmountColor, self.userStore.currentUserIncomeAmountColor);
if (self.$user.isUserLogined()) { if (isUserLogined()) {
if (!self.settingsStore.appSettings.applicationLock || self.$user.isUserUnlocked()) { if (!self.settingsStore.appSettings.applicationLock || isUserUnlocked()) {
// refresh token if user is logined // refresh token if user is logined
self.tokensStore.refreshTokenAndRevokeOldToken().then(response => { self.tokensStore.refreshTokenAndRevokeOldToken().then(response => {
if (response.user) { if (response.user) {
+3 -2
View File
@@ -20,6 +20,7 @@ import { ThemeType } from '@/core/theme.ts';
import { isProduction } from '@/lib/version.ts'; import { isProduction } from '@/lib/version.ts';
import { getTheme, isEnableAnimate } from '@/lib/settings.ts'; import { getTheme, isEnableAnimate } from '@/lib/settings.ts';
import { initMapProvider } from '@/lib/map/index.ts'; import { initMapProvider } from '@/lib/map/index.ts';
import { isUserLogined, isUserUnlocked } from '@/lib/userstate.ts';
import { setExpenseAndIncomeAmountColor } from '@/lib/ui/common.ts'; import { setExpenseAndIncomeAmountColor } from '@/lib/ui/common.ts';
import { isModalShowing, setAppFontSize } from '@/lib/ui/mobile.js'; import { isModalShowing, setAppFontSize } from '@/lib/ui/mobile.js';
@@ -135,8 +136,8 @@ export default {
setExpenseAndIncomeAmountColor(self.userStore.currentUserExpenseAmountColor, self.userStore.currentUserIncomeAmountColor); setExpenseAndIncomeAmountColor(self.userStore.currentUserExpenseAmountColor, self.userStore.currentUserIncomeAmountColor);
if (self.$user.isUserLogined()) { if (isUserLogined()) {
if (!self.settingsStore.appSettings.applicationLock || self.$user.isUserUnlocked()) { if (!self.settingsStore.appSettings.applicationLock || isUserUnlocked()) {
// refresh token if user is logined // refresh token if user is logined
self.tokensStore.refreshTokenAndRevokeOldToken().then(response => { self.tokensStore.refreshTokenAndRevokeOldToken().then(response => {
if (response.user) { if (response.user) {
-3
View File
@@ -71,7 +71,6 @@ import draggable from 'vuedraggable';
import router from '@/router/desktop.js'; import router from '@/router/desktop.js';
import { getVersion, getBuildTime } from '@/lib/version.ts'; import { getVersion, getBuildTime } from '@/lib/version.ts';
import userstate from '@/lib/userstate.ts';
import { import {
getI18nOptions, getI18nOptions,
translateIf, translateIf,
@@ -477,6 +476,4 @@ app.config.globalProperties.$locale = i18nFunctions(i18n.global);
app.config.globalProperties.$tIf = (text, isTranslate) => translateIf(text, isTranslate, i18n.global.t); app.config.globalProperties.$tIf = (text, isTranslate) => translateIf(text, isTranslate, i18n.global.t);
app.config.globalProperties.$tError = (message) => translateError(message, i18n.global.t); app.config.globalProperties.$tError = (message) => translateError(message, i18n.global.t);
app.config.globalProperties.$user = userstate;
app.mount('#app'); app.mount('#app');
+10 -7
View File
@@ -109,7 +109,10 @@ import type {
UserProfileUpdateResponse UserProfileUpdateResponse
} from '@/models/user.ts'; } from '@/models/user.ts';
import userState from './userstate.ts'; import {
getCurrentToken,
clearCurrentTokenAndUserInfo
} from './userstate.ts';
import { import {
isDefined, isDefined,
@@ -145,7 +148,7 @@ const blockedRequests: ((token: string | undefined) => void)[] = [];
axios.defaults.baseURL = BASE_API_URL_PATH; axios.defaults.baseURL = BASE_API_URL_PATH;
axios.defaults.timeout = DEFAULT_API_TIMEOUT; axios.defaults.timeout = DEFAULT_API_TIMEOUT;
axios.interceptors.request.use((config: ApiRequestConfig) => { axios.interceptors.request.use((config: ApiRequestConfig) => {
const token = userState.getToken(); const token = getCurrentToken();
if (token && !config.noAuth) { if (token && !config.noAuth) {
config.headers.Authorization = `Bearer ${token}`; config.headers.Authorization = `Bearer ${token}`;
@@ -184,7 +187,7 @@ axios.interceptors.response.use(response => {
|| errorCode === 202006 // current token does not require two-factor authorization || errorCode === 202006 // current token does not require two-factor authorization
|| errorCode === 202012 // token is empty || errorCode === 202012 // token is empty
) { ) {
userState.clearTokenAndUserInfo(false); clearCurrentTokenAndUserInfo(false);
location.reload(); location.reload();
return Promise.reject({ processed: true }); return Promise.reject({ processed: true });
} }
@@ -521,7 +524,7 @@ export default {
return `${BASE_QRCODE_PATH}/${qrCodeName}.png`; return `${BASE_QRCODE_PATH}/${qrCodeName}.png`;
}, },
generateMapProxyTileImageUrl: (mapProvider: string, language: string): string => { generateMapProxyTileImageUrl: (mapProvider: string, language: string): string => {
const token = userState.getToken(); const token = getCurrentToken();
let url = `${BASE_PROXY_URL_PATH}/map/tile/{z}/{x}/{y}.png?provider=${mapProvider}&token=${token}`; let url = `${BASE_PROXY_URL_PATH}/map/tile/{z}/{x}/{y}.png?provider=${mapProvider}&token=${token}`;
if (language) { if (language) {
@@ -531,7 +534,7 @@ export default {
return url; return url;
}, },
generateMapProxyAnnotationImageUrl: (mapProvider: string, language: string): string => { generateMapProxyAnnotationImageUrl: (mapProvider: string, language: string): string => {
const token = userState.getToken(); const token = getCurrentToken();
let url = `${BASE_PROXY_URL_PATH}/map/annotation/{z}/{x}/{y}.png?provider=${mapProvider}&token=${token}`; let url = `${BASE_PROXY_URL_PATH}/map/annotation/{z}/{x}/{y}.png?provider=${mapProvider}&token=${token}`;
if (language) { if (language) {
@@ -564,7 +567,7 @@ export default {
} }
const params = []; const params = [];
params.push('token=' + userState.getToken()); params.push('token=' + getCurrentToken());
if (disableBrowserCache) { if (disableBrowserCache) {
if (isBoolean(disableBrowserCache)) { if (isBoolean(disableBrowserCache)) {
@@ -586,7 +589,7 @@ export default {
} }
const params = []; const params = [];
params.push('token=' + userState.getToken()); params.push('token=' + getCurrentToken());
if (disableBrowserCache) { if (disableBrowserCache) {
if (isBoolean(disableBrowserCache)) { if (isBoolean(disableBrowserCache)) {
+134 -131
View File
@@ -34,80 +34,11 @@ function getDecryptedToken(encryptedToken: string, appLockState: ApplicationLock
return bytes.toString(CryptoJS.enc.Utf8); return bytes.toString(CryptoJS.enc.Utf8);
} }
function getToken(): string | null { export function isUserLogined(): boolean {
if (isEnableApplicationLock()) {
const usedEncryptedToken = sessionStorage.getItem(encryptedTokenSessionStorageKey);
const currentEncryptedToken = localStorage.getItem(tokenLocalStorageKey);
if (!usedEncryptedToken || !currentEncryptedToken) {
return null;
}
if (usedEncryptedToken === currentEncryptedToken) {
return sessionStorage.getItem(tokenSessionStorageKey);
}
// re-decrypt token
logger.warn(`encrypted token in local storage does not equal to the one in session storage, need to re-decrypt`);
const appLockState = getUserAppLockState();
const token = getDecryptedToken(currentEncryptedToken, appLockState);
sessionStorage.setItem(encryptedTokenSessionStorageKey, currentEncryptedToken);
sessionStorage.setItem(tokenSessionStorageKey, token);
return token;
} else {
return localStorage.getItem(tokenLocalStorageKey);
}
}
function getUserInfo(): UserBasicInfo | null {
const data = localStorage.getItem(userInfoLocalStorageKey);
if (!data) {
return null;
}
return JSON.parse(data) as UserBasicInfo;
}
function getUserTransactionDraft(): unknown | null {
let data = localStorage.getItem(transactionDraftLocalStorageKey);
if (!data) {
return null;
}
if (isEnableApplicationLock()) {
const appLockState = getUserAppLockState();
data = getDecryptedToken(data, appLockState);
}
return JSON.parse(data);
}
function getUserAppLockState(): ApplicationLockState {
const data = sessionStorage.getItem(appLockStateSessionStorageKey);
if (!data) {
throw new Error('No app lock state in session storage');
}
const appLockState = JSON.parse(data);
if (!appLockState || !appLockState.username || !appLockState.secret) {
throw new Error('App lock state is invalid');
}
return appLockState as ApplicationLockState;
}
function isUserLogined(): boolean {
return !!localStorage.getItem(tokenLocalStorageKey); return !!localStorage.getItem(tokenLocalStorageKey);
} }
function isUserUnlocked(): boolean { export function isUserUnlocked(): boolean {
if (!isUserLogined()) { if (!isUserLogined()) {
return false; return false;
} }
@@ -119,31 +50,27 @@ function isUserUnlocked(): boolean {
return !!sessionStorage.getItem(appLockStateSessionStorageKey) && !!sessionStorage.getItem(tokenSessionStorageKey); return !!sessionStorage.getItem(appLockStateSessionStorageKey) && !!sessionStorage.getItem(tokenSessionStorageKey);
} }
function getWebAuthnCredentialId(): string | undefined { export function hasUserAppLockState(): boolean {
const webauthnConfigData = localStorage.getItem(webauthnConfigLocalStorageKey); return !!getUserAppLockState();
}
if (!webauthnConfigData) { export function getUserAppLockState(): ApplicationLockState | null {
return undefined; const data = sessionStorage.getItem(appLockStateSessionStorageKey);
if (!data) {
return null;
} }
const webauthnConfig = JSON.parse(webauthnConfigData) as WebAuthnConfig; const appLockState = JSON.parse(data);
return webauthnConfig.credentialId; if (!appLockState || !appLockState.username || !appLockState.secret) {
return null;
}
return appLockState as ApplicationLockState;
} }
function saveWebAuthnConfig(credentialId: string): void { export function unlockTokenByWebAuthn(credentialId: string, userName: string, userSecret: string): void {
const webAuthnConfig: WebAuthnConfig = {
credentialId: credentialId
};
localStorage.setItem(webauthnConfigLocalStorageKey, JSON.stringify(webAuthnConfig));
}
function clearWebAuthnConfig(): void {
localStorage.removeItem(webauthnConfigLocalStorageKey);
}
function unlockTokenByWebAuthn(credentialId: string, userName: string, userSecret: string): void {
const webauthnConfigData = localStorage.getItem(webauthnConfigLocalStorageKey); const webauthnConfigData = localStorage.getItem(webauthnConfigLocalStorageKey);
if (!webauthnConfigData) { if (!webauthnConfigData) {
@@ -173,7 +100,7 @@ function unlockTokenByWebAuthn(credentialId: string, userName: string, userSecre
sessionStorage.setItem(tokenSessionStorageKey, token); sessionStorage.setItem(tokenSessionStorageKey, token);
} }
function unlockTokenByPinCode(userName: string, pinCode: string): void { export function unlockTokenByPinCode(userName: string, pinCode: string): void {
const encryptedToken = localStorage.getItem(tokenLocalStorageKey); const encryptedToken = localStorage.getItem(tokenLocalStorageKey);
if (!encryptedToken) { if (!encryptedToken) {
@@ -191,7 +118,7 @@ function unlockTokenByPinCode(userName: string, pinCode: string): void {
sessionStorage.setItem(tokenSessionStorageKey, token); sessionStorage.setItem(tokenSessionStorageKey, token);
} }
function encryptToken(userName: string, pinCode: string): void { export function encryptToken(userName: string, pinCode: string): void {
const token = localStorage.getItem(tokenLocalStorageKey); const token = localStorage.getItem(tokenLocalStorageKey);
if (!token) { if (!token) {
@@ -210,7 +137,7 @@ function encryptToken(userName: string, pinCode: string): void {
localStorage.setItem(tokenLocalStorageKey, encryptedToken); localStorage.setItem(tokenLocalStorageKey, encryptedToken);
} }
function decryptToken(): void { export function decryptToken(): void {
const token = sessionStorage.getItem(tokenSessionStorageKey); const token = sessionStorage.getItem(tokenSessionStorageKey);
if (!token) { if (!token) {
@@ -223,18 +150,55 @@ function decryptToken(): void {
sessionStorage.removeItem(appLockStateSessionStorageKey); sessionStorage.removeItem(appLockStateSessionStorageKey);
} }
function isCorrectPinCode(pinCode: string): boolean { export function isCorrectPinCode(pinCode: string): boolean {
const secret = getAppLockSecret(pinCode); const secret = getAppLockSecret(pinCode);
const appLockState = getUserAppLockState(); const appLockState = getUserAppLockState();
if (!appLockState) {
return false;
}
return appLockState && secret === appLockState.secret; return appLockState && secret === appLockState.secret;
} }
function updateToken(token: string): void { export function getCurrentToken(): string | null {
if (isEnableApplicationLock()) {
const usedEncryptedToken = sessionStorage.getItem(encryptedTokenSessionStorageKey);
const currentEncryptedToken = localStorage.getItem(tokenLocalStorageKey);
if (!usedEncryptedToken || !currentEncryptedToken) {
return null;
}
if (usedEncryptedToken === currentEncryptedToken) {
return sessionStorage.getItem(tokenSessionStorageKey);
}
// re-decrypt token
logger.warn(`encrypted token in local storage does not equal to the one in session storage, need to re-decrypt`);
const appLockState = getUserAppLockState();
if (!appLockState) {
return null;
}
const token = getDecryptedToken(currentEncryptedToken, appLockState);
sessionStorage.setItem(encryptedTokenSessionStorageKey, currentEncryptedToken);
sessionStorage.setItem(tokenSessionStorageKey, token);
return token;
} else {
return localStorage.getItem(tokenLocalStorageKey);
}
}
export function updateCurrentToken(token: string): void {
if (isString(token)) { if (isString(token)) {
if (isEnableApplicationLock()) { if (isEnableApplicationLock() && hasUserAppLockState()) {
const appLockState = getUserAppLockState(); const appLockState = getUserAppLockState();
const encryptedToken = getEncryptedToken(token, appLockState); const encryptedToken = getEncryptedToken(token, appLockState as ApplicationLockState);
sessionStorage.setItem(encryptedTokenSessionStorageKey, encryptedToken); sessionStorage.setItem(encryptedTokenSessionStorageKey, encryptedToken);
sessionStorage.setItem(tokenSessionStorageKey, token); sessionStorage.setItem(tokenSessionStorageKey, token);
@@ -245,13 +209,75 @@ function updateToken(token: string): void {
} }
} }
function updateUserInfo(user: UserBasicInfo): void { export function hasWebAuthnConfig(): boolean {
return !!getWebAuthnCredentialId();
}
export function getWebAuthnCredentialId(): string | undefined {
const webauthnConfigData = localStorage.getItem(webauthnConfigLocalStorageKey);
if (!webauthnConfigData) {
return undefined;
}
const webauthnConfig = JSON.parse(webauthnConfigData) as WebAuthnConfig;
return webauthnConfig.credentialId;
}
export function saveWebAuthnConfig(credentialId: string): void {
const webAuthnConfig: WebAuthnConfig = {
credentialId: credentialId
};
localStorage.setItem(webauthnConfigLocalStorageKey, JSON.stringify(webAuthnConfig));
}
export function clearWebAuthnConfig(): void {
localStorage.removeItem(webauthnConfigLocalStorageKey);
}
export function getCurrentUserInfo(): UserBasicInfo | null {
const data = localStorage.getItem(userInfoLocalStorageKey);
if (!data) {
return null;
}
return JSON.parse(data) as UserBasicInfo;
}
export function updateCurrentUserInfo(user: UserBasicInfo): void {
if (isObject(user)) { if (isObject(user)) {
localStorage.setItem(userInfoLocalStorageKey, JSON.stringify(user)); localStorage.setItem(userInfoLocalStorageKey, JSON.stringify(user));
} }
} }
function updateUserTransactionDraft(transaction: unknown): void { export function clearCurrentUserInfo(): void {
localStorage.removeItem(userInfoLocalStorageKey);
}
export function getUserTransactionDraft(): unknown | null {
let data = localStorage.getItem(transactionDraftLocalStorageKey);
if (!data) {
return null;
}
if (isEnableApplicationLock()) {
const appLockState = getUserAppLockState();
if (!appLockState) {
return null;
}
data = getDecryptedToken(data, appLockState);
}
return JSON.parse(data);
}
export function updateUserTransactionDraft(transaction: unknown): void {
if (!isObject(transaction)) { if (!isObject(transaction)) {
return; return;
} }
@@ -260,27 +286,28 @@ function updateUserTransactionDraft(transaction: unknown): void {
if (isEnableApplicationLock()) { if (isEnableApplicationLock()) {
const appLockState = getUserAppLockState(); const appLockState = getUserAppLockState();
if (!appLockState) {
return;
}
data = getEncryptedToken(data, appLockState); data = getEncryptedToken(data, appLockState);
} }
localStorage.setItem(transactionDraftLocalStorageKey, data); localStorage.setItem(transactionDraftLocalStorageKey, data);
} }
function clearUserInfo(): void { export function clearUserTransactionDraft(): void {
localStorage.removeItem(userInfoLocalStorageKey);
}
function clearUserTransactionDraft(): void {
localStorage.removeItem(transactionDraftLocalStorageKey); localStorage.removeItem(transactionDraftLocalStorageKey);
} }
function clearSessionToken(): void { export function clearCurrentSessionToken(): void {
sessionStorage.removeItem(tokenSessionStorageKey); sessionStorage.removeItem(tokenSessionStorageKey);
sessionStorage.removeItem(encryptedTokenSessionStorageKey); sessionStorage.removeItem(encryptedTokenSessionStorageKey);
sessionStorage.removeItem(appLockStateSessionStorageKey); sessionStorage.removeItem(appLockStateSessionStorageKey);
} }
function clearTokenAndUserInfo(clearAppLockState: boolean): void { export function clearCurrentTokenAndUserInfo(clearAppLockState: boolean): void {
if (clearAppLockState) { if (clearAppLockState) {
sessionStorage.removeItem(appLockStateSessionStorageKey); sessionStorage.removeItem(appLockStateSessionStorageKey);
} }
@@ -289,29 +316,5 @@ function clearTokenAndUserInfo(clearAppLockState: boolean): void {
sessionStorage.removeItem(encryptedTokenSessionStorageKey); sessionStorage.removeItem(encryptedTokenSessionStorageKey);
localStorage.removeItem(tokenLocalStorageKey); localStorage.removeItem(tokenLocalStorageKey);
clearUserTransactionDraft(); clearUserTransactionDraft();
clearUserInfo(); clearCurrentUserInfo();
} }
export default {
getToken,
getUserInfo,
getUserTransactionDraft,
getUserAppLockState,
isUserLogined,
isUserUnlocked,
getWebAuthnCredentialId,
saveWebAuthnConfig,
clearWebAuthnConfig,
unlockTokenByWebAuthn,
unlockTokenByPinCode,
encryptToken,
decryptToken,
isCorrectPinCode,
updateToken,
updateUserTransactionDraft,
updateUserInfo,
clearUserInfo,
clearUserTransactionDraft,
clearSessionToken,
clearTokenAndUserInfo
};
-3
View File
@@ -80,7 +80,6 @@ import VueDatePicker from '@vuepic/vue-datepicker';
import '@vuepic/vue-datepicker/dist/main.css'; import '@vuepic/vue-datepicker/dist/main.css';
import { getVersion, getBuildTime } from '@/lib/version.ts'; import { getVersion, getBuildTime } from '@/lib/version.ts';
import userstate from '@/lib/userstate.ts';
import { import {
getI18nOptions, getI18nOptions,
translateIf, translateIf,
@@ -216,6 +215,4 @@ app.config.globalProperties.$showLoading = showLoading;
app.config.globalProperties.$hideLoading = hideLoading; app.config.globalProperties.$hideLoading = hideLoading;
app.config.globalProperties.$routeBackOnError = routeBackOnError; app.config.globalProperties.$routeBackOnError = routeBackOnError;
app.config.globalProperties.$user = userstate;
app.mount('#app'); app.mount('#app');
+7 -7
View File
@@ -1,7 +1,7 @@
import { createRouter, createWebHashHistory } from 'vue-router'; import { createRouter, createWebHashHistory } from 'vue-router';
import { TemplateType } from '@/core/template.ts'; import { TemplateType } from '@/core/template.ts';
import userState from '@/lib/userstate.ts'; import { isUserLogined, isUserUnlocked } from '@/lib/userstate.ts';
import MainLayout from '@/views/desktop/MainLayout.vue'; import MainLayout from '@/views/desktop/MainLayout.vue';
import LoginPage from '@/views/desktop/LoginPage.vue'; import LoginPage from '@/views/desktop/LoginPage.vue';
@@ -32,14 +32,14 @@ import ExchangeRatesPage from '@/views/desktop/ExchangeRatesPage.vue';
import AboutPage from '@/views/desktop/AboutPage.vue'; import AboutPage from '@/views/desktop/AboutPage.vue';
function checkLogin() { function checkLogin() {
if (!userState.isUserLogined()) { if (!isUserLogined()) {
return { return {
path: '/login', path: '/login',
replace: true replace: true
}; };
} }
if (!userState.isUserUnlocked()) { if (!isUserUnlocked()) {
return { return {
path: '/unlock', path: '/unlock',
replace: true replace: true
@@ -48,14 +48,14 @@ function checkLogin() {
} }
function checkLocked() { function checkLocked() {
if (!userState.isUserLogined()) { if (!isUserLogined()) {
return { return {
path: '/login', path: '/login',
replace: true replace: true
}; };
} }
if (userState.isUserUnlocked()) { if (isUserUnlocked()) {
return { return {
path: '/', path: '/',
replace: true replace: true
@@ -64,14 +64,14 @@ function checkLocked() {
} }
function checkNotLogin() { function checkNotLogin() {
if (userState.isUserLogined() && !userState.isUserUnlocked()) { if (isUserLogined() && !isUserUnlocked()) {
return { return {
path: '/unlock', path: '/unlock',
replace: true replace: true
}; };
} }
if (userState.isUserLogined()) { if (isUserLogined()) {
return { return {
path: '/', path: '/',
replace: true replace: true
+7 -7
View File
@@ -1,4 +1,4 @@
import userState from '@/lib/userstate.ts'; import { isUserLogined, isUserUnlocked } from '@/lib/userstate.ts';
import HomePage from '@/views/mobile/HomePage.vue'; import HomePage from '@/views/mobile/HomePage.vue';
import LoginPage from '@/views/mobile/LoginPage.vue'; import LoginPage from '@/views/mobile/LoginPage.vue';
@@ -49,7 +49,7 @@ function asyncResolve(component) {
} }
function checkLogin({ router, resolve, reject }) { function checkLogin({ router, resolve, reject }) {
if (!userState.isUserLogined()) { if (!isUserLogined()) {
reject(); reject();
router.navigate('/login', { router.navigate('/login', {
clearPreviousHistory: true, clearPreviousHistory: true,
@@ -58,7 +58,7 @@ function checkLogin({ router, resolve, reject }) {
return; return;
} }
if (!userState.isUserUnlocked()) { if (!isUserUnlocked()) {
reject(); reject();
router.navigate('/unlock', { router.navigate('/unlock', {
clearPreviousHistory: true, clearPreviousHistory: true,
@@ -71,7 +71,7 @@ function checkLogin({ router, resolve, reject }) {
} }
function checkLocked({ router, resolve, reject }) { function checkLocked({ router, resolve, reject }) {
if (!userState.isUserLogined()) { if (!isUserLogined()) {
reject(); reject();
router.navigate('/login', { router.navigate('/login', {
clearPreviousHistory: true, clearPreviousHistory: true,
@@ -80,7 +80,7 @@ function checkLocked({ router, resolve, reject }) {
return; return;
} }
if (userState.isUserUnlocked()) { if (isUserUnlocked()) {
reject(); reject();
router.navigate('/', { router.navigate('/', {
clearPreviousHistory: true, clearPreviousHistory: true,
@@ -93,7 +93,7 @@ function checkLocked({ router, resolve, reject }) {
} }
function checkNotLogin({ router, resolve, reject }) { function checkNotLogin({ router, resolve, reject }) {
if (userState.isUserLogined() && !userState.isUserUnlocked()) { if (isUserLogined() && !isUserUnlocked()) {
reject(); reject();
router.navigate('/unlock', { router.navigate('/unlock', {
clearPreviousHistory: true, clearPreviousHistory: true,
@@ -102,7 +102,7 @@ function checkNotLogin({ router, resolve, reject }) {
return; return;
} }
if (userState.isUserLogined()) { if (isUserLogined()) {
reject(); reject();
router.navigate('/', { router.navigate('/', {
clearPreviousHistory: true, clearPreviousHistory: true,
+27 -20
View File
@@ -11,7 +11,14 @@ import { useOverviewStore } from './overview.js';
import { useStatisticsStore } from './statistics.js'; import { useStatisticsStore } from './statistics.js';
import { useExchangeRatesStore } from './exchangeRates.js'; import { useExchangeRatesStore } from './exchangeRates.js';
import userState from '@/lib/userstate.ts'; import {
hasUserAppLockState,
getUserAppLockState,
updateCurrentToken,
clearWebAuthnConfig,
clearCurrentSessionToken,
clearCurrentTokenAndUserInfo
} from '@/lib/userstate.ts';
import services from '@/lib/services.ts'; import services from '@/lib/services.ts';
import logger from '@/lib/logger.ts'; import logger from '@/lib/logger.ts';
import { isObject, isString } from '@/lib/common.ts'; import { isObject, isString } from '@/lib/common.ts';
@@ -75,18 +82,18 @@ export const useRootStore = defineStore('root', {
return; return;
} }
if (settingsStore.appSettings.applicationLock || userState.getUserAppLockState()) { if (settingsStore.appSettings.applicationLock || hasUserAppLockState()) {
const appLockState = userState.getUserAppLockState(); const appLockState = getUserAppLockState();
if (!appLockState || appLockState.username !== data.result.user.username) { if (!appLockState || appLockState.username !== data.result.user.username) {
userState.clearTokenAndUserInfo(true); clearCurrentTokenAndUserInfo(true);
settingsStore.setEnableApplicationLock(false); settingsStore.setEnableApplicationLock(false);
settingsStore.setEnableApplicationLockWebAuthn(false); settingsStore.setEnableApplicationLockWebAuthn(false);
userState.clearWebAuthnConfig(); clearWebAuthnConfig();
} }
} }
userState.updateToken(data.result.token); updateCurrentToken(data.result.token);
if (data.result.user && isObject(data.result.user)) { if (data.result.user && isObject(data.result.user)) {
const userStore = useUserStore(); const userStore = useUserStore();
@@ -136,18 +143,18 @@ export const useRootStore = defineStore('root', {
return; return;
} }
if (settingsStore.appSettings.applicationLock || userState.getUserAppLockState()) { if (settingsStore.appSettings.applicationLock || hasUserAppLockState()) {
const appLockState = userState.getUserAppLockState(); const appLockState = getUserAppLockState();
if (!appLockState || appLockState.username !== data.result.user.username) { if (!appLockState || appLockState.username !== data.result.user.username) {
userState.clearTokenAndUserInfo(true); clearCurrentTokenAndUserInfo(true);
settingsStore.setEnableApplicationLock(false); settingsStore.setEnableApplicationLock(false);
settingsStore.setEnableApplicationLockWebAuthn(false); settingsStore.setEnableApplicationLockWebAuthn(false);
userState.clearWebAuthnConfig(); clearWebAuthnConfig();
} }
} }
userState.updateToken(data.result.token); updateCurrentToken(data.result.token);
if (data.result.user && isObject(data.result.user)) { if (data.result.user && isObject(data.result.user)) {
const userStore = useUserStore(); const userStore = useUserStore();
@@ -192,11 +199,11 @@ export const useRootStore = defineStore('root', {
if (settingsStore.appSettings.applicationLock) { if (settingsStore.appSettings.applicationLock) {
settingsStore.setEnableApplicationLock(false); settingsStore.setEnableApplicationLock(false);
settingsStore.setEnableApplicationLockWebAuthn(false); settingsStore.setEnableApplicationLockWebAuthn(false);
userState.clearWebAuthnConfig(); clearWebAuthnConfig();
} }
if (data.result.token && isString(data.result.token)) { if (data.result.token && isString(data.result.token)) {
userState.updateToken(data.result.token); updateCurrentToken(data.result.token);
} }
if (data.result.user && isObject(data.result.user)) { if (data.result.user && isObject(data.result.user)) {
@@ -219,7 +226,7 @@ export const useRootStore = defineStore('root', {
}); });
}, },
lock() { lock() {
userState.clearSessionToken(); clearCurrentSessionToken();
this.resetAllStates(false); this.resetAllStates(false);
}, },
logout() { logout() {
@@ -234,8 +241,8 @@ export const useRootStore = defineStore('root', {
return; return;
} }
userState.clearTokenAndUserInfo(true); clearCurrentTokenAndUserInfo(true);
userState.clearWebAuthnConfig(); clearWebAuthnConfig();
self.resetAllStates(true); self.resetAllStates(true);
resolve(data.result); resolve(data.result);
@@ -253,8 +260,8 @@ export const useRootStore = defineStore('root', {
}); });
}, },
forceLogout() { forceLogout() {
userState.clearTokenAndUserInfo(true); clearCurrentTokenAndUserInfo(true);
userState.clearWebAuthnConfig(); clearWebAuthnConfig();
this.resetAllStates(true); this.resetAllStates(true);
}, },
verifyEmail({ token, requestNewToken }) { verifyEmail({ token, requestNewToken }) {
@@ -271,7 +278,7 @@ export const useRootStore = defineStore('root', {
} }
if (data.result.newToken && isString(data.result.newToken)) { if (data.result.newToken && isString(data.result.newToken)) {
userState.updateToken(data.result.newToken); updateCurrentToken(data.result.newToken);
} }
if (data.result.user && isObject(data.result.user)) { if (data.result.user && isObject(data.result.user)) {
@@ -405,7 +412,7 @@ export const useRootStore = defineStore('root', {
} }
if (data.result.newToken && isString(data.result.newToken)) { if (data.result.newToken && isString(data.result.newToken)) {
userState.updateToken(data.result.newToken); updateCurrentToken(data.result.newToken);
} }
if (data.result.user && isObject(data.result.user)) { if (data.result.user && isObject(data.result.user)) {
+2 -2
View File
@@ -2,7 +2,7 @@ import { defineStore } from 'pinia';
import { useUserStore } from './user.js'; import { useUserStore } from './user.js';
import userState from '@/lib/userstate.ts'; import { updateCurrentToken } from '@/lib/userstate.ts';
import services from '@/lib/services.ts'; import services from '@/lib/services.ts';
import logger from '@/lib/logger.ts'; import logger from '@/lib/logger.ts';
import { isObject } from '@/lib/common.ts'; import { isObject } from '@/lib/common.ts';
@@ -46,7 +46,7 @@ export const useTokensStore = defineStore('tokens', {
} }
if (data && data.success && data.result && data.result.newToken) { if (data && data.success && data.result && data.result.newToken) {
userState.updateToken(data.result.newToken); updateCurrentToken(data.result.newToken);
if (data.result.oldTokenId) { if (data.result.oldTokenId) {
self.revokeToken({ self.revokeToken({
+9 -5
View File
@@ -12,7 +12,11 @@ import { DateRange } from '@/core/datetime.ts';
import { CategoryType } from '@/core/category.ts'; import { CategoryType } from '@/core/category.ts';
import { TransactionType, TransactionTagFilterType } from '@/core/transaction.ts'; import { TransactionType, TransactionTagFilterType } from '@/core/transaction.ts';
import { TRANSACTION_MIN_AMOUNT, TRANSACTION_MAX_AMOUNT } from '@/consts/transaction.ts'; import { TRANSACTION_MIN_AMOUNT, TRANSACTION_MAX_AMOUNT } from '@/consts/transaction.ts';
import userState from '@/lib/userstate.ts'; import {
getUserTransactionDraft,
updateUserTransactionDraft,
clearUserTransactionDraft
} from '@/lib/userstate.ts';
import services from '@/lib/services.ts'; import services from '@/lib/services.ts';
import logger from '@/lib/logger.ts'; import logger from '@/lib/logger.ts';
import { import {
@@ -366,7 +370,7 @@ function buildTransactionDraft(transaction) {
export const useTransactionsStore = defineStore('transactions', { export const useTransactionsStore = defineStore('transactions', {
state: () => ({ state: () => ({
transactionDraft: userState.getUserTransactionDraft(), transactionDraft: getUserTransactionDraft(),
transactionsFilter: { transactionsFilter: {
dateType: DateRange.All.type, dateType: DateRange.All.type,
maxTime: 0, maxTime: 0,
@@ -502,7 +506,7 @@ export const useTransactionsStore = defineStore('transactions', {
const settingsStore = useSettingsStore(); const settingsStore = useSettingsStore();
if (settingsStore.appSettings.autoSaveTransactionDraft === 'enabled' || settingsStore.appSettings.autoSaveTransactionDraft === 'confirmation') { if (settingsStore.appSettings.autoSaveTransactionDraft === 'enabled' || settingsStore.appSettings.autoSaveTransactionDraft === 'confirmation') {
this.transactionDraft = userState.getUserTransactionDraft(); this.transactionDraft = getUserTransactionDraft();
} else { } else {
this.transactionDraft = null; this.transactionDraft = null;
} }
@@ -590,11 +594,11 @@ export const useTransactionsStore = defineStore('transactions', {
this.transactionDraft = buildTransactionDraft(transaction); this.transactionDraft = buildTransactionDraft(transaction);
} }
userState.updateUserTransactionDraft(this.transactionDraft); updateUserTransactionDraft(this.transactionDraft);
}, },
clearTransactionDraft() { clearTransactionDraft() {
this.transactionDraft = null; this.transactionDraft = null;
userState.clearUserTransactionDraft(); clearUserTransactionDraft();
}, },
generateNewTransactionModel(type) { generateNewTransactionModel(type) {
const settingsStore = useSettingsStore(); const settingsStore = useSettingsStore();
+2 -2
View File
@@ -1,6 +1,6 @@
import { defineStore } from 'pinia'; import { defineStore } from 'pinia';
import userState from '@/lib/userstate.ts'; import { updateCurrentToken } from '@/lib/userstate.ts';
import services from '@/lib/services.ts'; import services from '@/lib/services.ts';
import logger from '@/lib/logger.ts'; import logger from '@/lib/logger.ts';
import { isBoolean } from '@/lib/common.ts'; import { isBoolean } from '@/lib/common.ts';
@@ -69,7 +69,7 @@ export const useTwoFactorAuthStore = defineStore('twoFactorAuth', {
} }
if (data.result.token) { if (data.result.token) {
userState.updateToken(data.result.token); updateCurrentToken(data.result.token);
} }
resolve(data.result); resolve(data.result);
+8 -4
View File
@@ -2,7 +2,11 @@ import { defineStore } from 'pinia';
import { useSettingsStore } from './setting.ts'; import { useSettingsStore } from './setting.ts';
import userState from '@/lib/userstate.ts'; import {
getCurrentUserInfo,
updateCurrentUserInfo,
clearCurrentUserInfo
} from '@/lib/userstate.ts';
import services from '@/lib/services.ts'; import services from '@/lib/services.ts';
import logger from '@/lib/logger.ts'; import logger from '@/lib/logger.ts';
import { import {
@@ -12,7 +16,7 @@ import {
export const useUserStore = defineStore('user', { export const useUserStore = defineStore('user', {
state: () => ({ state: () => ({
currentUserBasicInfo: userState.getUserInfo() currentUserBasicInfo: getCurrentUserInfo()
}), }),
getters: { getters: {
currentUserNickname(state) { currentUserNickname(state) {
@@ -99,11 +103,11 @@ export const useUserStore = defineStore('user', {
}, },
storeUserBasicInfo(userInfo) { storeUserBasicInfo(userInfo) {
this.currentUserBasicInfo = userInfo; this.currentUserBasicInfo = userInfo;
userState.updateUserInfo(userInfo); updateCurrentUserInfo(userInfo);
}, },
resetUserBasicInfo() { resetUserBasicInfo() {
this.currentUserBasicInfo = null; this.currentUserBasicInfo = null;
userState.clearUserInfo(); clearCurrentUserInfo();
}, },
getCurrentUserProfile() { getCurrentUserProfile() {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
+2 -1
View File
@@ -203,6 +203,7 @@ import {
getUnixTimeBeforeUnixTime, getUnixTimeBeforeUnixTime,
getUnixTimeAfterUnixTime getUnixTimeAfterUnixTime
} from '@/lib/datetime.ts'; } from '@/lib/datetime.ts';
import { isUserLogined, isUserUnlocked } from '@/lib/userstate.ts';
import { import {
mdiRefresh, mdiRefresh,
@@ -348,7 +349,7 @@ export default {
} }
}, },
created() { created() {
if (this.$user.isUserLogined() && this.$user.isUserUnlocked()) { if (isUserLogined() && isUserUnlocked()) {
this.reload(false); this.reload(false);
} }
}, },
+2 -1
View File
@@ -248,6 +248,7 @@ import { APPLICATION_LOGO_PATH } from '@/consts/asset.ts';
import { CategoryType } from '@/core/category.ts'; import { CategoryType } from '@/core/category.ts';
import { ThemeType } from '@/core/theme.ts'; import { ThemeType } from '@/core/theme.ts';
import { categorizedArrayToPlainArray } from '@/lib/common.ts'; import { categorizedArrayToPlainArray } from '@/lib/common.ts';
import { isUserLogined } from '@/lib/userstate.ts';
import { setExpenseAndIncomeAmountColor } from '@/lib/ui/common.ts'; import { setExpenseAndIncomeAmountColor } from '@/lib/ui/common.ts';
import { import {
@@ -436,7 +437,7 @@ export default {
user: self.user, user: self.user,
presetCategories: presetCategories presetCategories: presetCategories
}).then(response => { }).then(response => {
if (!self.$user.isUserLogined()) { if (!isUserLogined()) {
self.submitting = false; self.submitting = false;
if (self.usePresetCategories && !response.presetCategoriesSaved) { if (self.usePresetCategories && !response.presetCategoriesSaved) {
+11 -5
View File
@@ -121,6 +121,12 @@ import { APPLICATION_LOGO_PATH } from '@/consts/asset.ts';
import { ThemeType } from '@/core/theme.ts'; import { ThemeType } from '@/core/theme.ts';
import logger from '@/lib/logger.ts'; import logger from '@/lib/logger.ts';
import webauthn from '@/lib/webauthn.js'; import webauthn from '@/lib/webauthn.js';
import {
unlockTokenByWebAuthn,
unlockTokenByPinCode,
hasWebAuthnConfig,
getWebAuthnCredentialId
} from '@/lib/userstate.ts';
import { setExpenseAndIncomeAmountColor } from '@/lib/ui/common.ts'; import { setExpenseAndIncomeAmountColor } from '@/lib/ui/common.ts';
export default { export default {
@@ -143,7 +149,7 @@ export default {
}, },
isWebAuthnAvailable() { isWebAuthnAvailable() {
return this.settingsStore.appSettings.applicationLockWebAuthn return this.settingsStore.appSettings.applicationLockWebAuthn
&& this.$user.getWebAuthnCredentialId() && hasWebAuthnConfig()
&& webauthn.isSupported(); && webauthn.isSupported();
}, },
isDarkMode() { isDarkMode() {
@@ -164,7 +170,7 @@ export default {
unlockByWebAuthn() { unlockByWebAuthn() {
const self = this; const self = this;
if (!self.settingsStore.appSettings.applicationLockWebAuthn || !self.$user.getWebAuthnCredentialId()) { if (!self.settingsStore.appSettings.applicationLockWebAuthn || !hasWebAuthnConfig()) {
self.$refs.snackbar.showMessage('WebAuthn is not enabled'); self.$refs.snackbar.showMessage('WebAuthn is not enabled');
return; return;
} }
@@ -178,11 +184,11 @@ export default {
webauthn.verifyCredential( webauthn.verifyCredential(
self.userStore.currentUserBasicInfo, self.userStore.currentUserBasicInfo,
self.$user.getWebAuthnCredentialId() getWebAuthnCredentialId()
).then(({ id, userName, userSecret }) => { ).then(({ id, userName, userSecret }) => {
self.verifyingByWebAuthn = false; self.verifyingByWebAuthn = false;
self.$user.unlockTokenByWebAuthn(id, userName, userSecret); unlockTokenByWebAuthn(id, userName, userSecret);
self.transactionsStore.initTransactionDraft(); self.transactionsStore.initTransactionDraft();
self.tokensStore.refreshTokenAndRevokeOldToken().then(response => { self.tokensStore.refreshTokenAndRevokeOldToken().then(response => {
if (response.user) { if (response.user) {
@@ -232,7 +238,7 @@ export default {
} }
try { try {
self.$user.unlockTokenByPinCode(user.username, pinCode); unlockTokenByPinCode(user.username, pinCode);
self.transactionsStore.initTransactionDraft(); self.transactionsStore.initTransactionDraft();
self.tokensStore.refreshTokenAndRevokeOldToken().then(response => { self.tokensStore.refreshTokenAndRevokeOldToken().then(response => {
if (response.user) { if (response.user) {
+3 -2
View File
@@ -119,6 +119,7 @@ import { useSettingsStore } from '@/stores/setting.ts';
import { APPLICATION_LOGO_PATH } from '@/consts/asset.ts'; import { APPLICATION_LOGO_PATH } from '@/consts/asset.ts';
import { ThemeType } from '@/core/theme.ts'; import { ThemeType } from '@/core/theme.ts';
import { isUserVerifyEmailEnabled } from '@/lib/server_settings.ts'; import { isUserVerifyEmailEnabled } from '@/lib/server_settings.ts';
import { isUserLogined } from '@/lib/userstate.ts';
import { import {
mdiChevronLeft mdiChevronLeft
@@ -183,7 +184,7 @@ export default {
self.rootStore.verifyEmail({ self.rootStore.verifyEmail({
token: self.token, token: self.token,
requestNewToken: !self.$user.isUserLogined() requestNewToken: !isUserLogined()
}).then(() => { }).then(() => {
self.loading = false; self.loading = false;
self.verified = true; self.verified = true;
@@ -219,7 +220,7 @@ export default {
}); });
}, },
onSnackbarShowStateChanged(newValue) { onSnackbarShowStateChanged(newValue) {
if (!newValue && this.verified && this.$user.isUserLogined()) { if (!newValue && this.verified && isUserLogined()) {
this.$router.replace('/'); this.$router.replace('/');
} }
}, },
@@ -68,6 +68,14 @@ import { useTransactionsStore } from '@/stores/transaction.js';
import logger from '@/lib/logger.ts'; import logger from '@/lib/logger.ts';
import webauthn from '@/lib/webauthn.js'; import webauthn from '@/lib/webauthn.js';
import {
getUserAppLockState,
encryptToken,
decryptToken,
isCorrectPinCode,
saveWebAuthnConfig,
clearWebAuthnConfig
} from '@/lib/userstate.ts';
export default { export default {
data() { data() {
@@ -107,12 +115,12 @@ export default {
self.enablingWebAuthn = true; self.enablingWebAuthn = true;
webauthn.registerCredential( webauthn.registerCredential(
self.$user.getUserAppLockState(), getUserAppLockState(),
self.userStore.currentUserBasicInfo, self.userStore.currentUserBasicInfo,
).then(({ id }) => { ).then(({ id }) => {
self.enablingWebAuthn = false; self.enablingWebAuthn = false;
self.$user.saveWebAuthnConfig(id); saveWebAuthnConfig(id);
self.settingsStore.setEnableApplicationLockWebAuthn(true); self.settingsStore.setEnableApplicationLockWebAuthn(true);
self.$refs.snackbar.showMessage('You have enabled WebAuthn successfully'); self.$refs.snackbar.showMessage('You have enabled WebAuthn successfully');
}).catch(error => { }).catch(error => {
@@ -132,11 +140,11 @@ export default {
self.isEnableApplicationLockWebAuthn = false; self.isEnableApplicationLockWebAuthn = false;
self.settingsStore.setEnableApplicationLockWebAuthn(false); self.settingsStore.setEnableApplicationLockWebAuthn(false);
self.$user.clearWebAuthnConfig(); clearWebAuthnConfig();
}); });
} else { } else {
self.settingsStore.setEnableApplicationLockWebAuthn(false); self.settingsStore.setEnableApplicationLockWebAuthn(false);
self.$user.clearWebAuthnConfig(); clearWebAuthnConfig();
} }
} }
}, },
@@ -174,12 +182,12 @@ export default {
return; return;
} }
this.$user.encryptToken(user.username, this.pinCode); encryptToken(user.username, this.pinCode);
this.settingsStore.setEnableApplicationLock(true); this.settingsStore.setEnableApplicationLock(true);
this.transactionsStore.saveTransactionDraft(); this.transactionsStore.saveTransactionDraft();
this.settingsStore.setEnableApplicationLockWebAuthn(false); this.settingsStore.setEnableApplicationLockWebAuthn(false);
this.$user.clearWebAuthnConfig(); clearWebAuthnConfig();
this.pinCode = ''; this.pinCode = '';
}, },
@@ -189,7 +197,7 @@ export default {
return; return;
} }
if (!this.$user.isCorrectPinCode(this.pinCode)) { if (!isCorrectPinCode(this.pinCode)) {
this.pinCode = ''; this.pinCode = '';
this.$refs.snackbar.showMessage('Incorrect PIN code'); this.$refs.snackbar.showMessage('Incorrect PIN code');
return; return;
@@ -197,12 +205,12 @@ export default {
this.pinCode = ''; this.pinCode = '';
this.$user.decryptToken(); decryptToken();
this.settingsStore.setEnableApplicationLock(false); this.settingsStore.setEnableApplicationLock(false);
this.transactionsStore.saveTransactionDraft(); this.transactionsStore.saveTransactionDraft();
this.settingsStore.setEnableApplicationLockWebAuthn(false); this.settingsStore.setEnableApplicationLockWebAuthn(false);
this.$user.clearWebAuthnConfig(); clearWebAuthnConfig();
} }
} }
} }
+17 -9
View File
@@ -43,6 +43,14 @@ import { useTransactionsStore } from '@/stores/transaction.js';
import logger from '@/lib/logger.ts'; import logger from '@/lib/logger.ts';
import webauthn from '@/lib/webauthn.js'; import webauthn from '@/lib/webauthn.js';
import {
getUserAppLockState,
encryptToken,
decryptToken,
isCorrectPinCode,
saveWebAuthnConfig,
clearWebAuthnConfig
} from '@/lib/userstate.ts';
export default { export default {
data() { data() {
@@ -81,12 +89,12 @@ export default {
self.$showLoading(); self.$showLoading();
webauthn.registerCredential( webauthn.registerCredential(
self.$user.getUserAppLockState(), getUserAppLockState(),
self.userStore.currentUserBasicInfo, self.userStore.currentUserBasicInfo,
).then(({ id }) => { ).then(({ id }) => {
self.$hideLoading(); self.$hideLoading();
self.$user.saveWebAuthnConfig(id); saveWebAuthnConfig(id);
self.settingsStore.setEnableApplicationLockWebAuthn(true); self.settingsStore.setEnableApplicationLockWebAuthn(true);
self.$toast('You have enabled WebAuthn successfully'); self.$toast('You have enabled WebAuthn successfully');
}).catch(error => { }).catch(error => {
@@ -106,11 +114,11 @@ export default {
self.isEnableApplicationLockWebAuthn = false; self.isEnableApplicationLockWebAuthn = false;
self.settingsStore.setEnableApplicationLockWebAuthn(false); self.settingsStore.setEnableApplicationLockWebAuthn(false);
self.$user.clearWebAuthnConfig(); clearWebAuthnConfig();
}); });
} else { } else {
self.settingsStore.setEnableApplicationLockWebAuthn(false); self.settingsStore.setEnableApplicationLockWebAuthn(false);
self.$user.clearWebAuthnConfig(); clearWebAuthnConfig();
} }
} }
}, },
@@ -144,12 +152,12 @@ export default {
return; return;
} }
this.$user.encryptToken(user.username, pinCode); encryptToken(user.username, pinCode);
this.settingsStore.setEnableApplicationLock(true); this.settingsStore.setEnableApplicationLock(true);
this.transactionsStore.saveTransactionDraft(); this.transactionsStore.saveTransactionDraft();
this.settingsStore.setEnableApplicationLockWebAuthn(false); this.settingsStore.setEnableApplicationLockWebAuthn(false);
this.$user.clearWebAuthnConfig(); clearWebAuthnConfig();
this.showInputPinCodeSheetForEnable = false; this.showInputPinCodeSheetForEnable = false;
}, },
@@ -164,17 +172,17 @@ export default {
return; return;
} }
if (!this.$user.isCorrectPinCode(pinCode)) { if (!isCorrectPinCode(pinCode)) {
this.$alert('Incorrect PIN code'); this.$alert('Incorrect PIN code');
return; return;
} }
this.$user.decryptToken(); decryptToken();
this.settingsStore.setEnableApplicationLock(false); this.settingsStore.setEnableApplicationLock(false);
this.transactionsStore.saveTransactionDraft(); this.transactionsStore.saveTransactionDraft();
this.settingsStore.setEnableApplicationLockWebAuthn(false); this.settingsStore.setEnableApplicationLockWebAuthn(false);
this.$user.clearWebAuthnConfig(); clearWebAuthnConfig();
this.showInputPinCodeSheetForDisable = false; this.showInputPinCodeSheetForDisable = false;
} }
+2 -1
View File
@@ -210,6 +210,7 @@ import { useOverviewStore } from '@/stores/overview.js';
import { DateRange } from '@/core/datetime.ts'; import { DateRange } from '@/core/datetime.ts';
import { TemplateType } from '@/core/template.ts'; import { TemplateType } from '@/core/template.ts';
import { formatUnixTime } from '@/lib/datetime.ts'; import { formatUnixTime } from '@/lib/datetime.ts';
import { isUserLogined, isUserUnlocked } from '@/lib/userstate.ts';
export default { export default {
props: [ props: [
@@ -269,7 +270,7 @@ export default {
created() { created() {
const self = this; const self = this;
if (self.$user.isUserLogined() && self.$user.isUserUnlocked()) { if (isUserLogined() && isUserUnlocked()) {
self.loading = true; self.loading = true;
self.overviewStore.loadTransactionOverview({ self.overviewStore.loadTransactionOverview({
+2 -1
View File
@@ -184,6 +184,7 @@ import { useExchangeRatesStore } from '@/stores/exchangeRates.js';
import { CategoryType } from '@/core/category.ts'; import { CategoryType } from '@/core/category.ts';
import { getNameByKeyValue, categorizedArrayToPlainArray } from '@/lib/common.ts'; import { getNameByKeyValue, categorizedArrayToPlainArray } from '@/lib/common.ts';
import { isUserLogined } from '@/lib/userstate.ts';
import { setExpenseAndIncomeAmountColor } from '@/lib/ui/common.ts'; import { setExpenseAndIncomeAmountColor } from '@/lib/ui/common.ts';
export default { export default {
@@ -307,7 +308,7 @@ export default {
user: self.user, user: self.user,
presetCategories: presetCategories presetCategories: presetCategories
}).then(response => { }).then(response => {
if (!self.$user.isUserLogined()) { if (!isUserLogined()) {
self.submitting = false; self.submitting = false;
self.$hideLoading(); self.$hideLoading();
+11 -5
View File
@@ -76,6 +76,12 @@ import { useExchangeRatesStore } from '@/stores/exchangeRates.js';
import { APPLICATION_LOGO_PATH } from '@/consts/asset.ts'; import { APPLICATION_LOGO_PATH } from '@/consts/asset.ts';
import logger from '@/lib/logger.ts'; import logger from '@/lib/logger.ts';
import webauthn from '@/lib/webauthn.js'; import webauthn from '@/lib/webauthn.js';
import {
unlockTokenByWebAuthn,
unlockTokenByPinCode,
hasWebAuthnConfig,
getWebAuthnCredentialId
} from '@/lib/userstate.ts';
import { setExpenseAndIncomeAmountColor } from '@/lib/ui/common.ts'; import { setExpenseAndIncomeAmountColor } from '@/lib/ui/common.ts';
import { isModalShowing } from '@/lib/ui/mobile.js'; import { isModalShowing } from '@/lib/ui/mobile.js';
@@ -101,7 +107,7 @@ export default {
}, },
isWebAuthnAvailable() { isWebAuthnAvailable() {
return this.settingsStore.appSettings.applicationLockWebAuthn return this.settingsStore.appSettings.applicationLockWebAuthn
&& this.$user.getWebAuthnCredentialId() && hasWebAuthnConfig()
&& webauthn.isSupported(); && webauthn.isSupported();
}, },
currentLanguageCode() { currentLanguageCode() {
@@ -116,7 +122,7 @@ export default {
const self = this; const self = this;
const router = self.f7router; const router = self.f7router;
if (!self.settingsStore.appSettings.applicationLockWebAuthn || !self.$user.getWebAuthnCredentialId()) { if (!self.settingsStore.appSettings.applicationLockWebAuthn || !hasWebAuthnConfig()) {
self.$toast('WebAuthn is not enabled'); self.$toast('WebAuthn is not enabled');
return; return;
} }
@@ -130,11 +136,11 @@ export default {
webauthn.verifyCredential( webauthn.verifyCredential(
self.userStore.currentUserBasicInfo, self.userStore.currentUserBasicInfo,
self.$user.getWebAuthnCredentialId() getWebAuthnCredentialId()
).then(({ id, userName, userSecret }) => { ).then(({ id, userName, userSecret }) => {
self.$hideLoading(); self.$hideLoading();
self.$user.unlockTokenByWebAuthn(id, userName, userSecret); unlockTokenByWebAuthn(id, userName, userSecret);
self.transactionsStore.initTransactionDraft(); self.transactionsStore.initTransactionDraft();
self.tokensStore.refreshTokenAndRevokeOldToken().then(response => { self.tokensStore.refreshTokenAndRevokeOldToken().then(response => {
if (response.user) { if (response.user) {
@@ -189,7 +195,7 @@ export default {
} }
try { try {
self.$user.unlockTokenByPinCode(user.username, pinCode); unlockTokenByPinCode(user.username, pinCode);
self.transactionsStore.initTransactionDraft(); self.transactionsStore.initTransactionDraft();
self.tokensStore.refreshTokenAndRevokeOldToken().then(response => { self.tokensStore.refreshTokenAndRevokeOldToken().then(response => {
if (response.user) { if (response.user) {