mirror of
https://github.com/mealie-recipes/mealie.git
synced 2026-01-31 04:53:11 -05:00
fix: disable invitations when password login is disabled (#6781)
This commit is contained in:
@@ -35,6 +35,7 @@
|
||||
{{ $t("general.create") }}
|
||||
</BaseButton>
|
||||
<BaseButton
|
||||
v-if="$appInfo.allowPasswordLogin"
|
||||
class="mr-2"
|
||||
color="info"
|
||||
:icon="$globals.icons.link"
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
<ToggleState tag="article">
|
||||
<template #activator="{ toggle, state }">
|
||||
<v-btn
|
||||
v-if="!state"
|
||||
v-if="!state && $appInfo.allowPasswordLogin"
|
||||
color="info"
|
||||
class="mt-2 mb-n3"
|
||||
@click="toggle"
|
||||
@@ -37,7 +37,7 @@
|
||||
{{ $t("settings.change-password") }}
|
||||
</v-btn>
|
||||
<v-btn
|
||||
v-else
|
||||
v-else-if="$appInfo.allowPasswordLogin"
|
||||
color="info"
|
||||
class="mt-2 mb-n3"
|
||||
@click="toggle"
|
||||
@@ -111,7 +111,7 @@
|
||||
class="mt-10"
|
||||
:title="$t('settings.change-password')"
|
||||
/>
|
||||
<v-card variant="outlined">
|
||||
<v-card variant="outlined" style="border-color: lightgrey;">
|
||||
<v-card-text class="pb-0">
|
||||
<v-form ref="passChange">
|
||||
<v-text-field
|
||||
|
||||
@@ -295,6 +295,7 @@ export default defineNuxtComponent({
|
||||
async setup() {
|
||||
const i18n = useI18n();
|
||||
const $auth = useMealieAuth();
|
||||
const { $appInfo } = useNuxtApp();
|
||||
const route = useRoute();
|
||||
const groupSlug = computed(() => route.params.groupSlug || $auth.user.value?.groupSlug || "");
|
||||
|
||||
@@ -302,7 +303,18 @@ export default defineNuxtComponent({
|
||||
title: i18n.t("settings.profile"),
|
||||
});
|
||||
|
||||
const user = computed<UserOut | null>(() => $auth.user.value);
|
||||
const user = computed<UserOut | null>(() => {
|
||||
const authUser = $auth.user.value;
|
||||
if (!authUser) return null;
|
||||
|
||||
// Override canInvite if password login is disabled
|
||||
const canInvite = !$appInfo.allowPasswordLogin ? false : authUser.canInvite;
|
||||
|
||||
return {
|
||||
...authUser,
|
||||
canInvite,
|
||||
};
|
||||
});
|
||||
|
||||
const inviteDialog = ref(false);
|
||||
const api = useUserApi();
|
||||
|
||||
@@ -2,6 +2,7 @@ from typing import Annotated
|
||||
|
||||
from fastapi import APIRouter, Header, HTTPException, status
|
||||
|
||||
from mealie.core.config import get_app_settings
|
||||
from mealie.core.security import url_safe_token
|
||||
from mealie.routes._base import BaseUserController, controller
|
||||
from mealie.schema.household.invite_token import (
|
||||
@@ -21,10 +22,23 @@ router = APIRouter(prefix="/households/invitations", tags=["Households: Invitati
|
||||
class GroupInvitationsController(BaseUserController):
|
||||
@router.get("", response_model=list[ReadInviteToken])
|
||||
def get_invite_tokens(self):
|
||||
if not self.user.admin:
|
||||
raise HTTPException(
|
||||
status.HTTP_403_FORBIDDEN,
|
||||
detail="Only admins can list invite tokens",
|
||||
)
|
||||
|
||||
return self.repos.group_invite_tokens.page_all(PaginationQuery(page=1, per_page=-1)).items
|
||||
|
||||
@router.post("", response_model=ReadInviteToken, status_code=status.HTTP_201_CREATED)
|
||||
def create_invite_token(self, body: CreateInviteToken):
|
||||
settings = get_app_settings()
|
||||
if not settings.ALLOW_PASSWORD_LOGIN:
|
||||
raise HTTPException(
|
||||
status.HTTP_403_FORBIDDEN,
|
||||
detail="Invitation tokens are disabled when password login is not allowed",
|
||||
)
|
||||
|
||||
if not self.user.can_invite:
|
||||
raise HTTPException(
|
||||
status.HTTP_403_FORBIDDEN,
|
||||
@@ -51,6 +65,19 @@ class GroupInvitationsController(BaseUserController):
|
||||
invite: EmailInvitation,
|
||||
accept_language: Annotated[str | None, Header()] = None,
|
||||
):
|
||||
settings = get_app_settings()
|
||||
if not settings.ALLOW_PASSWORD_LOGIN:
|
||||
raise HTTPException(
|
||||
status.HTTP_403_FORBIDDEN,
|
||||
detail="Invitation email are disabled when password login is not allowed",
|
||||
)
|
||||
|
||||
if not self.user.can_invite:
|
||||
raise HTTPException(
|
||||
status.HTTP_403_FORBIDDEN,
|
||||
detail="This user can't send email invitations",
|
||||
)
|
||||
|
||||
email_service = EmailService(locale=accept_language)
|
||||
url = f"{self.settings.BASE_URL}/register?token={invite.token}"
|
||||
|
||||
|
||||
@@ -9,17 +9,17 @@ from tests.utils.fixture_schemas import TestUser
|
||||
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
def invite(api_client: TestClient, unique_user: TestUser) -> None:
|
||||
def invite(api_client: TestClient, admin_user: TestUser) -> None:
|
||||
# Test Creation
|
||||
r = api_client.post(api_routes.households_invitations, json={"uses": 2}, headers=unique_user.token)
|
||||
r = api_client.post(api_routes.households_invitations, json={"uses": 2}, headers=admin_user.token)
|
||||
assert r.status_code == 201
|
||||
invitation = r.json()
|
||||
return invitation["token"]
|
||||
|
||||
|
||||
def test_get_all_invitation(api_client: TestClient, unique_user: TestUser, invite: str) -> None:
|
||||
def test_get_all_invitation(api_client: TestClient, admin_user: TestUser, invite: str) -> None:
|
||||
# Get All Invites
|
||||
r = api_client.get(api_routes.households_invitations, headers=unique_user.token)
|
||||
r = api_client.get(api_routes.households_invitations, headers=admin_user.token)
|
||||
|
||||
assert r.status_code == 200
|
||||
|
||||
@@ -28,8 +28,8 @@ def test_get_all_invitation(api_client: TestClient, unique_user: TestUser, invit
|
||||
assert len(items) == 1
|
||||
|
||||
for item in items:
|
||||
assert item["groupId"] == unique_user.group_id
|
||||
assert item["householdId"] == unique_user.household_id
|
||||
assert item["groupId"] == admin_user.group_id
|
||||
assert item["householdId"] == admin_user.household_id
|
||||
assert item["token"] == invite
|
||||
|
||||
|
||||
@@ -59,7 +59,7 @@ def register_user(api_client: TestClient, invite: str):
|
||||
return registration, response
|
||||
|
||||
|
||||
def test_group_invitation_link(api_client: TestClient, unique_user: TestUser, invite: str):
|
||||
def test_group_invitation_link(api_client: TestClient, admin_user: TestUser, invite: str):
|
||||
registration, r = register_user(api_client, invite)
|
||||
assert r.status_code == 201
|
||||
|
||||
@@ -75,8 +75,8 @@ def test_group_invitation_link(api_client: TestClient, unique_user: TestUser, in
|
||||
r = api_client.get(api_routes.users_self, headers={"Authorization": f"Bearer {token}"})
|
||||
|
||||
assert r.status_code == 200
|
||||
assert r.json()["groupId"] == unique_user.group_id
|
||||
assert r.json()["householdId"] == unique_user.household_id
|
||||
assert r.json()["groupId"] == admin_user.group_id
|
||||
assert r.json()["householdId"] == admin_user.household_id
|
||||
|
||||
|
||||
def test_group_invitation_delete_after_uses(api_client: TestClient, invite: str) -> None:
|
||||
|
||||
Reference in New Issue
Block a user