Clean up savedCredentials

This commit is contained in:
Natsumi
2025-10-31 01:49:31 +11:00
parent cfd2f22b2c
commit f434c83b0c
2 changed files with 101 additions and 58 deletions
+59 -50
View File
@@ -15,7 +15,6 @@ import { useAdvancedSettingsStore } from './settings/advanced';
import { useNotificationStore } from './notification'; import { useNotificationStore } from './notification';
import { useUpdateLoopStore } from './updateLoop'; import { useUpdateLoopStore } from './updateLoop';
import { useUserStore } from './user'; import { useUserStore } from './user';
import { useVrcxStore } from './vrcx';
import { watchState } from '../service/watchState'; import { watchState } from '../service/watchState';
import configRepository from '../service/config'; import configRepository from '../service/config';
@@ -27,7 +26,6 @@ export const useAuthStore = defineStore('Auth', () => {
const notificationStore = useNotificationStore(); const notificationStore = useNotificationStore();
const userStore = useUserStore(); const userStore = useUserStore();
const updateLoopStore = useUpdateLoopStore(); const updateLoopStore = useUpdateLoopStore();
const vrcxStore = useVrcxStore();
const { t } = useI18n(); const { t } = useI18n();
const state = reactive({ const state = reactive({
@@ -43,7 +41,6 @@ export const useAuthStore = defineStore('Auth', () => {
endpoint: '', endpoint: '',
websocket: '', websocket: '',
saveCredentials: false, saveCredentials: false,
savedCredentials: {},
lastUserLoggedIn: '', lastUserLoggedIn: '',
rules: { rules: {
username: [ username: [
@@ -144,16 +141,29 @@ export const useAuthStore = defineStore('Auth', () => {
JSON.stringify(credentials) JSON.stringify(credentials)
); );
} }
loginForm.value.savedCredentials = credentials;
} catch (error) { } catch (error) {
console.error('Failed to parse savedCredentials:', error); console.error('Failed to parse savedCredentials:', error);
loginForm.value.savedCredentials = {};
} }
state.enableCustomEndpoint = enableCustomEndpoint; state.enableCustomEndpoint = enableCustomEndpoint;
} }
init(); init();
async function getSavedCredentials(userId) {
let savedCredentials = {};
try {
savedCredentials = JSON.parse(
await configRepository.getString('savedCredentials', '{}')
);
} catch (e) {
console.error('Failed to get saved credentials:', e);
}
if (!savedCredentials) {
return null;
}
return savedCredentials[userId];
}
async function handleLogoutEvent() { async function handleLogoutEvent() {
if (watchState.isLoggedIn) { if (watchState.isLoggedIn) {
new Noty({ new Noty({
@@ -187,10 +197,9 @@ export const useAuthStore = defineStore('Auth', () => {
!advancedSettingsStore.enablePrimaryPassword && !advancedSettingsStore.enablePrimaryPassword &&
(await configRepository.getString('lastUserLoggedIn')) !== null (await configRepository.getString('lastUserLoggedIn')) !== null
) { ) {
const user = const user = await getSavedCredentials(
loginForm.value.savedCredentials[ loginForm.value.lastUserLoggedIn
loginForm.value.lastUserLoggedIn );
];
if (user?.loginParams?.endpoint) { if (user?.loginParams?.endpoint) {
AppDebug.endpointDomain = user.loginParams.endpoint; AppDebug.endpointDomain = user.loginParams.endpoint;
AppDebug.websocketDomain = user.loginParams.websocket; AppDebug.websocketDomain = user.loginParams.websocket;
@@ -220,11 +229,10 @@ export const useAuthStore = defineStore('Auth', () => {
async function clearCookiesTryLogin() { async function clearCookiesTryLogin() {
await webApiService.clearCookies(); await webApiService.clearCookies();
if (loginForm.value.lastUserLoggedIn) { if (loginForm.value.lastUserLoggedIn) {
const user = const user = await getSavedCredentials(
loginForm.value.savedCredentials[ loginForm.value.lastUserLoggedIn
loginForm.value.lastUserLoggedIn );
]; if (user) {
if (typeof user !== 'undefined') {
delete user.cookies; delete user.cookies;
await relogin(user); await relogin(user);
} }
@@ -233,11 +241,10 @@ export const useAuthStore = defineStore('Auth', () => {
async function resendEmail2fa() { async function resendEmail2fa() {
if (loginForm.value.lastUserLoggedIn) { if (loginForm.value.lastUserLoggedIn) {
const user = const user = await getSavedCredentials(
loginForm.value.savedCredentials[ loginForm.value.lastUserLoggedIn
loginForm.value.lastUserLoggedIn );
]; if (user) {
if (typeof user !== 'undefined') {
await webApiService.clearCookies(); await webApiService.clearCookies();
delete user.cookies; delete user.cookies;
relogin(user).then(() => { relogin(user).then(() => {
@@ -272,24 +279,28 @@ export const useAuthStore = defineStore('Auth', () => {
inputPattern: /[\s\S]{1,32}/ inputPattern: /[\s\S]{1,32}/
} }
) )
.then(({ value }) => { .then(async ({ value }) => {
for (const userId in loginForm.value.savedCredentials) { let savedCredentials = JSON.parse(
await configRepository.getString(
'savedCredentials',
'{}'
)
);
for (const userId in savedCredentials) {
security security
.decrypt( .decrypt(
loginForm.value.savedCredentials[userId] savedCredentials[userId].loginParams.password,
.loginParams.password,
value value
) )
.then(async (pt) => { .then(async (pt) => {
credentialsToSave.value = { credentialsToSave.value = {
username: username:
loginForm.value.savedCredentials[userId] savedCredentials[userId].loginParams
.loginParams.username, .username,
password: pt password: pt
}; };
await updateStoredUser( await updateStoredUser(
loginForm.value.savedCredentials[userId] savedCredentials[userId].user
.user
); );
await configRepository.setBool( await configRepository.setBool(
'enablePrimaryPassword', 'enablePrimaryPassword',
@@ -320,23 +331,19 @@ export const useAuthStore = defineStore('Auth', () => {
enablePrimaryPasswordDialog.value.visible = false; enablePrimaryPasswordDialog.value.visible = false;
if (advancedSettingsStore.enablePrimaryPassword) { if (advancedSettingsStore.enablePrimaryPassword) {
const key = enablePrimaryPasswordDialog.value.password; const key = enablePrimaryPasswordDialog.value.password;
for (const userId in loginForm.value.savedCredentials) { let savedCredentials = JSON.parse(
await configRepository.getString('savedCredentials', '{}')
);
for (const userId in savedCredentials) {
security security
.encrypt( .encrypt(savedCredentials[userId].loginParams.password, key)
loginForm.value.savedCredentials[userId].loginParams
.password,
key
)
.then((ct) => { .then((ct) => {
credentialsToSave.value = { credentialsToSave.value = {
username: username:
loginForm.value.savedCredentials[userId] savedCredentials[userId].loginParams.username,
.loginParams.username,
password: ct password: ct
}; };
updateStoredUser( updateStoredUser(savedCredentials[userId].user);
loginForm.value.savedCredentials[userId].user
);
}); });
} }
} }
@@ -366,7 +373,6 @@ export const useAuthStore = defineStore('Auth', () => {
savedCredentials[user.id].cookies = savedCredentials[user.id].cookies =
await webApiService.getCookies(); await webApiService.getCookies();
} }
loginForm.value.savedCredentials = savedCredentials;
const jsonCredentialsArray = JSON.stringify(savedCredentials); const jsonCredentialsArray = JSON.stringify(savedCredentials);
await configRepository.setString( await configRepository.setString(
'savedCredentials', 'savedCredentials',
@@ -531,9 +537,10 @@ export const useAuthStore = defineStore('Auth', () => {
false false
); );
} }
loginForm.value.savedCredentials = savedCredentials; await configRepository.setString(
const jsonCredentials = JSON.stringify(savedCredentials); 'savedCredentials',
await configRepository.setString('savedCredentials', jsonCredentials); JSON.stringify(savedCredentials)
);
new Noty({ new Noty({
type: 'success', type: 'success',
text: 'Account removed.' text: 'Account removed.'
@@ -571,12 +578,15 @@ export const useAuthStore = defineStore('Auth', () => {
inputPattern: /[\s\S]{1,32}/ inputPattern: /[\s\S]{1,32}/
} }
) )
.then(({ value }) => { .then(async ({ value }) => {
const savedCredentials = JSON.parse(
await configRepository.getString(
'savedCredentials'
)
);
const saveCredential = const saveCredential =
loginForm.value.savedCredentials[ savedCredentials[
Object.keys( Object.keys(savedCredentials)[0]
loginForm.value.savedCredentials
)[0]
]; ];
security security
.decrypt( .decrypt(
@@ -823,9 +833,8 @@ export const useAuthStore = defineStore('Auth', () => {
return; return;
} }
attemptingAutoLogin.value = true; attemptingAutoLogin.value = true;
const user = const user = getSavedCredentials(loginForm.value.lastUserLoggedIn);
loginForm.value.savedCredentials[loginForm.value.lastUserLoggedIn]; if (!user) {
if (typeof user === 'undefined') {
attemptingAutoLogin.value = false; attemptingAutoLogin.value = false;
return; return;
} }
+42 -8
View File
@@ -92,19 +92,19 @@
> >
</div> </div>
<hr v-if="Object.keys(loginForm.savedCredentials).length !== 0" class="x-vertical-divider" /> <hr v-if="Object.keys(savedCredentials).length !== 0" class="x-vertical-divider" />
<div v-if="Object.keys(loginForm.savedCredentials).length !== 0"> <div v-if="Object.keys(savedCredentials).length !== 0">
<h2 style="font-weight: bold; text-align: center; margin: 0"> <h2 style="font-weight: bold; text-align: center; margin: 0">
{{ t('view.login.savedAccounts') }} {{ t('view.login.savedAccounts') }}
</h2> </h2>
<div class="x-scroll-wrapper" style="margin-top: 10px"> <div class="x-scroll-wrapper" style="margin-top: 10px">
<div class="x-saved-account-list"> <div class="x-saved-account-list">
<div <div
v-for="user in loginForm.savedCredentials" v-for="user in savedCredentials"
:key="user.user.id" :key="user.user.id"
class="x-friend-item" class="x-friend-item"
@click="relogin(user)"> @click="clickSavedLogin(user)">
<div class="avatar"> <div class="avatar">
<img :src="userImage(user.user)" loading="lazy" /> <img :src="userImage(user.user)" loading="lazy" />
</div> </div>
@@ -119,7 +119,7 @@
:icon="Delete" :icon="Delete"
style="margin-left: 10px" style="margin-left: 10px"
circle circle
@click.stop="deleteSavedLogin(user.user.id)"></el-button> @click.stop="clickDeleteSavedLogin(user.user.id)"></el-button>
</div> </div>
</div> </div>
</div> </div>
@@ -149,13 +149,16 @@
<script setup> <script setup>
import { Connection, Delete, Download } from '@element-plus/icons-vue'; import { Connection, Delete, Download } from '@element-plus/icons-vue';
import { onBeforeUnmount, ref } from 'vue'; import { onBeforeMount, onBeforeUnmount, ref } from 'vue';
import { storeToRefs } from 'pinia'; import { storeToRefs } from 'pinia';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import { useAuthStore, useGeneralSettingsStore, useVRCXUpdaterStore } from '../../stores'; import { useAuthStore, useGeneralSettingsStore, useVRCXUpdaterStore } from '../../stores';
import { openExternalLink, userImage } from '../../shared/utils'; import { openExternalLink, userImage } from '../../shared/utils';
import { AppDebug } from '../../service/appConfig'; import { AppDebug } from '../../service/appConfig';
import { watchState } from '../../service/watchState';
import configRepository from '../../service/config';
const { showVRCXUpdateDialog } = useVRCXUpdaterStore(); const { showVRCXUpdateDialog } = useVRCXUpdaterStore();
const { loginForm, enableCustomEndpoint } = storeToRefs(useAuthStore()); const { loginForm, enableCustomEndpoint } = storeToRefs(useAuthStore());
@@ -165,18 +168,49 @@
const { t } = useI18n(); const { t } = useI18n();
const loginFormRef = ref(null); const loginFormRef = ref(null);
const savedCredentials = ref({});
async function clickDeleteSavedLogin(userId) {
await deleteSavedLogin(userId);
await updateSavedCredentials();
}
async function clickSavedLogin(user) {
await relogin(user);
await updateSavedCredentials();
}
function handleLogin() { function handleLogin() {
if (loginFormRef.value) { if (loginFormRef.value) {
loginFormRef.value.validate((valid) => { loginFormRef.value.validate(async (valid) => {
valid && login(); if (valid) {
await login();
await updateSavedCredentials();
}
}); });
} }
} }
async function updateSavedCredentials() {
if (watchState.isLoggedIn) {
return;
}
try {
savedCredentials.value = JSON.parse(await configRepository.getString('savedCredentials')) || {};
} catch (e) {
console.error('Failed to parse saved credentials:', e);
savedCredentials.value = {};
}
}
onBeforeMount(async () => {
updateSavedCredentials();
});
onBeforeUnmount(() => { onBeforeUnmount(() => {
if (loginFormRef.value) { if (loginFormRef.value) {
loginFormRef.value.resetFields(); loginFormRef.value.resetFields();
} }
savedCredentials.value = {};
}); });
</script> </script>