web/satellite: clear vuex state on session timeout

We have to clear vuex app state on session timeout because user's session gets invalidated and user is redirected to login screen.

Issue:
https://github.com/storj/storj/issues/5370

Change-Id: Id654056331c81fac0b46ed90eccea0a044e4e1c9
This commit is contained in:
Vitalii 2022-12-15 13:15:09 +02:00 committed by Storj Robot
parent bb170a9d57
commit 92a757cf3f
8 changed files with 102 additions and 15 deletions

View File

@ -143,17 +143,20 @@ export default class AccountArea extends Vue {
return;
}
await this.$store.dispatch(PM_ACTIONS.CLEAR);
await this.$store.dispatch(PROJECTS_ACTIONS.CLEAR);
await this.$store.dispatch(USER_ACTIONS.CLEAR);
await this.$store.dispatch(ACCESS_GRANTS_ACTIONS.CLEAR);
await this.$store.dispatch(ACCESS_GRANTS_ACTIONS.STOP_ACCESS_GRANTS_WEB_WORKER);
await this.$store.dispatch(NOTIFICATION_ACTIONS.CLEAR);
await this.$store.dispatch(BUCKET_ACTIONS.CLEAR);
await this.$store.dispatch(OBJECTS_ACTIONS.CLEAR);
await this.$store.dispatch(APP_STATE_ACTIONS.CLOSE_POPUPS);
await this.$store.dispatch(PAYMENTS_ACTIONS.CLEAR_PAYMENT_INFO);
await this.$store.dispatch(AB_TESTING_ACTIONS.RESET);
await Promise.all([
this.$store.dispatch(PM_ACTIONS.CLEAR),
this.$store.dispatch(PROJECTS_ACTIONS.CLEAR),
this.$store.dispatch(USER_ACTIONS.CLEAR),
this.$store.dispatch(ACCESS_GRANTS_ACTIONS.STOP_ACCESS_GRANTS_WEB_WORKER),
this.$store.dispatch(ACCESS_GRANTS_ACTIONS.CLEAR),
this.$store.dispatch(NOTIFICATION_ACTIONS.CLEAR),
this.$store.dispatch(BUCKET_ACTIONS.CLEAR),
this.$store.dispatch(OBJECTS_ACTIONS.CLEAR),
this.$store.dispatch(APP_STATE_ACTIONS.CLOSE_POPUPS),
this.$store.dispatch(PAYMENTS_ACTIONS.CLEAR_PAYMENT_INFO),
this.$store.dispatch(AB_TESTING_ACTIONS.RESET),
this.$store.dispatch('files/clear'),
]);
LocalData.removeUserId();
}

View File

