mirror of
https://github.com/mayswind/ezbookkeeping.git
synced 2026-05-14 15:07:33 +08:00
add log in frontend
This commit is contained in:
@@ -0,0 +1,42 @@
|
||||
import settings from './settings.js';
|
||||
|
||||
function logDebug(msg, obj) {
|
||||
if (settings.isEnableDebug()) {
|
||||
if (obj) {
|
||||
console.debug('[lab Debug] ' + msg, obj);
|
||||
} else {
|
||||
console.debug('[lab Debug] ' + msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function logInfo(msg, obj) {
|
||||
if (obj) {
|
||||
console.info('[lab Info] ' + msg, obj);
|
||||
} else {
|
||||
console.info('[lab Info] ' + msg);
|
||||
}
|
||||
}
|
||||
|
||||
function logWarn(msg, obj) {
|
||||
if (obj) {
|
||||
console.warn('[lab Warn] ' + msg, obj);
|
||||
} else {
|
||||
console.warn('[lab Warn] ' + msg);
|
||||
}
|
||||
}
|
||||
|
||||
function logError(msg, obj) {
|
||||
if (obj) {
|
||||
console.error('[lab Error] ' + msg, obj);
|
||||
} else {
|
||||
console.error('[lab Error] ' + msg);
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
debug: logDebug,
|
||||
info: logInfo,
|
||||
warn: logWarn,
|
||||
error: logError
|
||||
};
|
||||
@@ -5,6 +5,7 @@ const serverSettingsCookieKey = 'ACP_SETTINGS';
|
||||
|
||||
const defaultSettings = {
|
||||
lang: 'en',
|
||||
debug: false,
|
||||
applicationLock: false,
|
||||
applicationLockWebAuthn: false,
|
||||
autoUpdateExchangeRatesData: true,
|
||||
@@ -75,6 +76,8 @@ function clearSettings() {
|
||||
export default {
|
||||
getLanguage: () => getOriginalOption('lang'),
|
||||
setLanguage: value => setOption('lang', value),
|
||||
isEnableDebug: () => getOption('debug'),
|
||||
setEnableDebug: value => setOption('debug', value),
|
||||
isEnableApplicationLock: () => getOption('applicationLock'),
|
||||
setEnableApplicationLock: value => setOption('applicationLock', value),
|
||||
isEnableApplicationLockWebAuthn: () => getOption('applicationLockWebAuthn'),
|
||||
|
||||
+19
-3
@@ -1,4 +1,5 @@
|
||||
import CBOR from 'cbor-js';
|
||||
import logger from './logger.js';
|
||||
import utils from './utils.js';
|
||||
|
||||
const PUBLIC_KEY_CREDENTIAL_CREATION_OPTIONS_TEMPLATE = {
|
||||
@@ -72,6 +73,8 @@ function registerCredential({ username, nickname }, userSecret) {
|
||||
}
|
||||
});
|
||||
|
||||
logger.debug('webauthn create options', publicKeyCredentialCreationOptions);
|
||||
|
||||
return navigator.credentials.create({
|
||||
publicKey: publicKeyCredentialCreationOptions
|
||||
}).then(rawCredential => {
|
||||
@@ -80,15 +83,20 @@ function registerCredential({ username, nickname }, userSecret) {
|
||||
|
||||
const challengeFromClientData = clientData && clientData.challenge ? atob(clientData.challenge) : null;
|
||||
|
||||
logger.debug('webauthn create raw response', rawCredential);
|
||||
|
||||
if (rawCredential && rawCredential.rawId &&
|
||||
clientData && clientData.type === 'webauthn.create' && challengeFromClientData === challenge) {
|
||||
|
||||
return {
|
||||
const ret = {
|
||||
id: utils.base64encode(rawCredential.rawId),
|
||||
clientData: clientData,
|
||||
publicKey: publicKey,
|
||||
rawCredential: rawCredential
|
||||
};
|
||||
|
||||
logger.debug('webauthn create response', ret);
|
||||
|
||||
return ret;
|
||||
} else {
|
||||
return Promise.reject({
|
||||
invalid: true
|
||||
@@ -137,22 +145,30 @@ function verifyCredential(credentialId) {
|
||||
});
|
||||
publicKeyCredentialRequestOptions.allowCredentials[0].id = Uint8Array.from(atob(credentialId), c=>c.charCodeAt(0)).buffer;
|
||||
|
||||
logger.debug('webauthn get options', publicKeyCredentialRequestOptions);
|
||||
|
||||
return navigator.credentials.get({
|
||||
publicKey: publicKeyCredentialRequestOptions
|
||||
}).then(rawCredential => {
|
||||
const clientData = rawCredential ? parseClientData(rawCredential) : null;
|
||||
const challengeFromClientData = clientData && clientData.challenge ? atob(clientData.challenge) : null;
|
||||
|
||||
logger.debug('webauthn get raw response', rawCredential);
|
||||
|
||||
if (rawCredential && rawCredential.rawId &&
|
||||
rawCredential.response && rawCredential.response.userHandle &&
|
||||
clientData && clientData.type === 'webauthn.get' && challengeFromClientData === challenge) {
|
||||
|
||||
return {
|
||||
const ret = {
|
||||
id: utils.base64encode(rawCredential.rawId),
|
||||
userSecret: utils.arrayBufferToString(rawCredential.response.userHandle),
|
||||
clientData: clientData,
|
||||
rawCredential: rawCredential
|
||||
};
|
||||
|
||||
logger.debug('webauthn get response', ret);
|
||||
|
||||
return ret;
|
||||
} else {
|
||||
return Promise.reject({
|
||||
invalid: true
|
||||
|
||||
@@ -20,6 +20,7 @@ import icons from './consts/icon.js';
|
||||
import account from './consts/account.js';
|
||||
import licenses from './consts/licenses.js';
|
||||
import version from './lib/version.js';
|
||||
import logger from './lib/logger.js';
|
||||
import settings from './lib/settings.js';
|
||||
import services from './lib/services.js';
|
||||
import userstate from './lib/userstate.js';
|
||||
@@ -51,6 +52,7 @@ Vue.prototype.$constants = {
|
||||
account: account,
|
||||
};
|
||||
Vue.prototype.$utilities = utils;
|
||||
Vue.prototype.$logger = logger;
|
||||
Vue.prototype.$webauthn = webauthn;
|
||||
Vue.prototype.$settings = settings;
|
||||
Vue.prototype.$getDefaultLanguage = getDefaultLanguage;
|
||||
@@ -163,6 +165,12 @@ Vue.filter('accountIcon', (value) => accountIconFilter(value));
|
||||
Vue.filter('tokenDevice', (value) => tokenDeviceFilter(value));
|
||||
Vue.filter('tokenIcon', (value) => tokenIconFilter(value));
|
||||
|
||||
if (settings.getLanguage()) {
|
||||
logger.info(`Current language is ${settings.getLanguage()}`);
|
||||
} else {
|
||||
logger.info(`No language is set, use browser default ${getDefaultLanguage()}`);
|
||||
}
|
||||
|
||||
Vue.prototype.$setLanguage(settings.getLanguage() || getDefaultLanguage());
|
||||
|
||||
if (userstate.isUserLogined()) {
|
||||
|
||||
@@ -112,12 +112,14 @@ export default {
|
||||
self.$user.saveWebAuthnConfig(id);
|
||||
self.$settings.setEnableApplicationLockWebAuthn(true);
|
||||
self.$toast('You have enabled Face ID/Touch ID successfully');
|
||||
}).catch(({ notSupported, invalid }) => {
|
||||
}).catch(error => {
|
||||
self.$logger.error('failed to enable FaceID/Touch ID', error);
|
||||
|
||||
self.$hideLoading();
|
||||
|
||||
if (notSupported) {
|
||||
if (error.notSupported) {
|
||||
self.$toast('This device does not support Face ID/Touch ID');
|
||||
} else if (invalid) {
|
||||
} else if (error.invalid) {
|
||||
self.$toast('Failed to enable Face ID/Touch ID');
|
||||
} else {
|
||||
self.$toast('User has canceled or this device does not support Face ID/Touch ID');
|
||||
|
||||
@@ -137,6 +137,8 @@ export default {
|
||||
|
||||
self.$toast('Exchange rates data has been updated');
|
||||
}).catch(error => {
|
||||
self.$logger.error('failed to get latest exchange rates data', error);
|
||||
|
||||
if (done) {
|
||||
done();
|
||||
}
|
||||
|
||||
@@ -194,6 +194,8 @@ export default {
|
||||
|
||||
router.refreshPage();
|
||||
}).catch(error => {
|
||||
self.$logger.error('failed to login', error);
|
||||
|
||||
self.logining = false;
|
||||
self.$hideLoading();
|
||||
|
||||
@@ -267,6 +269,8 @@ export default {
|
||||
self.show2faSheet = false;
|
||||
router.refreshPage();
|
||||
}).catch(error => {
|
||||
self.$logger.error('failed to verify 2fa', error);
|
||||
|
||||
self.verifying = false;
|
||||
self.$hideLoading();
|
||||
|
||||
|
||||
@@ -188,6 +188,8 @@ export default {
|
||||
self.$exchangeRates.clearExchangeRates();
|
||||
router.navigate('/');
|
||||
}).catch(error => {
|
||||
self.$logger.error('failed to log out', error);
|
||||
|
||||
self.logouting = false;
|
||||
self.$hideLoading();
|
||||
|
||||
|
||||
@@ -166,6 +166,8 @@ export default {
|
||||
self.$toast('You have been successfully registered');
|
||||
router.navigate('/');
|
||||
}).catch(error => {
|
||||
self.$logger.error('failed to sign up', error);
|
||||
|
||||
self.submitting = false;
|
||||
self.$hideLoading();
|
||||
|
||||
|
||||
@@ -43,10 +43,12 @@ export default {
|
||||
}
|
||||
|
||||
router.refreshPage();
|
||||
}).catch(({ notSupported, invalid }) => {
|
||||
if (notSupported) {
|
||||
}).catch(error => {
|
||||
self.$logger.error('failed to use webauthn to verify', error);
|
||||
|
||||
if (error.notSupported) {
|
||||
self.$toast('This device does not support Face ID/Touch ID');
|
||||
} else if (invalid) {
|
||||
} else if (error.invalid) {
|
||||
self.$toast('Failed to authenticate by Face ID/Touch ID');
|
||||
} else {
|
||||
self.$toast('User has canceled or this device does not support Face ID/Touch ID');
|
||||
@@ -72,6 +74,7 @@ export default {
|
||||
|
||||
router.refreshPage();
|
||||
} catch (ex) {
|
||||
this.$logger.error('failed to unlock by pin code', ex);
|
||||
this.$alert('PIN code is wrong');
|
||||
}
|
||||
},
|
||||
|
||||
@@ -394,6 +394,8 @@ export default {
|
||||
|
||||
self.loading = false;
|
||||
}).catch(error => {
|
||||
self.$logger.error('failed to load account info', error);
|
||||
|
||||
if (error.response && error.response.data && error.response.data.errorMessage) {
|
||||
self.$alert({ error: error.response.data }, () => {
|
||||
router.back();
|
||||
@@ -548,6 +550,8 @@ export default {
|
||||
|
||||
router.back('/account/list', { force: true });
|
||||
}).catch(error => {
|
||||
self.$logger.error('failed to save account', error);
|
||||
|
||||
self.submitting = false;
|
||||
self.$hideLoading();
|
||||
|
||||
|
||||
@@ -305,6 +305,8 @@ export default {
|
||||
self.accounts = self.$utilities.getCategorizedAccounts(data.result);
|
||||
self.loading = false;
|
||||
}).catch(error => {
|
||||
self.$logger.error('failed to load account list', error);
|
||||
|
||||
if (error.response && error.response.data && error.response.data.errorMessage) {
|
||||
self.$alert({ error: error.response.data }, () => {
|
||||
router.back();
|
||||
@@ -332,6 +334,8 @@ export default {
|
||||
|
||||
self.accounts = self.$utilities.getCategorizedAccounts(data.result);
|
||||
}).catch(error => {
|
||||
self.$logger.error('failed to reload account list', error);
|
||||
|
||||
done();
|
||||
|
||||
if (error.response && error.response.data && error.response.data.errorMessage) {
|
||||
@@ -477,6 +481,8 @@ export default {
|
||||
self.sortable = false;
|
||||
self.displayOrderModified = false;
|
||||
}).catch(error => {
|
||||
self.$logger.error('failed to save accounts display order', error);
|
||||
|
||||
self.displayOrderSaving = false;
|
||||
self.$hideLoading();
|
||||
|
||||
@@ -514,6 +520,8 @@ export default {
|
||||
|
||||
account.hidden = hidden;
|
||||
}).catch(error => {
|
||||
self.$logger.error('failed to change account visibility', error);
|
||||
|
||||
self.$hideLoading();
|
||||
|
||||
if (error.response && error.response.data && error.response.data.errorMessage) {
|
||||
@@ -555,6 +563,8 @@ export default {
|
||||
}
|
||||
});
|
||||
}).catch(error => {
|
||||
self.$logger.error('failed to delete account', error);
|
||||
|
||||
self.$hideLoading();
|
||||
|
||||
if (error.response && error.response.data && error.response.data.errorMessage) {
|
||||
|
||||
@@ -69,6 +69,8 @@ export default {
|
||||
self.tokens = data.result;
|
||||
self.loading = false;
|
||||
}).catch(error => {
|
||||
self.$logger.error('failed to load token list', error);
|
||||
|
||||
if (error.response && error.response.data && error.response.data.errorMessage) {
|
||||
self.$alert({ error: error.response.data }, () => {
|
||||
router.back();
|
||||
@@ -96,6 +98,8 @@ export default {
|
||||
|
||||
self.tokens = data.result;
|
||||
}).catch(error => {
|
||||
self.$logger.error('failed to reload token list', error);
|
||||
|
||||
done();
|
||||
|
||||
if (error.response && error.response.data && error.response.data.errorMessage) {
|
||||
@@ -132,6 +136,8 @@ export default {
|
||||
}
|
||||
});
|
||||
}).catch(error => {
|
||||
self.$logger.error('failed to revoke token', error);
|
||||
|
||||
self.$hideLoading();
|
||||
|
||||
if (error.response && error.response.data && error.response.data.errorMessage) {
|
||||
@@ -169,6 +175,8 @@ export default {
|
||||
|
||||
self.$toast('You have logged out all other sessions');
|
||||
}).catch(error => {
|
||||
self.$logger.error('failed to revoke all tokens', error);
|
||||
|
||||
self.$hideLoading();
|
||||
|
||||
if (error.response && error.response.data && error.response.data.errorMessage) {
|
||||
|
||||
@@ -184,6 +184,8 @@ export default {
|
||||
self.status = data.result.enable;
|
||||
self.loading = false;
|
||||
}).catch(error => {
|
||||
self.$logger.error('failed to get 2fa status', error);
|
||||
|
||||
if (error.response && error.response.data && error.response.data.errorMessage) {
|
||||
self.$alert({ error: error.response.data }, () => {
|
||||
router.back();
|
||||
@@ -220,6 +222,8 @@ export default {
|
||||
|
||||
self.showInputPasscodeSheetForEnable = true;
|
||||
}).catch(error => {
|
||||
self.$logger.error('failed to request to enable 2fa', error);
|
||||
|
||||
self.enabling = false;
|
||||
self.$hideLoading();
|
||||
|
||||
@@ -262,6 +266,8 @@ export default {
|
||||
self.showBackupCodeSheet = true;
|
||||
}
|
||||
}).catch(error => {
|
||||
self.$logger.error('failed to confirm to enable 2fa', error);
|
||||
|
||||
self.enableConfirming = false;
|
||||
self.$hideLoading();
|
||||
|
||||
@@ -300,6 +306,8 @@ export default {
|
||||
self.showInputPasswordSheetForDisable = false;
|
||||
self.$toast('Two factor authentication has been disabled');
|
||||
}).catch(error => {
|
||||
self.$logger.error('failed to disable 2fa', error);
|
||||
|
||||
self.disabling = false;
|
||||
self.$hideLoading();
|
||||
|
||||
@@ -339,6 +347,8 @@ export default {
|
||||
self.currentBackupCode = data.result.recoveryCodes.join('\n');
|
||||
self.showBackupCodeSheet = true;
|
||||
}).catch(error => {
|
||||
self.$logger.error('failed to regenerate 2fa recovery code', error);
|
||||
|
||||
self.regenerating = false;
|
||||
self.$hideLoading();
|
||||
|
||||
|
||||
@@ -189,6 +189,8 @@ export default {
|
||||
self.newProfile.defaultCurrency = self.oldProfile.defaultCurrency;
|
||||
self.loading = false;
|
||||
}).catch(error => {
|
||||
self.$logger.error('failed to get user profile', error);
|
||||
|
||||
if (error.response && error.response.data && error.response.data.errorMessage) {
|
||||
self.$alert({ error: error.response.data }, () => {
|
||||
router.back();
|
||||
@@ -251,6 +253,8 @@ export default {
|
||||
self.$toast('Your profile has been successfully updated');
|
||||
router.back('/settings', { force: true });
|
||||
}).catch(error => {
|
||||
self.$logger.error('failed to save user profile', error);
|
||||
|
||||
self.saving = false;
|
||||
self.$hideLoading();
|
||||
self.currentPassword = '';
|
||||
|
||||
Reference in New Issue
Block a user