diff --git a/alembic/versions/2024-09-18-14.52.55_1fe4bd37ccc8_add_households_filter_to_meal_plans.py b/alembic/versions/2024-09-18-14.52.55_1fe4bd37ccc8_add_households_filter_to_meal_plans.py new file mode 100644 index 00000000000..a127e72f44a --- /dev/null +++ b/alembic/versions/2024-09-18-14.52.55_1fe4bd37ccc8_add_households_filter_to_meal_plans.py @@ -0,0 +1,53 @@ +"""add households filter to meal plans + +Revision ID: 1fe4bd37ccc8 +Revises: be568e39ffdf +Create Date: 2024-09-18 14:52:55.831540 + +""" + +import sqlalchemy as sa + +import mealie.db.migration_types +from alembic import op + +# revision identifiers, used by Alembic. +revision = "1fe4bd37ccc8" +down_revision: str | None = "be568e39ffdf" +branch_labels: str | tuple[str, ...] | None = None +depends_on: str | tuple[str, ...] | None = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.create_table( + "plan_rules_to_households", + sa.Column("group_plan_rule_id", mealie.db.migration_types.GUID(), nullable=True), + sa.Column("household_id", mealie.db.migration_types.GUID(), nullable=True), + sa.ForeignKeyConstraint( + ["group_plan_rule_id"], + ["group_meal_plan_rules.id"], + ), + sa.ForeignKeyConstraint( + ["household_id"], + ["households.id"], + ), + sa.UniqueConstraint("group_plan_rule_id", "household_id", name="group_plan_rule_id_household_id_key"), + ) + with op.batch_alter_table("plan_rules_to_households", schema=None) as batch_op: + batch_op.create_index( + batch_op.f("ix_plan_rules_to_households_group_plan_rule_id"), ["group_plan_rule_id"], unique=False + ) + batch_op.create_index(batch_op.f("ix_plan_rules_to_households_household_id"), ["household_id"], unique=False) + + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + with op.batch_alter_table("plan_rules_to_households", schema=None) as batch_op: + batch_op.drop_index(batch_op.f("ix_plan_rules_to_households_household_id")) + batch_op.drop_index(batch_op.f("ix_plan_rules_to_households_group_plan_rule_id")) + + op.drop_table("plan_rules_to_households") + # ### end Alembic commands ### diff --git a/docs/docs/contributors/developers-guide/migration-guide.md b/docs/docs/contributors/developers-guide/migration-guide.md new file mode 100644 index 00000000000..5640a796d61 --- /dev/null +++ b/docs/docs/contributors/developers-guide/migration-guide.md @@ -0,0 +1,51 @@ +# Migration Guide + +This guide is a reference for developers maintaining custom integrations with Mealie. While we aim to keep breaking changes to a minimum, major versions are likely to contain at least *some* breaking changes. To clarify: *most users do not need to worry about this, this is **only** for those maintaining integrations and/or leveraging the API*. + +While this guide aims to simplify the migration process for developers, it's not necessarily a comprehensive list of breaking changes. Starting with v2, a comprehensive list of breaking changes are highlighted in the release notes. + +## V1 → V2 + +The biggest change between V1 and V2 is the introduction of Households. For more information on how households work in relation to groups/users, check out the [Groups and Households](./features.md#groups-and-households) section in the Features guide. + +### `updateAt` is now `updatedAt` + +We have renamed the `updateAt` field to `updatedAt`. While the API will still accept `updateAt` as an alias, the API will return it as `updatedAt`. The field's behavior has otherwise been unchanged. + +### Backend Endpoint Changes + +These endpoints have moved, but are otherwise unchanged: +- `/groups/webhooks` -> `/households/webhooks` +- `/groups/shopping/items` -> `/households/shopping/items` +- `/groups/shopping/lists` -> `/households/shopping/lists` +- `/groups/mealplans` -> `/households/mealplans` +- `/groups/mealplans/rules` -> `/households/mealplans/rules` +- `/groups/invitations` -> `/households/invitations` +- `/groups/recipe-actions` -> `/households/recipe-actions` +- `/groups/events/notifications` -> `/households/events/notifications` +- `/groups/cookbooks` -> `/households/cookbooks` +- `/explore/foods/{group_slug}` -> `/explore/groups/{group_slug}/foods` +- `/explore/organizers/{group_slug}/categories` -> `/explore/groups/{group_slug}/categories` +- `/explore/organizers/{group_slug}/tags` -> `/explore/groups/{group_slug}/tags` +- `/explore/organizers/{group_slug}/tools` -> `/explore/groups/{group_slug}/tools` +- `/explore/cookbooks/{group_slug}` -> `/explore/groups/{group_slug}/cookbooks` +- `/explore/recipes/{group_slug}` -> `/explore/groups/{group_slug}/recipes` + +`/groups/members` previously returned a `UserOut` object, but now returns a `UserSummary`. Should you need the full user information (username, email, etc.), rather than just the summary, see `/households/members` instead for the household members. + +These endpoints have been completely removed: +- `/admin/analytics` (no longer used) +- `/groups/permissions` (see household permissions) +- `/groups/statistics` (see household statistics) +- `/groups/categories` (see organizer endpoints) +- `/recipes/summary/untagged` (no longer used) +- `/recipes/summary/uncategorized` (no longer used) +- `/users/group-users` (see `/groups/members` and `/households/members`) + +### Frontend Links + +These frontend pages have moved: +- `/group/mealplan/...` -> `/household/mealplan/...` +- `/group/members` -> `/household/members` +- `/group/notifiers` -> `/household/notifiers` +- `/group/webhooks` -> `/household/webhooks` diff --git a/docs/docs/documentation/getting-started/faq.md b/docs/docs/documentation/getting-started/faq.md index 78473d3cba2..b6692f9c9d8 100644 --- a/docs/docs/documentation/getting-started/faq.md +++ b/docs/docs/documentation/getting-started/faq.md @@ -98,13 +98,14 @@ python /app/mealie/scripts/change_password.py Follow the [steps above](#how-can-i-change-my-password) for changing your password. You will be prompted if you would like to switch your authentication method back to local auth so you can log in again. -## How do private groups and recipes work? +## How do private groups, households, and recipes work? Managing private groups and recipes can be confusing. The following diagram and notes should help explain how they work to determine if a recipe can be shared publicly. - Private links that are generated from the recipe page using the `Share` button bypass all group and recipe permissions - Private groups block all access to recipes, including those that are public, except as noted above. -- Groups with "Allow users outside of your group to see your recipes" disabled block all access to recipes, except as noted above. +- Private households, similar to private groups, block all access to recipes, except as noted above. +- Households with "Allow users outside of your group to see your recipes" disabled block all access to recipes, except as noted above. - Private recipes block all access to the recipe from public links. This does not affect Private Links. ```mermaid @@ -112,7 +113,8 @@ stateDiagram-v2 r1: Request Access p1: Using Private Link? p2: Is Group Private? - p3: Is Recipe Private? + p3: Is Household Private? + p4: Is Recipe Private? s1: Deny Access n1: Allow Access @@ -125,10 +127,13 @@ stateDiagram-v2 p2 --> p3: No p3 --> s1: Yes - p3 --> n1: No + p3 --> p4: No + + p4 --> s1: Yes + p4 --> n1: No ``` -For more information, check out the [Permissions and Public Access guide](./usage/permissions-and-public-access.md). +For more information on public access, check out the [Permissions and Public Access guide](./usage/permissions-and-public-access.md). For more information on groups vs. households, check out the [Groups and Households](./features.md#groups-and-households) section in the Features guide. ## Can I use fail2ban with Mealie? Yes, Mealie is configured to properly forward external IP addresses into the `mealie.log` logfile. Note that due to restrictions in docker, IP address forwarding only works on Linux. diff --git a/docs/docs/documentation/getting-started/features.md b/docs/docs/documentation/getting-started/features.md index 797c4d0d083..8e4aa62581c 100644 --- a/docs/docs/documentation/getting-started/features.md +++ b/docs/docs/documentation/getting-started/features.md @@ -35,7 +35,6 @@ Mealie has a robust and flexible recipe organization system with a few different #### Categories - Categories are the overarching organizer for recipes. You can assign as many categories as you'd like to a recipe, but we recommend that you try to limit the categories you assign to a recipe to one or two. This helps keep categories as focused as possible while still allowing you to find recipes that are related to each other. For example, you might assign a recipe to the category **Breakfast**, **Lunch**, **Dinner**, or **Side**. [Categories Demo](https://demo.mealie.io/g/home/recipes/categories){ .md-button .md-button--primary } @@ -164,6 +163,46 @@ Managing a robust collection of recipes inevitable requires a lot of data. Meali [Data Management Demo](https://demo.mealie.io/group/data/foods){ .md-button .md-button--primary } +## Groups and Households + +Mealie lets you fully customize how you organize your users. You can use Groups to host multiple instances (or tenants) of Mealie which are completely isolated from each other. Within each Group you can organize users into Households which allow users to share recipes, but keep other items separate (e.g. meal plans and shopping lists). + +### Groups + +Groups are fully isolated instances of Mealie. Think of a goup as a completely separate, fully self-contained site. There is no data shared between groups. Each group has its own users, recipes, tags, categories, etc. A user logged-in to one group cannot make any changes to another. + +Common use cases for groups include: +- Hosting multiple instances of Mealie for others who want to keep their data private and secure +- Creating completely isolated recipe pools + +### Households + +Households are subdivisions within a single Group. Households maintain their own users and settings, while sharing their recipes with other households. Households also share organizers (tags, categories, etc.) with the entire group. Meal Plans, Shopping Lists, and Integrations are only accessible within a household. + +Common use cases for households include: +- Sharing a common recipe pool amongst families +- Maintaining separate meal plans and shopping lists from other households +- Maintaining separate integrations and customizations from other households + +```mermaid +flowchart TB + mealie[(Mealie)] ==> groups + + %% Groups + groups((Groups)) --> ingredients & organizers + groups((Groups)) ====> households + ingredients("Ingredients
(Foods, Units, Labels)") + organizers("Organizers
(Categories, Tags, Tools)") + + %% Households + households((Households)) --> recipes & mealplans & shoppinglists & integrations + + recipes(Recipes & Cookbooks) + mealplans(Meal Plans) + shoppinglists(Shopping Lists) + integrations("Integrations
(Notifiers, Webhooks)") +``` + ## Server Administration ### Site Settings @@ -172,11 +211,13 @@ The site settings page contains general information about your installation like [Settings Demo](https://demo.mealie.io/admin/site-settings){ .md-button .md-button--primary } -### Users and Group +### Users, Households, and Groups -There is a small management area for users and groups that allows you to create, edit, and delete users and groups. +There is a small management area for users, households, and groups. [Users Demo](https://demo.mealie.io/admin/manage/users){ .md-button .md-button--primary } +[Households Demo](https://demo.mealie.io/admin/manage/households){ .md-button .md-button--primary } +[Groups Demo](https://demo.mealie.io/admin/manage/groups){ .md-button .md-button--primary } ### Backups diff --git a/docs/docs/documentation/getting-started/introduction.md b/docs/docs/documentation/getting-started/introduction.md index 010de5edf56..25648deafdd 100644 --- a/docs/docs/documentation/getting-started/introduction.md +++ b/docs/docs/documentation/getting-started/introduction.md @@ -11,7 +11,8 @@ Mealie is a self hosted recipe manager and meal planner with a RestAPI backend a - 🕸 Import recipes from around the web by URL - 📱 Progressive Web App - 📆 Create Meal Plans -- 🛒 Generate shopping lists +- 🛒 Generate Shopping Lists +- 🏠 Separate Users into Households and share Recipes - 🐳 Easy setup with Docker - 🎨 Customize your interface with color themed layouts - 🌍 localized in many languages @@ -27,7 +28,7 @@ Mealie is a self hosted recipe manager and meal planner with a RestAPI backend a - Copy Me That - Paprika - Tandoor Recipes - - Random meal plan generation + - Random Meal Plan generation - Advanced rule configuration to fine tune random recipes ## FAQ diff --git a/docs/docs/documentation/getting-started/updating.md b/docs/docs/documentation/getting-started/updating.md index 6917bc35bb9..de8be5a8746 100644 --- a/docs/docs/documentation/getting-started/updating.md +++ b/docs/docs/documentation/getting-started/updating.md @@ -9,8 +9,8 @@ - Create a Backup and Download from the UI - Upgrade -## Upgrading to Mealie v1 -If you are upgrading from pre-v1.0.0 to v1.0.0, make sure you read [Migrating to Mealie v1](./migrating-to-mealie-v1.md)! +## Upgrading to Mealie v1 or later +If you are upgrading from pre-v1.0.0 to v1.0.0 or later (v2.0.0, etc.), make sure you read [Migrating to Mealie v1](./migrating-to-mealie-v1.md)! ## Backing Up Your Data diff --git a/docs/docs/documentation/getting-started/usage/permissions-and-public-access.md b/docs/docs/documentation/getting-started/usage/permissions-and-public-access.md index 475a0b44886..35461701d22 100644 --- a/docs/docs/documentation/getting-started/usage/permissions-and-public-access.md +++ b/docs/docs/documentation/getting-started/usage/permissions-and-public-access.md @@ -19,9 +19,10 @@ Administrators can navigate to the Settings page and access the User Management ## Public Recipe Access -By default, groups are set to private, meaning only logged-in users may access the group. In order for a recipe to be viewable by public (not logged-in) users, two criteria must be met: +By default, groups and households are set to private, meaning only logged-in users may access the group/household. In order for a recipe to be viewable by public (not logged-in) users, three criteria must be met: -1. The group must not be private, *and* the group setting for allowing users outside of your group to see your recipes must be enabled. These can be toggled on the Group Settings page +1. The group must not be private +2. The household must not be private, *and* the household setting for allowing users outside of your group to see your recipes must be enabled. These can be toggled on the Household Settings page 2. The recipe must be set to public. This can be toggled for each recipe individually, or in bulk using the Recipe Data Management page Additionally, if the group is not private, public users can view all public group data (public recipes, public cookbooks, etc.) from the home page ([e.g. the demo home page](https://demo.mealie.io/g/home)). @@ -32,7 +33,8 @@ More broadly, here are the rules for how recipe access is determined: - Private links that are generated from the recipe page using the `Share` button bypass all group and recipe permissions - Private groups block all access to recipes, including those that are public, except as noted above. -- Groups with "Allow users outside of your group to see your recipes" disabled block all access to recipes, except as noted above. +- Private households, similar to private groups, block all access to recipes, except as noted above. +- Households with "Allow users outside of your group to see your recipes" disabled block all access to recipes, except as noted above. - Private recipes block all access to the recipe from public links. This does not affect Private Links. ```mermaid @@ -40,7 +42,8 @@ stateDiagram-v2 r1: Request Access p1: Using Private Link? p2: Is Group Private? - p3: Is Recipe Private? + p3: Is Household Private? + p4: Is Recipe Private? s1: Deny Access n1: Allow Access @@ -53,5 +56,8 @@ stateDiagram-v2 p2 --> p3: No p3 --> s1: Yes - p3 --> n1: No + p3 --> p4: No + + p4 --> s1: Yes + p4 --> n1: No ``` diff --git a/docs/docs/overrides/api.html b/docs/docs/overrides/api.html index ed6136a1666..ce5d7fd8614 100644 --- a/docs/docs/overrides/api.html +++ b/docs/docs/overrides/api.html @@ -14,7 +14,7 @@
diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index 2369a9a89e8..6def4dc34d7 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -101,5 +101,6 @@ nav: - Dev Getting Started: "contributors/developers-guide/starting-dev-server.md" - Database Changes: "contributors/developers-guide/database-changes.md" - Maintainers Guide: "contributors/developers-guide/maintainers.md" + - Migration Guide: "contributors/developers-guide/migration-guide.md" - Guides: - Improving Ingredient Parser: "contributors/guides/ingredient-parser.md" diff --git a/frontend/components/Domain/Household/GroupHouseholdSelector.vue b/frontend/components/Domain/Household/GroupHouseholdSelector.vue new file mode 100644 index 00000000000..fcdf63e4004 --- /dev/null +++ b/frontend/components/Domain/Household/GroupHouseholdSelector.vue @@ -0,0 +1,91 @@ + + + diff --git a/frontend/components/Domain/Household/GroupMealPlanRuleForm.vue b/frontend/components/Domain/Household/GroupMealPlanRuleForm.vue index cf71112a3ee..1f263eb3621 100644 --- a/frontend/components/Domain/Household/GroupMealPlanRuleForm.vue +++ b/frontend/components/Domain/Household/GroupMealPlanRuleForm.vue @@ -5,8 +5,15 @@ - - +
+ + + +
{{ $t('meal-plan.this-rule-will-apply', { @@ -18,11 +25,13 @@