1
0
Fork 0
mirror of https://github.com/mealie-recipes/mealie.git synced 2025-08-02 20:15:24 +02:00

feat(backend): start multi-tenant support (WIP) (#680)

* fix ts types

* feat(code-generation): ♻️ update code-generation formats

* new scope

* add step button

* fix linter error

* update code-generation tags

* feat(backend):  start multi-tenant support

* feat(backend):  group invitation token generation and signup

* refactor(backend): ♻️ move group admin actions to admin router

* set url base to include `/admin`

* feat(frontend):  generate user sign-up links

* test(backend):  refactor test-suite to further decouple tests (WIP)

* feat(backend): 🐛 assign owner on backup import for recipes

* fix(backend): 🐛 assign recipe owner on migration from other service

Co-authored-by: hay-kot <hay-kot@pm.me>
This commit is contained in:
Hayden 2021-09-09 08:51:29 -08:00 committed by GitHub
parent 3c504e7048
commit bdaf758712
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
90 changed files with 1793 additions and 949 deletions

View file

@ -0,0 +1,85 @@
import pytest
from fastapi.testclient import TestClient
from tests.utils.factories import user_registration_factory
from tests.utils.fixture_schemas import TestUser
class Routes:
base = "/api/groups/invitations"
auth_token = "/api/auth/token"
self = "/api/users/self"
register = "/api/users/register"
def item(item_id: int) -> str:
return f"{Routes.base}/{item_id}"
@pytest.fixture(scope="function")
def invite(api_client: TestClient, unique_user: TestUser) -> None:
# Test Creation
r = api_client.post(Routes.base, json={"uses": 2}, headers=unique_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:
# Get All Invites
r = api_client.get(Routes.base, headers=unique_user.token)
assert r.status_code == 200
items = r.json()
assert len(items) == 1
for item in items:
assert item["groupId"] == unique_user.group_id
assert item["token"] == invite
def register_user(api_client, invite):
# Test User can Join Group
registration = user_registration_factory()
registration.group = ""
registration.group_token = invite
response = api_client.post(Routes.register, json=registration.dict(by_alias=True))
print(response.json())
return registration, response
def test_group_invitation_link(api_client: TestClient, unique_user: TestUser, invite: str):
registration, r = register_user(api_client, invite)
assert r.status_code == 201
# Login as new User
form_data = {"username": registration.email, "password": registration.password}
r = api_client.post(Routes.auth_token, form_data)
assert r.status_code == 200
token = r.json().get("access_token")
assert token is not None
# Check user Group is Same
r = api_client.get(Routes.self, headers={"Authorization": f"Bearer {token}"})
assert r.status_code == 200
assert r.json()["groupId"] == unique_user.group_id
def test_group_invitation_delete_after_uses(api_client: TestClient, invite: str) -> None:
# Register First User
_, r = register_user(api_client, invite)
assert r.status_code == 201
# Register Second User
_, r = register_user(api_client, invite)
assert r.status_code == 201
# Check Group Invitation is Deleted
_, r = register_user(api_client, invite)
assert r.status_code == 400

View file

@ -2,6 +2,7 @@ from fastapi.testclient import TestClient
from mealie.schema.group.group_preferences import UpdateGroupPreferences
from tests.utils.assertion_helpers import assert_ignore_keys
from tests.utils.fixture_schemas import TestUser
class Routes:
@ -9,8 +10,8 @@ class Routes:
preferences = "/api/groups/preferences"
def test_get_preferences(api_client: TestClient, admin_token) -> None:
response = api_client.get(Routes.preferences, headers=admin_token)
def test_get_preferences(api_client: TestClient, unique_user: TestUser) -> None:
response = api_client.get(Routes.preferences, headers=unique_user.token)
assert response.status_code == 200
@ -21,8 +22,8 @@ def test_get_preferences(api_client: TestClient, admin_token) -> None:
assert preferences["recipeShowNutrition"] is False
def test_preferences_in_group(api_client: TestClient, admin_token) -> None:
response = api_client.get(Routes.base, headers=admin_token)
def test_preferences_in_group(api_client: TestClient, unique_user: TestUser) -> None:
response = api_client.get(Routes.base, headers=unique_user.token)
assert response.status_code == 200
@ -35,10 +36,10 @@ def test_preferences_in_group(api_client: TestClient, admin_token) -> None:
assert group["preferences"]["recipeShowNutrition"] is False
def test_update_preferences(api_client: TestClient, admin_token) -> None:
def test_update_preferences(api_client: TestClient, unique_user: TestUser) -> None:
new_data = UpdateGroupPreferences(recipe_public=False, recipe_show_nutrition=True)
response = api_client.put(Routes.preferences, json=new_data.dict(), headers=admin_token)
response = api_client.put(Routes.preferences, json=new_data.dict(), headers=unique_user.token)
assert response.status_code == 200

View file

@ -1,6 +1,6 @@
from fastapi.testclient import TestClient
from mealie.schema.user.registration import CreateUserRegistration
from tests.utils.factories import user_registration_factory
class Routes:
@ -9,21 +9,13 @@ class Routes:
def test_user_registration_new_group(api_client: TestClient):
registration = CreateUserRegistration(
group="New Group Name",
email="email@email.com",
username="fake-user-name",
password="fake-password",
password_confirm="fake-password",
advanced=False,
private=False,
)
registration = user_registration_factory()
response = api_client.post(Routes.base, json=registration.dict(by_alias=True))
assert response.status_code == 201
# Login
form_data = {"username": "email@email.com", "password": "fake-password"}
form_data = {"username": registration.email, "password": registration.password}
response = api_client.post(Routes.auth_token, form_data)
assert response.status_code == 200

View file

@ -0,0 +1,63 @@
import pytest
from fastapi.testclient import TestClient
from tests.utils.fixture_schemas import TestUser
class Routes:
base = "/api/groups/webhooks"
def item(item_id: int) -> str:
return f"{Routes.base}/{item_id}"
@pytest.fixture()
def webhook_data():
return {"enabled": True, "name": "Test-Name", "url": "https://my-fake-url.com", "time": "00:00"}
def test_create_webhook(api_client: TestClient, unique_user: TestUser, webhook_data):
response = api_client.post(Routes.base, json=webhook_data, headers=unique_user.token)
assert response.status_code == 200
def test_read_webhook(api_client: TestClient, webhook_data, unique_user: TestUser):
response = api_client.get(Routes.item(1), headers=unique_user.token)
webhook = response.json()
assert webhook["id"] == 1
assert webhook["name"] == webhook_data["name"]
assert webhook["url"] == webhook_data["url"]
assert webhook["time"] == webhook_data["time"]
assert webhook["enabled"] == webhook_data["enabled"]
def test_update_webhook(api_client: TestClient, webhook_data, unique_user: TestUser):
webhook_data["id"] = 1
webhook_data["name"] = "My New Name"
webhook_data["url"] = "https://my-new-fake-url.com"
webhook_data["time"] = "01:00"
webhook_data["enabled"] = False
response = api_client.put(Routes.item(1), json=webhook_data, headers=unique_user.token)
assert response.status_code == 200
updated_webhook = response.json()
assert updated_webhook["name"] == webhook_data["name"]
assert updated_webhook["url"] == webhook_data["url"]
assert updated_webhook["time"] == webhook_data["time"]
assert updated_webhook["enabled"] == webhook_data["enabled"]
assert response.status_code == 200
def test_delete_webhook(api_client: TestClient, unique_user: TestUser):
response = api_client.delete(Routes.item(1), headers=unique_user.token)
assert response.status_code == 200
response = api_client.get(Routes.item(1), headers=unique_user.token)
assert response.status_code == 404