@ -206,6 +206,12 @@ export function makeAccessGrantsModule(api: AccessGrantsApi, workerFactory?: Acc
state.permissionNotBefore = null;
state.permissionNotAfter = null;
state.gatewayCredentials = new EdgeCredentials();
state.isDownload = true;
state.isUpload = true;
state.isList = true;
state.isDelete = true;
state.accessGrantsWebWorker = null;
state.isAccessGrantsWebWorkerReady = false;
},
},
actions: {

View File

@ -208,6 +208,35 @@ export const appStateModule = {
state.appState.isAGDatePickerShown = false;
state.appState.isChartsDatePickerShown = false;
state.appState.isBucketNamesDropdownShown = false;
state.appState.isAddTeamMembersModalShown = false;
state.appState.isEditProfileModalShown = false;
state.appState.isChangePasswordModalShown = false;
state.appState.isUploadCancelPopupVisible = false;
state.appState.isSuccessfulPasswordResetShown = false;
state.appState.isCreateProjectPromptModalShown = false;
state.appState.isCreateProjectModalShown = false;
state.appState.isAddPMModalShown = false;
state.appState.isOpenBucketModalShown = false;
state.appState.isMFARecoveryModalShown = false;
state.appState.isEnableMFAModalShown = false;
state.appState.isDisableMFAModalShown = false;
state.appState.isAddTokenFundsModalShown = false;
state.appState.isShareBucketModalShown = false;
state.appState.isShareObjectModalShown = false;
state.appState.isDeleteBucketModalShown = false;
state.appState.isNewFolderModalShown = false;
state.appState.isCreateProjectPassphraseModalShown = false;
state.appState.isManageProjectPassphraseModalShown = false;
state.appState.isObjectDetailsModalShown = false;
state.appState.isAddCouponModalShown = false;
state.appState.isNewBillingAddCouponModalShown = false;
state.appState.onbAGStepBackRoute = '';
state.appState.onbAPIKeyStepBackRoute = '';
state.appState.onbCleanApiKey = '';
state.appState.onbApiKey = '';
state.appState.setDefaultPaymentMethodID = '';
state.appState.deletePaymentMethodID = '';
state.appState.onbSelectedOs = null;
},
[APP_STATE_MUTATIONS.CHANGE_STATE](state: State, newFetchState: AppState): void {
state.appState.fetchState = newFetchState;

View File

@ -288,6 +288,29 @@ export const makeFilesModule = (): FilesModule => ({
addUploadToChain(state: FilesState, fn) {
state.uploadChain = state.uploadChain.then(fn);
},
clear(state: FilesState) {
state.s3 = null;
state.accessKey = null;
state.path = '';
state.bucket = '';
state.browserRoot = '/';
state.files = [];
state.uploadChain = Promise.resolve();
state.uploading = [];
state.selectedAnchorFile = null;
state.unselectedAnchorFile = null;
state.selectedFiles = [];
state.shiftSelectedFiles = [];
state.filesToBeDeleted = [];
state.fetchSharedLink = () => 'javascript:null';
state.fetchPreviewAndMapUrl = () => 'javascript:null';
state.openedDropdown = null;
state.headingSorted = 'name';
state.orderBy = 'asc';
state.openModalOnFirstUpload = false;
state.objectPathForModal = '';
},
},
actions: {
async list({ commit, state }, path = state.path) {
@ -726,5 +749,9 @@ export const makeFilesModule = (): FilesModule => ({
dispatch('clearAllSelectedFiles');
}
},
clear({ commit }) {
commit('clear');
},
},
});

View File

@ -153,6 +153,7 @@ export function makeObjectsModule(): StoreModule<ObjectsState, ObjectsContext> {
});
state.bucketsList = [];
state.fileComponentBucketName = '';
state.leaveRoute = '';
},
},
actions: {

View File

@ -188,6 +188,8 @@ export function makeProjectsModule(api: ProjectsApi): StoreModule<ProjectsState,
state.settledBandwidthChartData = [];
state.chartDataSince = new Date();
state.chartDataBefore = new Date();
state.cursor = new ProjectsCursor();
state.page = new ProjectsPage();
},
[SET_PAGE_NUMBER](state: ProjectsState, pageNumber: number) {
state.cursor.page = pageNumber;

View File

@ -78,6 +78,8 @@ export function makeUsersModule(api: UsersApi): StoreModule<UsersState, UsersCon
[CLEAR](state: UsersState): void {
state.user = new User();
state.user.projectLimit = 1;
state.userMFASecret = '';
state.userMFARecoveryCodes = [];
},
[UPDATE_USER](state: UsersState, user: UpdatedUser): void {
state.user.fullName = user.fullName;

View File

@ -78,7 +78,7 @@ import { USER_ACTIONS } from '@/store/modules/users';
import { CouponType } from '@/types/coupons';
import { CreditCard } from '@/types/payments';
import { Project } from '@/types/projects';
import { APP_STATE_ACTIONS } from '@/utils/constants/actionNames';
import { APP_STATE_ACTIONS, NOTIFICATION_ACTIONS, PM_ACTIONS } from '@/utils/constants/actionNames';
import { APP_STATE_MUTATIONS } from '@/store/mutationConstants';
import { AppState } from '@/utils/constants/appStateEnum';
import { LocalData } from '@/utils/localData';
@ -90,6 +90,8 @@ import eventBus from '@/utils/eventBus';
import { ABTestValues } from '@/types/abtesting';
import { AB_TESTING_ACTIONS } from '@/store/modules/abTesting';
import { AnalyticsErrorEventSource } from '@/utils/constants/analyticsEventNames';
import { BUCKET_ACTIONS } from '@/store/modules/buckets';
import { OBJECTS_ACTIONS } from '@/store/modules/objects';
import ProjectInfoBar from '@/components/infoBars/ProjectInfoBar.vue';
import BillingNotification from '@/components/notifications/BillingNotification.vue';
@ -139,7 +141,7 @@ export default class DashboardArea extends Vue {
private inactivityModalShown = false;
private inactivityModalTime = 60000;
private ACTIVITY_REFRESH_TIME_LIMIT = 180000;
private sessionRefreshInterval: number = this.sessionDuration/2;
private sessionRefreshInterval: number = this.sessionDuration / 2;
private sessionRefreshTimerId: ReturnType<typeof setTimeout> | null;
private isSessionActive = false;
private isSessionRefreshing = false;
@ -217,7 +219,7 @@ export default class DashboardArea extends Vue {
*/
public async mounted(): Promise<void> {
this.$store.subscribeAction((action) => {
if (action.type == USER_ACTIONS.CLEAR) this.clearSessionTimers();
if (action.type === USER_ACTIONS.CLEAR) this.clearSessionTimers();
});
if (LocalData.getBillingNotificationAcknowledged()) {
@ -503,6 +505,21 @@ export default class DashboardArea extends Vue {
await this.$notify.error(error.message, AnalyticsErrorEventSource.OVERALL_SESSION_EXPIRED_ERROR);
}
await Promise.all([
this.$store.dispatch(PM_ACTIONS.CLEAR),
this.$store.dispatch(PROJECTS_ACTIONS.CLEAR),
this.$store.dispatch(USER_ACTIONS.CLEAR),
this.$store.dispatch(ACCESS_GRANTS_ACTIONS.STOP_ACCESS_GRANTS_WEB_WORKER),
this.$store.dispatch(ACCESS_GRANTS_ACTIONS.CLEAR),
this.$store.dispatch(NOTIFICATION_ACTIONS.CLEAR),
this.$store.dispatch(BUCKET_ACTIONS.CLEAR),
this.$store.dispatch(OBJECTS_ACTIONS.CLEAR),
this.$store.dispatch(APP_STATE_ACTIONS.CLOSE_POPUPS),
this.$store.dispatch(PAYMENTS_ACTIONS.CLEAR_PAYMENT_INFO),
this.$store.dispatch(AB_TESTING_ACTIONS.RESET),
this.$store.dispatch('files/clear'),
]);
}
/**
@ -511,7 +528,7 @@ export default class DashboardArea extends Vue {
private async onSessionActivity(): Promise<void> {
if (this.inactivityModalShown || this.isSessionActive) return;
if (this.sessionRefreshTimerId == null && !this.isSessionRefreshing) {
if (this.sessionRefreshTimerId === null && !this.isSessionRefreshing) {
await this.refreshSession();
}
this.isSessionActive = true;