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

View File

@@ -15,7 +15,6 @@ import { useAdvancedSettingsStore } from './settings/advanced';
import { useNotificationStore } from './notification';
import { useUpdateLoopStore } from './updateLoop';
import { useUserStore } from './user';
import { useVrcxStore } from './vrcx';
import { watchState } from '../service/watchState';
import configRepository from '../service/config';
@@ -27,7 +26,6 @@ export const useAuthStore = defineStore('Auth', () => {
const notificationStore = useNotificationStore();
const userStore = useUserStore();
const updateLoopStore = useUpdateLoopStore();
const vrcxStore = useVrcxStore();
const { t } = useI18n();
const state = reactive({
@@ -43,7 +41,6 @@ export const useAuthStore = defineStore('Auth', () => {
endpoint: '',
websocket: '',
saveCredentials: false,
savedCredentials: {},
lastUserLoggedIn: '',
rules: {
username: [
@@ -144,16 +141,29 @@ export const useAuthStore = defineStore('Auth', () => {
JSON.stringify(credentials)
);
}
loginForm.value.savedCredentials = credentials;
} catch (error) {
console.error('Failed to parse savedCredentials:', error);
loginForm.value.savedCredentials = {};
}
state.enableCustomEndpoint = enableCustomEndpoint;
}
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() {
if (watchState.isLoggedIn) {
new Noty({
@@ -187,10 +197,9 @@ export const useAuthStore = defineStore('Auth', () => {
!advancedSettingsStore.enablePrimaryPassword &&
(await configRepository.getString('lastUserLoggedIn')) !== null
) {
const user =
loginForm.value.savedCredentials[
loginForm.value.lastUserLoggedIn
];
const user = await getSavedCredentials(
loginForm.value.lastUserLoggedIn
);
if (user?.loginParams?.endpoint) {
AppDebug.endpointDomain = user.loginParams.endpoint;
AppDebug.websocketDomain = user.loginParams.websocket;
@@ -220,11 +229,10 @@ export const useAuthStore = defineStore('Auth', () => {
async function clearCookiesTryLogin() {
await webApiService.clearCookies();
if (loginForm.value.lastUserLoggedIn) {
const user =
loginForm.value.savedCredentials[
loginForm.value.lastUserLoggedIn
];
if (typeof user !== 'undefined') {
const user = await getSavedCredentials(
loginForm.value.lastUserLoggedIn
);
if (user) {
delete user.cookies;
await relogin(user);
}
@@ -233,11 +241,10 @@ export const useAuthStore = defineStore('Auth', () => {
async function resendEmail2fa() {
if (loginForm.value.lastUserLoggedIn) {
const user =
loginForm.value.savedCredentials[
loginForm.value.lastUserLoggedIn
];
if (typeof user !== 'undefined') {
const user = await getSavedCredentials(
loginForm.value.lastUserLoggedIn
);
if (user) {
await webApiService.clearCookies();
delete user.cookies;
relogin(user).then(() => {
@@ -272,24 +279,28 @@ export const useAuthStore = defineStore('Auth', () => {
inputPattern: /[\s\S]{1,32}/
}
)
.then(({ value }) => {
for (const userId in loginForm.value.savedCredentials) {
.then(async ({ value }) => {
let savedCredentials = JSON.parse(
await configRepository.getString(
'savedCredentials',
'{}'
)
);
for (const userId in savedCredentials) {
security
.decrypt(
loginForm.value.savedCredentials[userId]
.loginParams.password,
savedCredentials[userId].loginParams.password,
value
)
.then(async (pt) => {
credentialsToSave.value = {
username:
loginForm.value.savedCredentials[userId]
.loginParams.username,
savedCredentials[userId].loginParams
.username,
password: pt
};
await updateStoredUser(
loginForm.value.savedCredentials[userId]
.user
savedCredentials[userId].user
);
await configRepository.setBool(
'enablePrimaryPassword',
@@ -320,23 +331,19 @@ export const useAuthStore = defineStore('Auth', () => {
enablePrimaryPasswordDialog.value.visible = false;
if (advancedSettingsStore.enablePrimaryPassword) {
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
.encrypt(
loginForm.value.savedCredentials[userId].loginParams
.password,
key
)
.encrypt(savedCredentials[userId].loginParams.password, key)
.then((ct) => {
credentialsToSave.value = {
username:
loginForm.value.savedCredentials[userId]
.loginParams.username,
savedCredentials[userId].loginParams.username,
password: ct
};
updateStoredUser(
loginForm.value.savedCredentials[userId].user
);
updateStoredUser(savedCredentials[userId].user);
});
}
}
@@ -366,7 +373,6 @@ export const useAuthStore = defineStore('Auth', () => {
savedCredentials[user.id].cookies =
await webApiService.getCookies();
}
loginForm.value.savedCredentials = savedCredentials;
const jsonCredentialsArray = JSON.stringify(savedCredentials);
await configRepository.setString(
'savedCredentials',
@@ -531,9 +537,10 @@ export const useAuthStore = defineStore('Auth', () => {
false
);
}
loginForm.value.savedCredentials = savedCredentials;
const jsonCredentials = JSON.stringify(savedCredentials);
await configRepository.setString('savedCredentials', jsonCredentials);
await configRepository.setString(
'savedCredentials',
JSON.stringify(savedCredentials)
);
new Noty({
type: 'success',
text: 'Account removed.'
@@ -571,12 +578,15 @@ export const useAuthStore = defineStore('Auth', () => {
inputPattern: /[\s\S]{1,32}/
}
)
.then(({ value }) => {
.then(async ({ value }) => {
const savedCredentials = JSON.parse(
await configRepository.getString(
'savedCredentials'
)
);
const saveCredential =
loginForm.value.savedCredentials[
Object.keys(
loginForm.value.savedCredentials
)[0]
savedCredentials[
Object.keys(savedCredentials)[0]
];
security
.decrypt(
@@ -823,9 +833,8 @@ export const useAuthStore = defineStore('Auth', () => {
return;
}
attemptingAutoLogin.value = true;
const user =
loginForm.value.savedCredentials[loginForm.value.lastUserLoggedIn];
if (typeof user === 'undefined') {
const user = getSavedCredentials(loginForm.value.lastUserLoggedIn);
if (!user) {
attemptingAutoLogin.value = false;
return;
}

View File

@@ -92,19 +92,19 @@
>
</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">
{{ t('view.login.savedAccounts') }}
</h2>
<div class="x-scroll-wrapper" style="margin-top: 10px">
<div class="x-saved-account-list">
<div
v-for="user in loginForm.savedCredentials"
v-for="user in savedCredentials"
:key="user.user.id"
class="x-friend-item"
@click="relogin(user)">
@click="clickSavedLogin(user)">
<div class="avatar">
<img :src="userImage(user.user)" loading="lazy" />
</div>
@@ -119,7 +119,7 @@
:icon="Delete"
style="margin-left: 10px"
circle
@click.stop="deleteSavedLogin(user.user.id)"></el-button>
@click.stop="clickDeleteSavedLogin(user.user.id)"></el-button>
</div>
</div>
</div>
@@ -149,13 +149,16 @@
<script setup>
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 { useI18n } from 'vue-i18n';
import { useAuthStore, useGeneralSettingsStore, useVRCXUpdaterStore } from '../../stores';
import { openExternalLink, userImage } from '../../shared/utils';
import { AppDebug } from '../../service/appConfig';
import { watchState } from '../../service/watchState';
import configRepository from '../../service/config';
const { showVRCXUpdateDialog } = useVRCXUpdaterStore();
const { loginForm, enableCustomEndpoint } = storeToRefs(useAuthStore());
@@ -165,18 +168,49 @@
const { t } = useI18n();
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() {
if (loginFormRef.value) {
loginFormRef.value.validate((valid) => {
valid && login();
loginFormRef.value.validate(async (valid) => {
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(() => {
if (loginFormRef.value) {
loginFormRef.value.resetFields();
}
savedCredentials.value = {};
});
</script>