diff --git a/.github/workflows/build-docker-open-data.yml b/.github/workflows/build-docker-open-data.yml index 09df1956..22b3af12 100644 --- a/.github/workflows/build-docker-open-data.yml +++ b/.github/workflows/build-docker-open-data.yml @@ -21,7 +21,7 @@ jobs: suffix: "" continue-on-error: false steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Get version number id: get_version @@ -43,7 +43,7 @@ jobs: path: ./recipes/plugins/open_data_plugin # Build Vue frontend - - uses: actions/setup-node@v3 + - uses: actions/setup-node@v4 with: node-version: '18' cache: yarn diff --git a/.github/workflows/build-docker.yml b/.github/workflows/build-docker.yml index 8c29b9fe..b61169d5 100644 --- a/.github/workflows/build-docker.yml +++ b/.github/workflows/build-docker.yml @@ -21,7 +21,7 @@ jobs: suffix: "" continue-on-error: false steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Get version number id: get_version @@ -35,7 +35,7 @@ jobs: fi # Build Vue frontend - - uses: actions/setup-node@v3 + - uses: actions/setup-node@v4 with: node-version: '18' cache: yarn diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d699a564..3f81b1fb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,13 +12,13 @@ jobs: python-version: ['3.10'] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up Python 3.10 - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: '3.10' # Build Vue frontend - - uses: actions/setup-node@v3 + - uses: actions/setup-node@v4 with: node-version: '18' - name: Install Vue dependencies diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 4166aae3..fcdd8926 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -12,7 +12,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: # We must fetch at least the immediate parents so that if this is # a pull request then we can checkout the head. @@ -25,7 +25,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@v2 + uses: github/codeql-action/init@v3 # Override language selection by uncommenting this and choosing your languages with: languages: python, javascript @@ -47,6 +47,6 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v2 + uses: github/codeql-action/analyze@v3 with: languages: javascript, python diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 7a35555b..6956ee7f 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -9,8 +9,8 @@ jobs: if: github.repository_owner == 'TandoorRecipes' runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 - - uses: actions/setup-python@v4 + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 with: python-version: 3.x - run: pip install mkdocs-material mkdocs-include-markdown-plugin diff --git a/boot.sh b/boot.sh index 3faacad7..97a94f47 100644 --- a/boot.sh +++ b/boot.sh @@ -76,4 +76,4 @@ echo "Done" chmod -R 755 /opt/recipes/mediafiles -exec gunicorn -b :$TANDOOR_PORT --workers $GUNICORN_WORKERS --threads $GUNICORN_THREADS --access-logfile - --error-logfile - --log-level $GUNICORN_LOG_LEVEL recipes.wsgi +exec gunicorn -b "[::]:$TANDOOR_PORT" --workers $GUNICORN_WORKERS --threads $GUNICORN_THREADS --access-logfile - --error-logfile - --log-level $GUNICORN_LOG_LEVEL recipes.wsgi diff --git a/docs/faq.md b/docs/faq.md index 6c8e5aa5..1285b2ac 100644 --- a/docs/faq.md +++ b/docs/faq.md @@ -10,9 +10,12 @@ Tandoor can be installed as a progressive web app (PWA) on mobile and desktop de #### Safari (iPhone/iPad) Open Tandoor, click Safari's share button, select `Add to Home Screen` -### Chrome/Chromium +#### Chrome/Chromium Open Tandoor, click the `add Tandoor to the home screen` message that pops up at the bottom of the screen +#### Firefox for Android +Open Tandoor, click on the `⋮` menu icon, then on `Install` + ### Desktop browsers #### Google Chrome @@ -124,13 +127,13 @@ to your dream setup. ## How can I upgrade postgres (major versions)? Postgres requires manual intervention when updating from one major version to another. The steps are roughly -1. use `pg_dumpall` to dump your database into SQL (for Docker `docker-compose exec -T pg_dumpall -U -f /path/to/dump.sql`) +1. use `pg_dumpall` to dump your database into SQL (for Docker `docker-compose exec -T pg_dumpall -U -f /path/to/dump.sql`) 2. stop the DB / down the container 3. move your postgres directory in order to keep it as a backup (e.g. `mv postgres postgres_old`) 4. update postgres to the new major version (for Docker just change the version number and pull) 5. start the db / up the container (do not start tandoor as it will automatically perform the database migrations which will conflict with loading the dump) 6. if not using docker, you might need to create the same postgres user you had in the old database -7. load the postgres dump (for Docker `'/usr/local/bin/docker-compose exec -T psql -U postgres < /path/to/dump.sql`) +7. load the postgres dump (for Docker `'/usr/local/bin/docker-compose exec -T psql -U < /path/to/dump.sql`) If anything fails, go back to the old postgres version and data directory and try again. diff --git a/docs/features/automation.md b/docs/features/automation.md index b89a4a10..60a984c8 100644 --- a/docs/features/automation.md +++ b/docs/features/automation.md @@ -50,7 +50,7 @@ In order to prevent denial of service attacks on the RegEx engine the number of and the length of the inputs that are processed are limited. Those limits should never be reached during normal usage. -## Instructtion Replace, Title Replace, Food Replace & Unit Replace +## Instruction Replace, Title Replace, Food Replace & Unit Replace These work just like the Description Replace automation. Instruction, Food and Unit Replace will run against every iteration of the object in a recipe during import. diff --git a/docs/features/shopping.md b/docs/features/shopping.md index ca431dbb..cb1f1654 100644 --- a/docs/features/shopping.md +++ b/docs/features/shopping.md @@ -1,5 +1,5 @@ !!! info "WIP" - While being around for a while there are still a lot of features that i plan on adding to the shopping list. + While being around for a while there are still a lot of features that I plan on adding to the shopping list. You can see an overview of what is still planned on [this](https://github.com/vabene1111/recipes/issues/114) issue. @@ -41,4 +41,4 @@ There are a few more features worth pointing out 1. You can export recipes for use in other applications (Google Keep, etc.) by using the export button 2. In the export popup you can define a prefix to be put before each row in case an external app requires that -3. Marking a shopping list as finished will hide it from the shopping list page \ No newline at end of file +3. Marking a shopping list as finished will hide it from the shopping list page diff --git a/docs/install/other.md b/docs/install/other.md index a6db572e..b4829f3e 100644 --- a/docs/install/other.md +++ b/docs/install/other.md @@ -59,6 +59,155 @@ I used two paths `` and `` for simplicity. In my case I have I left out the TLS config in this example for simplicity. +## Docker + Apache + Sub-Path + +The following could prove to be useful if you are not using Traefik, but instead run Apache as your reverse proxy to route all calls for a shared (sub)domain to a sub path, e.g. https://mydomain.tld/tandoor + +As a side note, I am using [Blocky](https://0xerr0r.github.io/blocky/) + [Consul](https://hub.docker.com/r/hashicorp/consul) + [Registrator](https://hub.docker.com/r/gliderlabs/registrator) as a DNS solution. + +The relevant Apache config: +``` + + # in case you want to restrict access to specific IP addresses: + Require local + Require forward-dns [myhomedomain.useyourdomain.com] + Require ip [anylocalorremoteipyouwanttowhitelist] + + # The following assumes that tandoor.service.consul.local resolves to the IP address of the Docker container. + ProxyPass http://tandoor.service.consul.local:8080/tandoor + ProxyPassReverse http://tandoor.service.consul.local:8080/tandoor + RequestHeader add X-Script-Name /tandoor + RequestHeader set X-Forwarded-Proto "https" + ProxyPreserveHost On + + + Require local + Require forward-dns [myhomedomain.useyourdomain.com] + Require ip [anylocalorremoteipyouwanttowhitelist] + + ProxyPass http://tandoor.service.consul.local:8080/tandoor/tandoor/static + ProxyPassReverse http://tandoor.service.consul.local:8080/tandoor/static + RequestHeader add X-Script-Name /tandoor + RequestHeader set X-Forwarded-Proto "https" + ProxyPreserveHost On + +``` +and the relevant section from the docker-compose.yml: +``` + tandoor: + restart: always + container_name: tandoor + image: vabene1111/recipes + environment: + - SCRIPT_NAME=/tandoor + - JS_REVERSE_SCRIPT_PREFIX=/tandoor + - STATIC_URL=/tandoor/static/ + - MEDIA_URL=/tandoor/media/ + - GUNICORN_MEDIA=0 + - SECRET_KEY=${YOUR_TANDOOR_SECRET_KEY} + - POSTGRES_HOST=postgres.service.consul.local + - POSTGRES_PORT=${POSTGRES_PORT} + - POSTGRES_USER=${YOUR_TANDOOR_POSTGRES_USER} + - POSTGRES_PASSWORD=${YOUR_TANDOOR_POSTGRES_PASSWORD} + - POSTGRES_DB=${YOUR_TANDOOR_POSTGRES_DB} + labels: + # The following is relevant only if you are using Registrator and Consul + - "SERVICE_NAME=tandoor" + volumes: + - ${YOUR_DOCKER_VOLUME_BASE_DIR}/tandoor/static:/opt/recipes/staticfiles:rw + # Do not make this a bind mount, see https://docs.tandoor.dev/install/docker/#volumes- vs-bind-mounts + - tandoor_nginx_config:/opt/recipes/nginx/conf.d + - ${YOUR_DOCKER_VOLUME_BASE_DIR}}/tandoor/media:/opt/recipes/mediafiles:rw + depends_on: + # You will have to set up postgres accordingly + - postgres +``` + +The relevant docker-compose.yml for Registrator, Consul, and Blocky, and Autoheal: +``` + consul: + image: hashicorp/consul + container_name: consul + command: > + agent -server + -domain consul.local + -advertise=${YOUR_DOCKER_HOST_IP_ON_THE_LAN} + -client=0.0.0.0 + -encrypt=${SOME_SECRET_KEY} + -datacenter=${YOUR_DC_NAME} + -bootstrap-expect=1 + -ui + -log-level=info + environment: + - "CONSUL_LOCAL_CONFIG={\"skip_leave_on_interrupt\": true, \"dns_config\": { \"service_ttl\": { \"*\": \"0s\" } } }" + network_mode: "host" + restart: always + + registrator: + image: gliderlabs/registrator:latest + container_name: registrator + extra_hosts: + - "host.docker.internal:host-gateway" + volumes: + - /var/run/docker.sock:/tmp/docker.sock:ro + command: > + -internal + -cleanup=true + -deregister="always" + -resync=60 + consul://host.docker.internal:8500 + restart: always + + blocky: + image: spx01/blocky + container_name: blocky + restart: unless-stopped + healthcheck: + interval: 30s + timeout: 5s + start_period: 1m + labels: + # The following is only relevant if you use autoheal + autoheal: true + # Optional the instance hostname for logging purpose + hostname: blocky + extra_hosts: + - "host.docker.internal:host-gateway" + ports: + - "1153:53/tcp" + - "1153:53/udp" + - 4000:4000 + environment: + - TZ=YOUR_TIMEZONE # Optional to synchronize the log timestamp with host + volumes: + # Optional to synchronize the log timestamp with host + - /etc/localtime:/etc/localtime:ro + # config file + - ${YOUR_DOCKER_VOLUME_BASE_DIR}/blocky/config.yml:/app/config.yml + networks: + # in case you want to bind Blocky to an IP address + your-docker-network-name: + ipv4_address: 'some-ip-address-in-the-docker-network-subnet' + + autoheal: + image: willfarrell/autoheal + volumes: + - '/var/run/docker.sock:/var/run/docker.sock' + environment: + - AUTOHEAL_CONTAINER_LABEL=autoheal + restart: always + container_name: autoheal + +``` +as well as a snippet of the Blocky configuration: +``` +conditional: + fallbackUpstream: false + mapping: + consul.local: tcp+udp:host.docker.internal:8600 +``` + + ## WSL If you want to install Tandoor on the Windows Subsystem for Linux you can find a detailed post here: . diff --git a/nginx/conf.d/Recipes.conf b/nginx/conf.d/Recipes.conf index 22829720..9cda0f74 100644 --- a/nginx/conf.d/Recipes.conf +++ b/nginx/conf.d/Recipes.conf @@ -1,5 +1,6 @@ server { listen 80; + listen [::]:80 ipv6only=on; server_name localhost; client_max_body_size 128M; diff --git a/requirements.txt b/requirements.txt index 9cf4efdf..297e3e77 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,7 @@ Django==4.2.7 -cryptography===41.0.6 +cryptography===41.0.7 django-annoying==0.10.6 -django-autocomplete-light==3.9.4 +django-autocomplete-light==3.9.7 django-cleanup==8.0.0 django-crispy-forms==2.0 crispy-bootstrap4==2022.1 @@ -14,7 +14,7 @@ bleach==6.0.0 gunicorn==20.1.0 lxml==4.9.3 Markdown==3.5.1 -Pillow==10.0.1 +Pillow==10.1.0 psycopg2-binary==2.9.5 python-dotenv==1.0.0 requests==2.31.0 @@ -26,7 +26,7 @@ pyyaml==6.0.1 uritemplate==4.1.1 beautifulsoup4==4.12.2 microdata==0.8.0 -Jinja2==3.1.2 +Jinja2==3.1.3 django-webpack-loader==1.8.1 git+https://github.com/BITSOLVER/django-js-reverse@071e304fd600107bc64bbde6f2491f1fe049ec82 django-allauth==0.58.1 @@ -36,13 +36,13 @@ pytest==7.4.3 pytest-django==4.6.0 django-treebeard==4.7 django-cors-headers==4.2.0 -django-storages==1.13.2 +django-storages==1.14.2 boto3==1.28.75 django-prometheus==2.2.0 django-hCaptcha==0.2.0 python-ldap==3.4.3 django-auth-ldap==4.4.0 -pytest-factoryboy==2.5.1 +pytest-factoryboy==2.6.0 pyppeteer==1.0.2 validators==0.20.0 pytube==15.0.0 diff --git a/vue/package.json b/vue/package.json index f90fbc7f..23be9a3f 100644 --- a/vue/package.json +++ b/vue/package.json @@ -46,7 +46,7 @@ "vue2-touch-events": "^3.2.2", "vuedraggable": "^2.24.3", "workbox-webpack-plugin": "^6.5.4", - "workbox-window": "^6.5.4" + "workbox-window": "^7.0.0" }, "devDependencies": { "@kazupon/vue-i18n-loader": "^0.5.0", @@ -65,11 +65,11 @@ "typescript": "~5.1.6", "vue-cli-plugin-i18n": "^2.3.2", "webpack-bundle-tracker": "1.8.1", - "workbox-background-sync": "^6.5.4", + "workbox-background-sync": "^7.0.0", "workbox-expiration": "^6.5.4", - "workbox-navigation-preload": "^6.5.4", + "workbox-navigation-preload": "^7.0.0", "workbox-precaching": "^6.5.4", - "workbox-routing": "^6.5.4", + "workbox-routing": "^7.0.0", "workbox-strategies": "^6.2.4" }, "eslintConfig": { diff --git a/vue/src/apps/MealPlanView/MealPlanView.vue b/vue/src/apps/MealPlanView/MealPlanView.vue index f870ee96..9beb8454 100644 --- a/vue/src/apps/MealPlanView/MealPlanView.vue +++ b/vue/src/apps/MealPlanView/MealPlanView.vue @@ -364,7 +364,7 @@ export default { }, mobileSimpleGrid() { let grid = []; - let currentDate = moment(); + let currentDate = moment(this.showDate); for (let x = 0; x < 7; x++) { let moment_date = currentDate.clone().add(x, "d"); grid.push({ @@ -483,7 +483,7 @@ export default { this.setShowDate(ctx.selectedDate) }, setShowDate(d) { - this.showDate = d + this.showDate = d ?? new Date(); }, createEntryClick(data) { this.mealplan_default_date = moment(data).format("YYYY-MM-DD") diff --git a/vue/src/components/IngredientComponent.vue b/vue/src/components/IngredientComponent.vue index eb26b87a..18876f06 100644 --- a/vue/src/components/IngredientComponent.vue +++ b/vue/src/components/IngredientComponent.vue @@ -7,7 +7,7 @@ - +