mirror of
https://github.com/mealie-recipes/mealie.git
synced 2026-07-10 09:40:16 -04:00
fix: clear cached recipe actions on logout to prevent cross-user leak (#7815)
Co-authored-by: Michael Genson <71845777+michael-genson@users.noreply.github.com> Co-authored-by: Michael Genson <genson.michael@gmail.com>
This commit is contained in:
@@ -8,6 +8,11 @@ import type { RecipeSearchQuery } from "~/lib/api/user/recipes/recipe";
|
||||
export const allRecipes = ref<Recipe[]>([]);
|
||||
export const recentRecipes = ref<Recipe[]>([]);
|
||||
|
||||
export function resetRecipes() {
|
||||
allRecipes.value = [];
|
||||
recentRecipes.value = [];
|
||||
}
|
||||
|
||||
function getParams(
|
||||
orderBy: string | null = null,
|
||||
orderDirection = "desc",
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { ref, computed } from "vue";
|
||||
import type { UserOut } from "~/lib/api/types/user";
|
||||
import { clearAllStores } from "~/composables/store";
|
||||
import { clearComposableCaches } from "~/composables/use-clear-composable-caches";
|
||||
import { getTokenCookieOptions } from "~/composables/use-token-cookie";
|
||||
|
||||
interface AuthData {
|
||||
@@ -25,6 +26,11 @@ interface AuthState {
|
||||
const authUser = ref<UserOut | null>(null);
|
||||
const authStatus = ref<"loading" | "authenticated" | "unauthenticated">("loading");
|
||||
|
||||
export function resetAuth() {
|
||||
authUser.value = null;
|
||||
authStatus.value = "unauthenticated";
|
||||
}
|
||||
|
||||
export const useAuthBackend = function (): AuthState {
|
||||
const { $axios } = useNuxtApp();
|
||||
const router = useRouter();
|
||||
@@ -41,8 +47,7 @@ export const useAuthBackend = function (): AuthState {
|
||||
// Only clear token on auth errors, not network errors
|
||||
if (error?.response?.status === 401) {
|
||||
setToken(null);
|
||||
authUser.value = null;
|
||||
authStatus.value = "unauthenticated";
|
||||
resetAuth();
|
||||
if (redirect) {
|
||||
router.push("/login");
|
||||
}
|
||||
@@ -99,12 +104,14 @@ export const useAuthBackend = function (): AuthState {
|
||||
}
|
||||
finally {
|
||||
setToken(null);
|
||||
authUser.value = null;
|
||||
authStatus.value = "unauthenticated";
|
||||
resetAuth();
|
||||
|
||||
// Clear all cached store data to prevent data leakage between users
|
||||
clearAllStores();
|
||||
|
||||
// Clear cached composable refs to prevent data leakage between users
|
||||
clearComposableCaches();
|
||||
|
||||
// Clear Nuxt's useAsyncData cache
|
||||
clearNuxtData();
|
||||
|
||||
|
||||
@@ -12,6 +12,13 @@ const backups = ref<AllBackups>({
|
||||
templates: [],
|
||||
});
|
||||
|
||||
export function resetBackups() {
|
||||
backups.value = {
|
||||
imports: [],
|
||||
templates: [],
|
||||
};
|
||||
}
|
||||
|
||||
function setBackups(newBackups: AllBackups | null) {
|
||||
if (newBackups) {
|
||||
backups.value = newBackups;
|
||||
|
||||
17
frontend/app/composables/use-clear-composable-caches.ts
Normal file
17
frontend/app/composables/use-clear-composable-caches.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import { resetGroupRecipeActions } from "~/composables/use-group-recipe-actions";
|
||||
import { resetGroupSelf } from "~/composables/use-groups";
|
||||
import { resetHouseholdSelf } from "~/composables/use-households";
|
||||
import { resetUserSelfRatings } from "~/composables/use-users/user-ratings";
|
||||
import { resetBackups } from "~/composables/use-backups";
|
||||
import { resetRecipes } from "~/composables/recipes/use-recipes";
|
||||
import { resetUserRegistrationForm } from "~/composables/use-users/user-registration-form";
|
||||
|
||||
export function clearComposableCaches() {
|
||||
resetGroupRecipeActions();
|
||||
resetGroupSelf();
|
||||
resetHouseholdSelf();
|
||||
resetUserSelfRatings();
|
||||
resetBackups();
|
||||
resetRecipes();
|
||||
resetUserRegistrationForm();
|
||||
}
|
||||
@@ -7,6 +7,11 @@ import type { Recipe } from "~/lib/api/types/recipe";
|
||||
const groupRecipeActions = ref<GroupRecipeActionOut[] | null>(null);
|
||||
const loading = ref(false);
|
||||
|
||||
export function resetGroupRecipeActions() {
|
||||
groupRecipeActions.value = null;
|
||||
loading.value = false;
|
||||
}
|
||||
|
||||
export function useGroupRecipeActionData() {
|
||||
const data = reactive({
|
||||
id: "",
|
||||
@@ -85,9 +90,6 @@ export const useGroupRecipeActions = function (
|
||||
loading,
|
||||
{ orderBy: orderBy },
|
||||
),
|
||||
flushStore() {
|
||||
groupRecipeActions.value = [];
|
||||
},
|
||||
};
|
||||
|
||||
return {
|
||||
|
||||
@@ -4,6 +4,11 @@ import type { GroupBase, GroupInDB, GroupSummary } from "~/lib/api/types/user";
|
||||
const groupSelfRef = ref<GroupSummary | null>(null);
|
||||
const loading = ref(false);
|
||||
|
||||
export function resetGroupSelf() {
|
||||
groupSelfRef.value = null;
|
||||
loading.value = false;
|
||||
}
|
||||
|
||||
export const useGroupSelf = function () {
|
||||
const api = useUserApi();
|
||||
const auth = useMealieAuth();
|
||||
|
||||
@@ -4,6 +4,11 @@ import type { HouseholdCreate, HouseholdInDB } from "~/lib/api/types/household";
|
||||
const householdSelfRef = ref<HouseholdInDB | null>(null);
|
||||
const loading = ref(false);
|
||||
|
||||
export function resetHouseholdSelf() {
|
||||
householdSelfRef.value = null;
|
||||
loading.value = false;
|
||||
}
|
||||
|
||||
export const useHouseholdSelf = function () {
|
||||
const api = useUserApi();
|
||||
const auth = useMealieAuth();
|
||||
|
||||
@@ -5,6 +5,12 @@ const userRatings = ref<UserRatingSummary[]>([]);
|
||||
const loading = ref(false);
|
||||
const ready = ref(false);
|
||||
|
||||
export function resetUserSelfRatings() {
|
||||
userRatings.value = [];
|
||||
loading.value = false;
|
||||
ready.value = false;
|
||||
}
|
||||
|
||||
export const useUserSelfRatings = function () {
|
||||
const auth = useMealieAuth();
|
||||
|
||||
|
||||
@@ -10,6 +10,16 @@ const password1 = ref("");
|
||||
const password2 = ref("");
|
||||
const advancedOptions = ref(false);
|
||||
|
||||
export function resetUserRegistrationForm() {
|
||||
domAccountForm.value = null;
|
||||
username.value = "";
|
||||
fullName.value = "";
|
||||
email.value = "";
|
||||
password1.value = "";
|
||||
password2.value = "";
|
||||
advancedOptions.value = false;
|
||||
}
|
||||
|
||||
export const useUserRegistrationForm = () => {
|
||||
const i18n = useI18n();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user