From 79425b4fc036280787f34dfdf7de1ab20bd4827f Mon Sep 17 00:00:00 2001 From: Jaimyn Mayer Date: Tue, 29 Aug 2023 00:53:22 +1000 Subject: [PATCH 01/10] update caprover deployment example --- docker/caprover.yaml | 154 ++++++++++++++++++++++++++++++------------- 1 file changed, 108 insertions(+), 46 deletions(-) diff --git a/docker/caprover.yaml b/docker/caprover.yaml index d93a46f7..32345213 100644 --- a/docker/caprover.yaml +++ b/docker/caprover.yaml @@ -1,72 +1,134 @@ captainVersion: 4 +caproverOneClickApp: + variables: + - id: $$cap_mm_version + label: MemberMatters Version + defaultValue: "latest" + description: Check out the docker page for the valid tags https://hub.docker.com/r/membermatters/membermatters/tags + validRegex: /^([^\s^\/])+$/ + - id: $$cap_env + label: Environment + defaultValue: "Production" + description: The environment your installation is running in. You can set this to "Development" for additional debug logging. + validRegex: /^([^\s^\/])+$/ + - id: $$cap_postgres_user + label: Postgres User + defaultValue: "membermatters" + description: The username for default postgres user (you shouldn't need to change this). + validRegex: /^([^\s^\/])+$/ + - id: $$cap_postgres_password + label: Postgres Password + defaultValue: "$$cap_gen_random_hex(30)" + description: The password for default postgres user (you shouldn't need to change this). + validRegex: /^([^\s^\/])+$/ + - id: $$cap_postgres_db + label: Postgres Database Name + defaultValue: "membermatters" + description: The postgres database name to use (you shouldn't need to change this). + validRegex: /^([^\s^\/])+$/ + - id: $$cap_mm_secret_key + label: MemberMatters Django Secret Key + defaultValue: "$$cap_gen_random_hex(30)" + description: The Django secret key (you shouldn't need to change this). + validRegex: /^([^\s^\/])+$/ + instructions: + start: >- + Getting ready to deploy MemberMatters. + end: >- + Done! 😄 + Your service is available at http://$$cap_appname.$$cap_root_domain. + You may need to load the data fixtures or create an admin login using the Django cli. + You can connect to the running container and run something like `python3 manage.py loaddata fixtures/initial.json` to do this. + displayName: "MemberMatters" + isOfficial: true + description: Open source membership management platform for makerspaces and community groups. + documentation: https://membermatters.org +######## services: - # MemberMatters - $$cap_appname: - image: membermatters/membermatters:$$cap_version + $$cap_appname-mm-postgres: + image: postgres:15.3-alpine restart: always environment: - MM_ENV: $$cap_env - MM_REDIS_HOST: "redis://srv-captain--$$cap_appname-redis:6379/0" + POSTGRES_USER: $$cap_postgres_user + POSTGRES_PASSWORD: $$cap_postgres_password + POSTGRES_DB: $$cap_postgres_db volumes: - - $$cap_appname-data:/usr/src/data - depends_on: - - $$cap_appname-redis + - $$cap_appname-mm-postgres-volume:/var/lib/postgresql/data caproverExtra: - containerHttpPort: "8000" + notExposeAsWebApp: true # MemberMatters Redis - $$cap_appname-redis: + $$cap_appname-mm-redis: image: redis:alpine restart: always + depends_on: + - $$cap_appname-mm-postgres + caproverExtra: + notExposeAsWebApp: true + + # MemberMatters + $$cap_appname-mm-webapp: + image: membermatters/membermatters:$$cap_mm_version + restart: always + environment: + MM_ENV: $$cap_env + MM_SECRET_KEY: $$cap_mm_secret_key + MM_REDIS_HOST: "redis://srv-captain--$$cap_appname-mm-redis:6379/0" + MM_USE_POSTGRES: True + POSTGRES_DB: $$cap_postgres_db + POSTGRES_USER: $$cap_postgres_user + POSTGRES_PASSWORD: $$cap_postgres_password + POSTGRES_HOST: "srv-captain--$$cap_appname-mm-postgres" + volumes: + - $$cap_appname-mm-webapp-data:/usr/src/data + depends_on: + - $$cap_appname-mm-redis + - $$cap_appname-mm-postgres + caproverExtra: + containerHttpPort: "8000" # MemberMatters Celery Worker - $$cap_appname-celery-worker: - image: membermatters/membermatters:$$cap_version - command: ["celery", "-A", "membermatters.celeryapp", "worker", "-l", "INFO"] + $$cap_appname-mm-celery-worker: + image: membermatters/membermatters:$$cap_mm_version + # command: ["celery", "-A", "membermatters.celeryapp", "worker", "-l", "INFO"] restart: always environment: MM_ENV: $$cap_env + MM_USE_POSTGRES: True + POSTGRES_DB: $$cap_postgres_db + POSTGRES_USER: $$cap_postgres_user + POSTGRES_PASSWORD: $$cap_postgres_password + POSTGRES_HOST: "srv-captain--$$cap_appname-mm-postgres" MM_RUN_MODE: "celery_worker" - MM_REDIS_HOST: "redis://srv-captain--$$cap_appname-redis:6379/0" + MM_REDIS_HOST: "redis://srv-captain--$$cap_appname-mm-redis:6379/0" volumes: - - $$cap_appname-data:/usr/src/data + - $$cap_appname-mm-data:/usr/src/data depends_on: - - $$cap_appname-redis - - $$cap_appname + - $$cap_appname-mm-redis + - $$cap_appname-mm-postgres + - $$cap_appname-mm-webapp + caproverExtra: + notExposeAsWebApp: true # MemberMatters Celery Beat - $$cap_appname-celery-beat: - image: membermatters/membermatters:$$cap_version - command: ["celery", "-A", "membermatters.celeryapp", "beat", "-l", "INFO"] + $$cap_appname-mm-celery-beat: + image: membermatters/membermatters:$$cap_mm_version + # command: ["celery", "-A", "membermatters.celeryapp", "beat", "-l", "INFO"] restart: always environment: MM_ENV: $$cap_env + MM_USE_POSTGRES: True + POSTGRES_DB: $$cap_postgres_db + POSTGRES_USER: $$cap_postgres_user + POSTGRES_PASSWORD: $$cap_postgres_password + POSTGRES_HOST: "srv-captain--$$cap_appname-mm-postgres" MM_RUN_MODE: "celery_beat" - MM_REDIS_HOST: "redis://srv-captain--$$cap_appname-redis:6379/0" + MM_REDIS_HOST: "redis://srv-captain--$$cap_appname-mm-redis:6379/0" volumes: - - $$cap_appname-data:/usr/src/data + - $$cap_appname-mm-data:/usr/src/data depends_on: - - $$cap_appname-redis - - $$cap_appname -caproverOneClickApp: - variables: - - id: $$cap_version - label: Version - defaultValue: "latest" - description: Check out the docker page for the valid tags https://hub.docker.com/r/membermatters/membermatters/tags - validRegex: /^([^\s^\/])+$/ - - id: $$cap_env - label: Environment - defaultValue: "Production" - description: The environment your installation is running in. You can set this to "Development" for additional debug logging. - validRegex: /^([^\s^\/])+$/ - instructions: - start: >- - MemberMatters is an open source membership management platform for makerspaces and community groups. - end: >- - Done! 😄 - Your service is available at http://$$cap_appname.$$cap_root_domain - displayName: "MemberMatters" - isOfficial: true - description: Open source membership management platform for makerspaces and community groups. - documentation: https://membermatters.org + - $$cap_appname-mm-redis + - $$cap_appname-mm-postgres + - $$cap_appname-mm-webapp + caproverExtra: + notExposeAsWebApp: true From 7b103d224e9f5373de5b1d62bdc6ac8d3aebfcaa Mon Sep 17 00:00:00 2001 From: Jaimyn Mayer Date: Tue, 29 Aug 2023 00:53:43 +1000 Subject: [PATCH 02/10] remove arm64 from dev docker build for speed --- .github/workflows/build_docker.dev.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build_docker.dev.yml b/.github/workflows/build_docker.dev.yml index e0668965..b643b65d 100644 --- a/.github/workflows/build_docker.dev.yml +++ b/.github/workflows/build_docker.dev.yml @@ -23,6 +23,6 @@ jobs: uses: docker/build-push-action@v3 with: file: docker/Dockerfile - platforms: linux/amd64,linux/arm64 + platforms: linux/amd64 push: true tags: membermatters/membermatters:dev From 251ad2be5e972e63902a5c77def36d733b6d51ae Mon Sep 17 00:00:00 2001 From: Jaimyn Mayer Date: Tue, 29 Aug 2023 00:53:58 +1000 Subject: [PATCH 03/10] removed invalid db migration references --- memberportal/profile/migrations/0001_initial.py | 1 - memberportal/profile/migrations/0007_auto_20211005_0015.py | 4 ---- 2 files changed, 5 deletions(-) diff --git a/memberportal/profile/migrations/0001_initial.py b/memberportal/profile/migrations/0001_initial.py index 9bb194bb..3b71603f 100644 --- a/memberportal/profile/migrations/0001_initial.py +++ b/memberportal/profile/migrations/0001_initial.py @@ -316,7 +316,6 @@ class Migration(migrations.Migration): models.CharField(blank=True, default="", max_length=6, null=True), ), ("doors", models.ManyToManyField(blank=True, to="access.Doors")), - ("groups", models.ManyToManyField(to="group.Group")), ( "interlocks", models.ManyToManyField(blank=True, to="access.Interlock"), diff --git a/memberportal/profile/migrations/0007_auto_20211005_0015.py b/memberportal/profile/migrations/0007_auto_20211005_0015.py index be470784..d730d5a3 100644 --- a/memberportal/profile/migrations/0007_auto_20211005_0015.py +++ b/memberportal/profile/migrations/0007_auto_20211005_0015.py @@ -9,10 +9,6 @@ class Migration(migrations.Migration): ] operations = [ - migrations.RemoveField( - model_name="profile", - name="groups", - ), migrations.AlterField( model_name="log", name="id", From cc5259c51721f02948903e58043ff99a319eff07 Mon Sep 17 00:00:00 2001 From: Jaimyn Mayer Date: Tue, 29 Aug 2023 00:54:38 +1000 Subject: [PATCH 04/10] fixed subscription endpoint fetching bug --- memberportal/api_access/views.py | 4 ++-- memberportal/api_admin_tools/views.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/memberportal/api_access/views.py b/memberportal/api_access/views.py index 9d98d389..4b0637ac 100644 --- a/memberportal/api_access/views.py +++ b/memberportal/api_access/views.py @@ -87,7 +87,7 @@ def put(self, request, door_id, user_id): class AuthoriseInterlock(APIView): """ - post: This method authorises a member to access an interlock. + put: This method authorises a member to access an interlock. """ permission_classes = (permissions.IsAdminUser,) @@ -105,7 +105,7 @@ def put(self, request, interlock_id, user_id): class RevokeDoor(APIView): """ - post: This method revokes a member's access to a door. + put: This method revokes a member's access to a door. """ permission_classes = (permissions.IsAdminUser,) diff --git a/memberportal/api_admin_tools/views.py b/memberportal/api_admin_tools/views.py index 779cff39..89ca621c 100644 --- a/memberportal/api_admin_tools/views.py +++ b/memberportal/api_admin_tools/views.py @@ -601,9 +601,9 @@ def get(self, request, member_id): s = None # if we have a subscription id, fetch the details - if member.user.profile.stripe_subscription_id: + if member.profile.stripe_subscription_id: s = stripe.Subscription.retrieve( - member.user.profile.stripe_subscription_id, + member.profile.stripe_subscription_id, ) # if we got subscription details From 74482add93e2137e33b8f629336472835ddac109 Mon Sep 17 00:00:00 2001 From: Jaimyn Mayer Date: Tue, 29 Aug 2023 00:54:59 +1000 Subject: [PATCH 05/10] fixed all frontend API URLS --- src-frontend/src/components/AccessList.vue | 4 ++-- src-frontend/src/components/Billing/SelectTier.vue | 2 +- .../src/components/Billing/SignupRequiredSteps.vue | 2 +- src-frontend/src/components/DigitalIdCard.vue | 2 +- src-frontend/src/components/ProxyForm.vue | 2 +- src-frontend/src/pages/MembershipPlan.vue | 8 ++++---- src-frontend/src/pages/VerifyEmail.vue | 2 +- 7 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src-frontend/src/components/AccessList.vue b/src-frontend/src/components/AccessList.vue index e5646014..d1d75c95 100644 --- a/src-frontend/src/components/AccessList.vue +++ b/src-frontend/src/components/AccessList.vue @@ -160,7 +160,7 @@ export default { if (!this.memberId) return; const device = type === 'interlock' ? 'interlocks' : 'doors'; this.$axios - .put(`api/access/${device}/${deviceId}/authorise/${memberId}/`) + .put(`/api/access/${device}/${deviceId}/authorise/${memberId}/`) .then(() => { this.getMemberAccess(); }) @@ -176,7 +176,7 @@ export default { if (!this.memberId) return; const device = type === 'interlock' ? 'interlocks' : 'doors'; this.$axios - .put(`api/access/${device}/${deviceId}/revoke/${memberId}/`) + .put(`/api/access/${device}/${deviceId}/revoke/${memberId}/`) .then(() => { this.getMemberAccess(); }) diff --git a/src-frontend/src/components/Billing/SelectTier.vue b/src-frontend/src/components/Billing/SelectTier.vue index 9ae7ff80..9e6019b6 100644 --- a/src-frontend/src/components/Billing/SelectTier.vue +++ b/src-frontend/src/components/Billing/SelectTier.vue @@ -279,7 +279,7 @@ export default defineComponent({ this.disableFinish = true; this.loading = true; this.$axios - .post(`api/billing/plans/${this.selectedPlan.id}/signup/`) + .post(`/api/billing/plans/${this.selectedPlan.id}/signup/`) .then((response) => { if (response.data.success) { this.finishSuccess = true; diff --git a/src-frontend/src/components/Billing/SignupRequiredSteps.vue b/src-frontend/src/components/Billing/SignupRequiredSteps.vue index d55d7673..b2b9d870 100644 --- a/src-frontend/src/components/Billing/SignupRequiredSteps.vue +++ b/src-frontend/src/components/Billing/SignupRequiredSteps.vue @@ -229,7 +229,7 @@ export default defineComponent({ this.updateInductionStatus(); }, 10000); - api.get('api/billing/can-signup/').then((result) => { + api.get('/api/billing/can-signup/').then((result) => { if (result.data.success) { this.step = 3; // skip straight to the end } else { diff --git a/src-frontend/src/components/DigitalIdCard.vue b/src-frontend/src/components/DigitalIdCard.vue index 3f87cf97..a2ddcd03 100644 --- a/src-frontend/src/components/DigitalIdCard.vue +++ b/src-frontend/src/components/DigitalIdCard.vue @@ -88,7 +88,7 @@ export default { }, methods: { getIdToken() { - this.$axios.get('api/profile/idtoken/').then((result) => { + this.$axios.get('/api/profile/idtoken/').then((result) => { QRCode.toDataURL(result.data.token, async (err, url) => { this.qrcode = url; }); diff --git a/src-frontend/src/components/ProxyForm.vue b/src-frontend/src/components/ProxyForm.vue index 42a69c50..fcfb2a3b 100644 --- a/src-frontend/src/components/ProxyForm.vue +++ b/src-frontend/src/components/ProxyForm.vue @@ -156,7 +156,7 @@ export default { submitProxy() { this.loading = true; this.$axios - .post('api/proxies/', { + .post('/api/proxies/', { meeting: this.meeting.id, memberCity: this.memberCity, proxy: this.proxy.member.id, diff --git a/src-frontend/src/pages/MembershipPlan.vue b/src-frontend/src/pages/MembershipPlan.vue index e84849b7..968031c8 100644 --- a/src-frontend/src/pages/MembershipPlan.vue +++ b/src-frontend/src/pages/MembershipPlan.vue @@ -151,7 +151,7 @@ export default defineComponent({ methods: { ...mapActions('profile', ['getProfile']), getSubscriptionInfo() { - this.$axios.get('api/billing/myplan/').then((result) => { + this.$axios.get('/api/billing/myplan/').then((result) => { if (result.data.success) { this.subscriptionInfo = result.data.subscription; } @@ -159,7 +159,7 @@ export default defineComponent({ }, getCanSignup() { this.$axios - .get('api/billing/can-signup/') + .get('/api/billing/can-signup/') .then((result) => { if (result.data.success) { this.canSignup = true; @@ -188,7 +188,7 @@ export default defineComponent({ this.disableButton = true; this.loadingButton = true; this.$axios - .post('api/billing/myplan/cancel/') + .post('/api/billing/myplan/cancel/') .then((result) => { if (result.data.success) { this.cancelSuccess = true; @@ -219,7 +219,7 @@ export default defineComponent({ this.disableButton = true; this.loadingButton = true; this.$axios - .post('api/billing/myplan/resume/') + .post('/api/billing/myplan/resume/') .then((result) => { if (result.data.success) { location.reload(); diff --git a/src-frontend/src/pages/VerifyEmail.vue b/src-frontend/src/pages/VerifyEmail.vue index 3c38c12c..05604b7f 100644 --- a/src-frontend/src/pages/VerifyEmail.vue +++ b/src-frontend/src/pages/VerifyEmail.vue @@ -51,7 +51,7 @@ export default { }, mounted() { this.$axios - .post(`api/email/${this.verifyToken}/verify/`) + .post(`/api/email/${this.verifyToken}/verify/`) .then(() => { /* eslint-disable */ this.verifyError = false; From f5739b0292b7ed055c077e97cfd7ad135cc7fd01 Mon Sep 17 00:00:00 2001 From: Jaimyn Mayer Date: Tue, 29 Aug 2023 01:52:54 +1000 Subject: [PATCH 06/10] made API URL routes more consistent --- memberportal/api_admin_tools/urls.py | 36 +++++++++++++++------------- memberportal/membermatters/urls.py | 7 +++--- 2 files changed, 22 insertions(+), 21 deletions(-) diff --git a/memberportal/api_admin_tools/urls.py b/memberportal/api_admin_tools/urls.py index e3a24482..c7ed06d7 100644 --- a/memberportal/api_admin_tools/urls.py +++ b/memberportal/api_admin_tools/urls.py @@ -4,66 +4,68 @@ # all of these urls start with "api/admin/" urlpatterns = [ - path("members/", views.GetMembers.as_view(), name="GetMembers"), + path("api/admin/members/", views.GetMembers.as_view(), name="GetMembers"), path( - "members//state//", + "api/admin/members//state//", views.MemberState.as_view(), name="MemberState", ), path( - "members//makemember/", + "api/admin/members//makemember/", views.MakeMember.as_view(), name="ActivateMember", ), path( - "members//access/", + "api/admin/members//access/", views.MemberAccess.as_view(), name="MemberAccess", ), path( - "members//sendwelcome/", + "api/admin/members//sendwelcome/", views.MemberWelcomeEmail.as_view(), name="MemberWelcomeEmail", ), path( - "members//profile/", + "api/admin/members//profile/", views.MemberProfile.as_view(), name="MemberProfile", ), path( - "members//billing/", + "api/admin/members//billing/", views.MemberBillingInfo.as_view(), name="MemberBillingInfo", ), path( - "members//logs/", + "api/admin/members//logs/", views.MemberLogs.as_view(), name="MemberLogs", ), - path("doors/", views.Doors.as_view(), name="Doors"), - path("interlocks/", views.Interlocks.as_view(), name="Interlocks"), - path("doors//", views.Doors.as_view(), name="Doors"), + path("api/admin/doors/", views.Doors.as_view(), name="Doors"), + path("api/admin/interlocks/", views.Interlocks.as_view(), name="Interlocks"), + path("api/admin/doors//", views.Doors.as_view(), name="Doors"), path( - "interlocks//", views.Interlocks.as_view(), name="Interlocks" + "api/admin/interlocks//", + views.Interlocks.as_view(), + name="Interlocks", ), - path("tiers/", views.MemberTiers.as_view(), name="ManageMemberTiers"), + path("api/admin/tiers/", views.MemberTiers.as_view(), name="ManageMemberTiers"), path( - "tiers//", + "api/admin/tiers//", views.ManageMemberTier.as_view(), name="ManageMemberTier", ), path( - "tiers//plans/", + "api/admin/tiers//plans/", views.ManageMemberTierPlans.as_view(), name="GetPlans", ), path( - "plans/", + "api/admin/plans/", views.ManageMemberTierPlans.as_view(), name="ManagePlans", ), path( - "plans//", + "api/admin/plans//", views.ManageMemberTierPlans.as_view(), name="ManagePlan", ), diff --git a/memberportal/membermatters/urls.py b/memberportal/membermatters/urls.py index 955a81e5..b535277a 100644 --- a/memberportal/membermatters/urls.py +++ b/memberportal/membermatters/urls.py @@ -38,7 +38,7 @@ def safe_constance_get(fld: str): # pass urlpatterns = [ - path("openid/", include("oidc_provider.urls", namespace="oidc_provider")), + path("api/openid/", include("oidc_provider.urls", namespace="oidc_provider")), path("", include("access.urls")), path("", include("memberbucks.urls")), path("", include("api_spacedirectory.urls")), @@ -48,10 +48,9 @@ def safe_constance_get(fld: str): path("", include("api_meeting.urls")), path("", include("api_member_bucks.urls")), path("", include("api_billing.urls")), - path("api/admin/", include("api_admin_tools.urls")), + path("", include("api_admin_tools.urls")), + path("api/", include("django_prometheus.urls")), path("admin/", admin.site.urls), - path("api-auth/", include("rest_framework.urls")), - path("", include("django_prometheus.urls")), ] if settings.DEBUG: From 99e2873fb0cb7d2f03f4f1ac6387db045d433411 Mon Sep 17 00:00:00 2001 From: Jaimyn Mayer Date: Tue, 29 Aug 2023 02:47:15 +1000 Subject: [PATCH 07/10] updated docker nginx proxy config --- docker/nginx.conf | 6 ++++-- memberportal/membermatters/settings.py | 3 +++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/docker/nginx.conf b/docker/nginx.conf index d3d73ac7..cbe34362 100644 --- a/docker/nginx.conf +++ b/docker/nginx.conf @@ -77,9 +77,11 @@ http { proxy_redirect off; proxy_pass http://app_server; proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Real-IP $http_x_real_ip; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Host $server_name; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header X-Forwarded-Host $host; + proxy_set_header X-Forwarded-Port $server_port; } } } diff --git a/memberportal/membermatters/settings.py b/memberportal/membermatters/settings.py index 9af6fa4e..8566ee52 100644 --- a/memberportal/membermatters/settings.py +++ b/memberportal/membermatters/settings.py @@ -291,5 +291,8 @@ OIDC_USERINFO = "membermatters.oidc_provider_settings.userinfo" +USE_X_FORWARDED_HOST = True +SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https") + # Needed for testing OIDC on local development environment with ngrok (oauth requires HTTPS) # SITE_URL = "https://1bd0-122-148-148-138.ngrok-free.app" From 736c15a9b1fc223d3f831bd27aae1fad76f0687b Mon Sep 17 00:00:00 2001 From: Jaimyn Mayer Date: Tue, 29 Aug 2023 03:26:42 +1000 Subject: [PATCH 08/10] made nginx proxy protocol correctly when behind a second reverse proxy --- docker/nginx.conf | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/docker/nginx.conf b/docker/nginx.conf index cbe34362..35f03a39 100644 --- a/docker/nginx.conf +++ b/docker/nginx.conf @@ -25,6 +25,12 @@ http { server localhost:8001 fail_timeout=10s; } + # if another reverse proxy is used the forwarded protocol may be wrong without this check + map $http_x_forwarded_proto $proxied_scheme { + default $http_x_forwarded_proto; + "" $scheme; + } + server { listen 8000 deferred default_server; client_max_body_size 10M; @@ -63,7 +69,7 @@ http { proxy_set_header Host $host; proxy_set_header X-Real-IP $http_x_real_ip; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header X-Forwarded-Proto $proxied_scheme; proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-Port $server_port; proxy_redirect off; @@ -79,7 +85,7 @@ http { proxy_set_header Host $host; proxy_set_header X-Real-IP $http_x_real_ip; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header X-Forwarded-Proto $proxied_scheme; proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-Port $server_port; } From 2a4072061a1f06529cc39f5907f290b1926413b5 Mon Sep 17 00:00:00 2001 From: Jaimyn Mayer Date: Thu, 31 Aug 2023 11:58:16 +1000 Subject: [PATCH 09/10] added missing translation string --- src-frontend/src/i18n/en-AU/index.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src-frontend/src/i18n/en-AU/index.ts b/src-frontend/src/i18n/en-AU/index.ts index 49708b12..d3b8fd2d 100644 --- a/src-frontend/src/i18n/en-AU/index.ts +++ b/src-frontend/src/i18n/en-AU/index.ts @@ -14,6 +14,7 @@ export default { manageTiers: 'Membership Plans', manageTier: 'Manage Membership Plan', managePlan: 'Manage Payment Plan', + verifyEmail: 'Verify your email to continue', adminTools: 'Admin Tools', meetings: 'Meetings', From 12c1780c0a7b568bb9d2db4d49cdec4514281abf Mon Sep 17 00:00:00 2001 From: Jaimyn Mayer Date: Thu, 31 Aug 2023 13:33:46 +1000 Subject: [PATCH 10/10] v3.4.0 --- CHANGELOG.md | 100 ++++++++++++++++++++++++++++++++++++-- package.json | 2 +- src-frontend/package.json | 2 +- 3 files changed, 97 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a02bc3e9..7a760ca2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,28 +5,92 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [v3.4.0] - 2023-08-31 + +### Removed + +- raw sql queries and replaced with Django ORM +- automatic loading of fixtures on first run +- db migrations that refer to now non-existent app + +### Added + +- oauth2 / openid connect (provider) support for SSO +- automatic door/interlock syncing on access changes +- access system status endpoint +- list of links as option for homepage cards +- added dedicated web socket sync/reboot commands +- option to enable discord swipe only on certain doors/interlocks +- automatically sync all rfid card changes to devices +- maintenance lockouts to devices +- flag to opt out accounts from email export +- check for invalid webcam/homepage cards config +- copy to clipboard feature for email export +- types for member objects +- support for postgres database backend + +### Changed + +- changed all environment variables to start with MM\_ +- refactored web socket code +- refactored frontend code and moved to src-frontend folder +- moved to vite and added polyfills etc. +- login page to add background gradient and logo +- migrated lots of frontend code to typescript +- MM logo +- screenshots in docs folder +- updated dockerfile to node 18 +- improved robustness of postmark integration +- increased size limit of some title/description fields +- caprover deployment example +- some API routes to be more consistent layout +- Dockerfile NGINX proxy_pass setup to work behind a second reverse proxy + +### Fixed + +- error messages for successful actions +- discord swipe log url +- manage member subscription data display +- reset access permissions for each member when “all_members” option is toggled off/on +- hide device from members feature +- homepage/welcome email cards and webcam examples +- missing translation strings +- minor bugs in manage member page +- GitHub actions +- dayjs imports +- registration requiring vehicle registration plate (should be optional) +- signals running in raw mode (ie when data importing) +- some frontend URLs in API requests (405 method not allowed errors) + ## [v3.3.0] - 2022-10-10 + ### Added + - Door bump API for unlocking doors from a 3rd party system - better webcam cache busting logic and documentation to configure webcams - option to collect vehicle registration "rego" plates on a member's profile ### Fixed -- Don't initialise twilio if not enabled (thanks @rechner) +- Don't initialise twilio if not enabled (thanks @rechner) ## [v3.2.0] - 2022-09-05 + ### Added + - Enable/disable Canvas induction via constance option - Support memberbucks without Stripe enabled - Support for a site wide currency format via the SITE_LOCALE_CURRENCY option - NZD, USD, and EUR currency locale formats ### Fixed + - Allow signup to succeed if access card requirement is true (commit #cb32009ef08ce21704231f577d61e50250f46463) ## [v3.1.0] - 2022-08-29 + ### Added + - Twilio integration for sending SMS alerts to members - Version to config endpoint for easier debugging - Basic celery setup (and container start script) @@ -34,15 +98,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Locale detection and support for GBP currency ### Changed + - Split constance config into separate module - Specified member's email as reply-to in issue card - Bumped deps by github security bot ### Fixed + - Bug with database fixtures preventing fixtures from loading ## [v3.0.0] - 2022-05-27 + ### Removed + - All Xero support - Legacy http API for door controllers - Member Types (for use with Xero) @@ -50,6 +118,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Unnecessary environment variables ### Added + - Websocket API for access control devices (ping/pong, authorise, sync tags, log access, update device ip) - Django pwned passwords - Loading spinner while app / login page is loading @@ -61,14 +130,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - User event, door and interlock logs to manage member screen ### Changed + - Upgraded to Vue 3, Qusar 2, all frontend dependencies updated - Bumped backend dependencies - Messaging around membership plan / payment plans to make it more clear -- References to "donate" to "make payment" as an exchange of money for goods/services is *not* a donation +- References to "donate" to "make payment" as an exchange of money for goods/services is _not_ a donation - Tidied up manage member UI and made it cleaner - Export mailing list translation to make it clearer ### Fixed + - Logging so it's actually useful now that we've moved to daphne - Redirect on loging sometimes getting stuck - Some forms not saving after modification @@ -84,28 +155,34 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Loading states for door unlock/reboot buttons - Typo in first joined date on digital ID - Door checkin via websocket overriding door object in database -- +- ## [v2.8.0] - 2021-10-20 + ### Removed + - Sendgrid integration for email sending ### Added + - Postmark integration for email sending - Mailchimp integration ### Changed + - Made site sign in/users on site feature optional - Made Dockerfile more development friendly (at expensive of slightly larger images) ### Fixed + - Inconsistent login bug on some browsers and iOS - Not quite mobile friendly sign up page - CSS and layout of membership plan/pricing pages - ## [v2.7.0] - 2021-10-20 + ### Added + - Feature flag system - Most optional features to feature flags - Option for collecting access card instead of inputting it @@ -114,6 +191,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Xero configuration options to database config ### Fixed + - Canvas randomly failing to sync user induction progress (canvas have started including a random null user for some reason) - Canvas api failure logic - Sentry error logging @@ -128,13 +206,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Excessively wide credit card form during signup ### Removed + - Groups feature ### Deprecated + - Access device HTTP endpoints. In a future release the current HTTP endpoints for access control devices will be removed and replaced with the new websocket protocol. ## [v2.6.3] - 2021-09-27 + ### Fixed + - Enable stripe billing menu visibility race condition - Sentry / stripe token race condition - Removed excess console logging @@ -145,26 +227,33 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Date display issue on proxy form ### Changed + - Replaced momentjs with dayjs - + ### Added + - Caprover example template - Basic read the docs website - Build docker image GitHub action ## [v2.6.2] - 2021-09-06 + ### Fixed + - Can't override existing card during signup - Occasional constance settings reset to default value ### Added + - Member billing and subscription info on admin page - Support for sentry error logging ### Changed + - Upgraded base docker image to Alpine 3.14 ## [v2.6.1] - 2021-07-11 + ### Fixed - Fixed checking induction requirements being skipped during signup @@ -180,6 +269,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [v2.6.0] - 2021-07-08 ### Changed + - More work on usage statistics ### Fixed diff --git a/package.json b/package.json index 14a84f56..16903583 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "membermatters", - "version": "3.3.0", + "version": "3.4.0", "devDependencies": { "eslint-webpack-plugin": "^3.1.1", "husky": "^6.0.0", diff --git a/src-frontend/package.json b/src-frontend/package.json index 0eccf71c..13808080 100644 --- a/src-frontend/package.json +++ b/src-frontend/package.json @@ -1,6 +1,6 @@ { "name": "frontend", - "version": "3.3.0", + "version": "3.4.0", "description": "The MemberMatters frontend", "productName": "MemberMatters", "author": "Jaimyn Mayer ",