mirror of
https://github.com/mealie-recipes/mealie.git
synced 2025-07-09 03:04:54 -04:00
Merge pull request #3100 from Kuchenpirat/feat-frontend-access-controll
feat: frontend access controll
This commit is contained in:
commit
a7775ea7ef
@ -1,8 +1,8 @@
|
||||
interface AuthRedirectParams {
|
||||
interface AdminRedirectParams {
|
||||
$auth: any
|
||||
redirect: (path: string) => void
|
||||
}
|
||||
export default function ({ $auth, redirect }: AuthRedirectParams) {
|
||||
export default function ({ $auth, redirect }: AdminRedirectParams) {
|
||||
// If the user is not an admin redirect to the home page
|
||||
if (!$auth.user.admin) {
|
||||
return redirect("/")
|
||||
|
11
frontend/middleware/advanced-only.ts
Normal file
11
frontend/middleware/advanced-only.ts
Normal file
@ -0,0 +1,11 @@
|
||||
interface AdvancedOnlyRedirectParams {
|
||||
$auth: any
|
||||
redirect: (path: string) => void
|
||||
}
|
||||
export default function ({ $auth, redirect }: AdvancedOnlyRedirectParams) {
|
||||
// If the user is not allowed to access advanced features redirect to the home page
|
||||
if (!$auth.user.advanced) {
|
||||
console.warn("User is not allowed to access advanced features");
|
||||
return redirect("/")
|
||||
}
|
||||
}
|
12
frontend/middleware/can-manage-only.ts
Normal file
12
frontend/middleware/can-manage-only.ts
Normal file
@ -0,0 +1,12 @@
|
||||
interface CanManageRedirectParams {
|
||||
$auth: any
|
||||
redirect: (path: string) => void
|
||||
}
|
||||
export default function ({ $auth, redirect }: CanManageRedirectParams) {
|
||||
// If the user is not allowed to manage group settings redirect to the home page
|
||||
console.log($auth.user)
|
||||
if (!$auth.user.canManage) {
|
||||
console.warn("User is not allowed to manage group settings");
|
||||
return redirect("/")
|
||||
}
|
||||
}
|
11
frontend/middleware/can-organize-only.ts
Normal file
11
frontend/middleware/can-organize-only.ts
Normal file
@ -0,0 +1,11 @@
|
||||
interface CanOrganizeRedirectParams {
|
||||
$auth: any
|
||||
redirect: (path: string) => void
|
||||
}
|
||||
export default function ({ $auth, redirect }: CanOrganizeRedirectParams) {
|
||||
// If the user is not allowed to organize redirect to the home page
|
||||
if (!$auth.user.canOrganize) {
|
||||
console.warn("User is not allowed to organize data");
|
||||
return redirect("/")
|
||||
}
|
||||
}
|
12
frontend/middleware/group-only.ts
Normal file
12
frontend/middleware/group-only.ts
Normal file
@ -0,0 +1,12 @@
|
||||
interface GroupOnlyRedirectParams {
|
||||
$auth: any
|
||||
route: any
|
||||
redirect: (path: string) => void
|
||||
}
|
||||
|
||||
export default function ({ $auth, route, redirect }: GroupOnlyRedirectParams) {
|
||||
// this can only be used for routes that have a groupSlug parameter (e.g. /g/:groupSlug/...)
|
||||
if (route.params.groupSlug !== $auth.user.groupSlug) {
|
||||
redirect("/")
|
||||
}
|
||||
}
|
@ -98,31 +98,23 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, reactive, ref, useRouter } from "@nuxtjs/composition-api";
|
||||
|
||||
import { defineComponent, reactive, ref } from "@nuxtjs/composition-api";
|
||||
import draggable from "vuedraggable";
|
||||
import { useCookbooks } from "@/composables/use-group-cookbooks";
|
||||
import { useLoggedInState } from "~/composables/use-logged-in-state";
|
||||
import CookbookEditor from "~/components/Domain/Cookbook/CookbookEditor.vue";
|
||||
import { ReadCookBook } from "~/lib/api/types/cookbook";
|
||||
|
||||
export default defineComponent({
|
||||
components: { CookbookEditor, draggable },
|
||||
middleware: ["auth", "group-only"],
|
||||
setup() {
|
||||
const { isOwnGroup, loggedIn } = useLoggedInState();
|
||||
const router = useRouter();
|
||||
|
||||
if (!(loggedIn.value && isOwnGroup.value)) {
|
||||
router.back();
|
||||
}
|
||||
|
||||
const dialogStates = reactive({
|
||||
create: false,
|
||||
delete: false,
|
||||
});
|
||||
|
||||
const { cookbooks, actions } = useCookbooks();
|
||||
|
||||
|
||||
|
||||
// create
|
||||
const createTarget = ref<ReadCookBook | null>(null);
|
||||
async function createCookbook() {
|
||||
@ -146,7 +138,6 @@ export default defineComponent({
|
||||
dialogStates.delete = false;
|
||||
deleteTarget.value = null;
|
||||
}
|
||||
|
||||
return {
|
||||
cookbooks,
|
||||
actions,
|
||||
|
@ -133,6 +133,7 @@ export default defineComponent({
|
||||
RecipeIngredientEditor,
|
||||
draggable
|
||||
},
|
||||
middleware: ["auth", "group-only"],
|
||||
setup() {
|
||||
const { $auth } = useContext();
|
||||
const panels = ref<number[]>([]);
|
||||
|
@ -33,6 +33,7 @@ import AdvancedOnly from "~/components/global/AdvancedOnly.vue";
|
||||
|
||||
export default defineComponent({
|
||||
components: { AdvancedOnly },
|
||||
middleware: ["auth", "group-only"],
|
||||
setup() {
|
||||
const { $auth, $globals, i18n } = useContext();
|
||||
|
||||
|
@ -22,6 +22,7 @@ export default defineComponent({
|
||||
components: {
|
||||
RecipeOrganizerPage,
|
||||
},
|
||||
middleware: ["auth", "group-only"],
|
||||
setup() {
|
||||
const { items, actions } = useCategoryStore();
|
||||
|
||||
|
@ -22,6 +22,7 @@ export default defineComponent({
|
||||
components: {
|
||||
RecipeOrganizerPage,
|
||||
},
|
||||
middleware: ["auth", "group-only"],
|
||||
setup() {
|
||||
const { items, actions } = useTagStore();
|
||||
|
||||
|
@ -17,6 +17,7 @@ import RecipeTimeline from "~/components/Domain/Recipe/RecipeTimeline.vue";
|
||||
|
||||
export default defineComponent({
|
||||
components: { RecipeTimeline },
|
||||
middleware: ["auth", "group-only"],
|
||||
setup() {
|
||||
const api = useUserApi();
|
||||
const ready = ref<boolean>(false);
|
||||
|
@ -22,6 +22,7 @@ export default defineComponent({
|
||||
components: {
|
||||
RecipeOrganizerPage,
|
||||
},
|
||||
middleware: ["auth", "group-only"],
|
||||
setup() {
|
||||
const toolStore = useToolStore();
|
||||
const dialog = ref(false);
|
||||
|
@ -30,6 +30,7 @@
|
||||
import { computed, defineComponent, useContext, useRoute } from "@nuxtjs/composition-api";
|
||||
|
||||
export default defineComponent({
|
||||
middleware: ["auth", "can-organize-only"],
|
||||
props: {
|
||||
value: {
|
||||
type: Boolean,
|
||||
|
@ -227,7 +227,6 @@ import { useFoodStore, useLabelStore } from "~/composables/store";
|
||||
import { VForm } from "~/types/vuetify";
|
||||
|
||||
export default defineComponent({
|
||||
|
||||
components: { MultiPurposeLabel, RecipeDataAliasManagerDialog },
|
||||
setup() {
|
||||
const userApi = useUserApi();
|
||||
|
@ -65,6 +65,7 @@ import { useGroupSelf } from "~/composables/use-groups";
|
||||
import { ReadGroupPreferences } from "~/lib/api/types/group";
|
||||
|
||||
export default defineComponent({
|
||||
middleware: ["auth", "can-manage-only"],
|
||||
setup() {
|
||||
const { group, actions: groupActions } = useGroupSelf();
|
||||
|
||||
|
@ -46,6 +46,7 @@ import { isSameDay, addDays, parseISO } from "date-fns";
|
||||
import { useMealplans } from "~/composables/use-group-mealplan";
|
||||
|
||||
export default defineComponent({
|
||||
middleware: ["auth"],
|
||||
setup() {
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
|
@ -98,6 +98,7 @@ export default defineComponent({
|
||||
GroupMealPlanRuleForm,
|
||||
RecipeChips,
|
||||
},
|
||||
middleware: ["auth"],
|
||||
props: {
|
||||
value: {
|
||||
type: Boolean,
|
||||
|
@ -78,6 +78,7 @@ export default defineComponent({
|
||||
components: {
|
||||
UserAvatar,
|
||||
},
|
||||
middleware: ["auth"],
|
||||
setup() {
|
||||
const api = useUserApi();
|
||||
|
||||
|
@ -85,6 +85,7 @@ const MIGRATIONS = {
|
||||
};
|
||||
|
||||
export default defineComponent({
|
||||
middleware: ["auth", "advanced-only"],
|
||||
setup() {
|
||||
const { $globals, i18n } = useContext();
|
||||
|
||||
|
@ -124,6 +124,7 @@ interface OptionSection {
|
||||
}
|
||||
|
||||
export default defineComponent({
|
||||
middleware: ["auth", "advanced-only"],
|
||||
setup() {
|
||||
const api = useUserApi();
|
||||
|
||||
|
@ -34,6 +34,7 @@ import { useUserApi } from "~/composables/api";
|
||||
import { ReportOut } from "~/lib/api/types/reports";
|
||||
|
||||
export default defineComponent({
|
||||
middleware: "auth",
|
||||
setup() {
|
||||
const route = useRoute();
|
||||
const id = route.value.params.id;
|
||||
|
@ -50,6 +50,7 @@ import GroupWebhookEditor from "~/components/Domain/Group/GroupWebhookEditor.vue
|
||||
|
||||
export default defineComponent({
|
||||
components: { GroupWebhookEditor },
|
||||
middleware: ["auth", "advanced-only"],
|
||||
setup() {
|
||||
const { actions, webhooks } = useGroupWebhooks();
|
||||
|
||||
|
@ -235,6 +235,7 @@ export default defineComponent({
|
||||
RecipeList,
|
||||
ShoppingListItemEditor,
|
||||
},
|
||||
middleware: "auth",
|
||||
setup() {
|
||||
const { $auth, i18n } = useContext();
|
||||
const preferences = useShoppingListPreferences();
|
||||
|
@ -44,6 +44,7 @@ import { useUserApi } from "~/composables/api";
|
||||
import { useAsyncKey } from "~/composables/use-utils";
|
||||
|
||||
export default defineComponent({
|
||||
middleware: "auth",
|
||||
setup() {
|
||||
const { $auth } = useContext();
|
||||
const userApi = useUserApi();
|
||||
|
@ -14,6 +14,7 @@ import { useAsyncKey } from "~/composables/use-utils";
|
||||
|
||||
export default defineComponent({
|
||||
components: { RecipeCardSection },
|
||||
middleware: "auth",
|
||||
setup() {
|
||||
const api = useUserApi();
|
||||
const route = useRoute();
|
||||
|
@ -69,6 +69,7 @@ import { useUserApi } from "~/composables/api";
|
||||
import { VForm } from "~/types/vuetify";
|
||||
|
||||
export default defineComponent({
|
||||
middleware: ["auth", "advanced-only"],
|
||||
setup() {
|
||||
const nuxtContext = useContext();
|
||||
|
||||
|
@ -135,6 +135,7 @@ export default defineComponent({
|
||||
UserAvatar,
|
||||
UserPasswordStrength,
|
||||
},
|
||||
middleware: "auth",
|
||||
setup() {
|
||||
const { $auth } = useContext();
|
||||
const user = computed(() => $auth.user as unknown as UserOut);
|
||||
|
@ -113,7 +113,7 @@
|
||||
<p>{{ $t('profile.group-description') }}</p>
|
||||
</div>
|
||||
<v-row tag="section">
|
||||
<v-col cols="12" sm="12" md="6">
|
||||
<v-col v-if="$auth.user.canManage" cols="12" sm="12" md="6">
|
||||
<UserProfileLinkCard
|
||||
:link="{ text: $tc('profile.group-settings'), to: `/group` }"
|
||||
:image="require('~/static/svgs/manage-group-settings.svg')"
|
||||
@ -162,17 +162,16 @@
|
||||
</UserProfileLinkCard>
|
||||
</v-col>
|
||||
</AdvancedOnly>
|
||||
<AdvancedOnly>
|
||||
<v-col cols="12" sm="12" md="6">
|
||||
<UserProfileLinkCard
|
||||
:link="{ text: $tc('profile.manage-data'), to: `/group/data/foods` }"
|
||||
:image="require('~/static/svgs/manage-recipes.svg')"
|
||||
>
|
||||
<template #title> {{ $t('profile.manage-data') }} </template>
|
||||
{{ $t('profile.manage-data-description') }}
|
||||
</UserProfileLinkCard>
|
||||
</v-col>
|
||||
</AdvancedOnly>
|
||||
<!-- $auth.user.canOrganize should not be null because of the auth middleware -->
|
||||
<v-col v-if="$auth.user.canOrganize" cols="12" sm="12" md="6">
|
||||
<UserProfileLinkCard
|
||||
:link="{ text: $tc('profile.manage-data'), to: `/group/data/foods` }"
|
||||
:image="require('~/static/svgs/manage-recipes.svg')"
|
||||
>
|
||||
<template #title> {{ $t('profile.manage-data') }} </template>
|
||||
{{ $t('profile.manage-data-description') }}
|
||||
</UserProfileLinkCard>
|
||||
</v-col>
|
||||
<AdvancedOnly>
|
||||
<v-col cols="12" sm="12" md="6">
|
||||
<UserProfileLinkCard
|
||||
@ -208,6 +207,7 @@ export default defineComponent({
|
||||
UserAvatar,
|
||||
StatsCards,
|
||||
},
|
||||
middleware: "auth",
|
||||
scrollToTop: true,
|
||||
setup() {
|
||||
const { $auth, i18n } = useContext();
|
||||
|
Loading…
x
Reference in New Issue
Block a user