fix: Home Doesn't Load For Non-Admin Users (#2556)

* added non-admin route for fetching current group

* simplified frontend group slug fetching

* exposed public link even if user can't invite

* 🧹
This commit is contained in:
Michael Genson 2023-09-19 12:06:39 -05:00 committed by GitHub
parent 15c6df88ab
commit 3e5596f898
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 27 additions and 43 deletions

View File

@ -52,7 +52,6 @@
show-print show-print
:menu-top="false" :menu-top="false"
:name="recipe.name" :name="recipe.name"
:group-id="recipe.groupId"
:slug="recipe.slug" :slug="recipe.slug"
:menu-icon="$globals.icons.dotsVertical" :menu-icon="$globals.icons.dotsVertical"
fab fab

View File

@ -271,15 +271,6 @@ export default defineComponent({
type: Number, type: Number,
default: 1, default: 1,
}, },
/**
* Optional group ID prop that is only _required_ when the
* public URL is requested. If the public URL button is pressed
* and the groupId is not set, an error will be thrown.
*/
groupId: {
type: String,
default: "",
},
}, },
setup(props, context) { setup(props, context) {
const api = useUserApi(); const api = useUserApi();
@ -517,18 +508,17 @@ export default defineComponent({
const groupSlug = ref<string>(""); const groupSlug = ref<string>("");
async function setGroupSlug() { async function setGroupSlug() {
if (!props.groupId) { if (groupSlug.value) {
groupSlug.value = props.groupId;
return; return;
} }
const {data} = await api.groups.getOne(props.groupId); const { data } = await api.users.getSelfGroup();
if (!data) { if (data) {
groupSlug.value = props.groupId; groupSlug.value = data.slug;
return; } else {
// @ts-ignore this will either be a string or undefined
groupSlug.value = $auth.user?.groupId
} }
groupSlug.value = data.slug;
} }
// Note: Print is handled as an event in the parent component // Note: Print is handled as an event in the parent component
@ -560,14 +550,9 @@ export default defineComponent({
state.shareDialog = true; state.shareDialog = true;
}, },
publicUrl: async () => { publicUrl: async () => {
if (!props.groupId) { await setGroupSlug();
alert.error("Unknown group ID");
console.error("prop `groupId` is required when requesting a public URL");
return;
}
if (!groupSlug.value) { if (!groupSlug.value) {
await setGroupSlug(); return;
} }
copyText(`${window.location.origin}/explore/recipes/${groupSlug.value}/${props.slug}`); copyText(`${window.location.origin}/explore/recipes/${groupSlug.value}/${props.slug}`);

View File

@ -1,7 +1,9 @@
import { BaseCRUDAPI } from "../base/base-clients"; import { BaseCRUDAPI } from "../base/base-clients";
import { RequestResponse } from "../types/non-generated";
import { import {
ChangePassword, ChangePassword,
DeleteTokenResponse, DeleteTokenResponse,
GroupInDB,
LongLiveTokenIn, LongLiveTokenIn,
LongLiveTokenOut, LongLiveTokenOut,
ResetPassword, ResetPassword,
@ -15,6 +17,7 @@ const prefix = "/api";
const routes = { const routes = {
usersSelf: `${prefix}/users/self`, usersSelf: `${prefix}/users/self`,
groupsSelf: `${prefix}/users/self/group`,
passwordReset: `${prefix}/users/reset-password`, passwordReset: `${prefix}/users/reset-password`,
passwordChange: `${prefix}/users/password`, passwordChange: `${prefix}/users/password`,
users: `${prefix}/users`, users: `${prefix}/users`,
@ -33,6 +36,10 @@ export class UserApi extends BaseCRUDAPI<UserIn, UserOut, UserBase> {
baseRoute: string = routes.users; baseRoute: string = routes.users;
itemRoute = (itemid: string) => routes.usersId(itemid); itemRoute = (itemid: string) => routes.usersId(itemid);
async getSelfGroup(): Promise<RequestResponse<GroupInDB>> {
return await this.requests.get(routes.groupsSelf, {});
}
async addFavorite(id: string, slug: string) { async addFavorite(id: string, slug: string) {
return await this.requests.post(routes.usersIdFavoritesSlug(id, slug), {}); return await this.requests.post(routes.usersIdFavoritesSlug(id, slug), {});
} }

View File

@ -5,7 +5,7 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { defineComponent, ref, useContext } from "@nuxtjs/composition-api"; import { defineComponent, ref } from "@nuxtjs/composition-api";
import { invoke } from "@vueuse/core"; import { invoke } from "@vueuse/core";
import { useUserApi } from "~/composables/api/api-client"; import { useUserApi } from "~/composables/api/api-client";
import RecipeExplorerPage from "~/components/Domain/Recipe/RecipeExplorerPage.vue"; import RecipeExplorerPage from "~/components/Domain/Recipe/RecipeExplorerPage.vue";
@ -13,23 +13,12 @@ import RecipeExplorerPage from "~/components/Domain/Recipe/RecipeExplorerPage.vu
export default defineComponent({ export default defineComponent({
components: { RecipeExplorerPage }, components: { RecipeExplorerPage },
setup() { setup() {
const { $auth } = useContext();
const api = useUserApi(); const api = useUserApi();
// @ts-ignore $auth.user is typed as unknown, even though it's a user
const groupId: string | undefined = $auth.user?.groupId;
const groupSlug = ref<string>(); const groupSlug = ref<string>();
invoke(async () => { invoke(async () => {
if (!groupId) { const { data } = await api.users.getSelfGroup();
return; groupSlug.value = data?.slug;
}
const { data } = await api.groups.getOne(groupId);
if (data) {
groupSlug.value = data.slug;
}
}); });
return { return {

View File

@ -8,9 +8,9 @@
{{ $t('profile.description') }} {{ $t('profile.description') }}
<a href="https://hay-kot.github.io/mealie/" target="_blank"> {{ $t('general.learn-more') }} </a> <a href="https://hay-kot.github.io/mealie/" target="_blank"> {{ $t('general.learn-more') }} </a>
</p> </p>
<v-card v-if="$auth.user.canInvite" flat color="background" width="100%" max-width="600px"> <v-card flat color="background" width="100%" max-width="600px">
<v-card-actions class="d-flex justify-center"> <v-card-actions class="d-flex justify-center">
<v-btn outlined rounded @click="getSignupLink()"> <v-btn v-if="$auth.user.canInvite" outlined rounded @click="getSignupLink()">
<v-icon left> <v-icon left>
{{ $globals.icons.createAlt }} {{ $globals.icons.createAlt }}
</v-icon> </v-icon>
@ -257,7 +257,7 @@ export default defineComponent({
return; return;
} }
const { data } = await api.groups.getOne(user.value.groupId); const { data } = await api.users.getSelfGroup();
group.value = data; group.value = data;
}); });

View File

@ -10,7 +10,7 @@ from mealie.routes.users._helpers import assert_user_change_allowed
from mealie.schema.response import ErrorResponse, SuccessResponse from mealie.schema.response import ErrorResponse, SuccessResponse
from mealie.schema.response.pagination import PaginationQuery from mealie.schema.response.pagination import PaginationQuery
from mealie.schema.user import ChangePassword, UserBase, UserIn, UserOut from mealie.schema.user import ChangePassword, UserBase, UserIn, UserOut
from mealie.schema.user.user import UserPagination from mealie.schema.user.user import GroupInDB, UserPagination
user_router = UserAPIRouter(prefix="/users", tags=["Users: CRUD"]) user_router = UserAPIRouter(prefix="/users", tags=["Users: CRUD"])
admin_router = AdminAPIRouter(prefix="/users", tags=["Users: Admin CRUD"]) admin_router = AdminAPIRouter(prefix="/users", tags=["Users: Admin CRUD"])
@ -59,6 +59,10 @@ class UserController(BaseUserController):
def get_logged_in_user(self): def get_logged_in_user(self):
return self.user return self.user
@user_router.get("/self/group", response_model=GroupInDB)
def get_logged_in_user_group(self):
return self.group
@user_router.put("/password") @user_router.put("/password")
def update_password(self, password_change: ChangePassword): def update_password(self, password_change: ChangePassword):
"""Resets the User Password""" """Resets the User Password"""