diff --git a/Tiltfile b/Tiltfile index 87723cc..83ecbd0 100644 --- a/Tiltfile +++ b/Tiltfile @@ -13,11 +13,11 @@ secret_settings( ## cert-manager loaded using this extension is PAINFULLY SLOW, and it must re-install and re-test every time the Tiltfile changes. ## additionally, it is SYNCRHONOUS, which means nothing else can update until cert-manager is updated. @see https://github.com/tilt-dev/tilt-extensions/pull/90#issuecomment-704381205 ## TL;DR: It's much preferred & much faster to use a helm chart for working with cert-manager in every environment. -# load('ext://cert_manager', 'deploy_cert_manager') -# deploy_cert_manager( -# load_to_kind=False, -# version='v1.15.1', -# ) +load('ext://cert_manager', 'deploy_cert_manager') +deploy_cert_manager( + load_to_kind=True, + version='v1.15.1', +) load('ext://helm_remote', 'helm_remote') @@ -120,15 +120,18 @@ docker_build( 'fp/strapi', '.', dockerfile='./d.strapi.dockerfile', - target='dev', + target='strapi', only=[ + './.npmrc', './package.json', './pnpm-lock.yaml', + './pnpm-workspace.yaml', './packages/strapi', './packages/types', ], live_update=[ - sync('./packages/strapi', '/app') + sync('./packages/strapi', '/app'), + run('cd /app && pnpm i', trigger=['./packages/strapi/package.json', './packages/strapi/pnpm-lock.yaml']) ] ) @@ -217,10 +220,10 @@ docker_build( docker_build( - 'fp/scout-manager', + 'fp/scout', '.', dockerfile='d.scout.dockerfile', - target='scout-manager', + target='scout', live_update=[ sync('./packages/scout', '/app'), run('cd /app && pnpm i', trigger=['./packages/scout/package.json', './packages/scout/pnpm-lock.yaml']), @@ -230,6 +233,34 @@ docker_build( ) +docker_build( + 'fp/worker', + '.', + dockerfile='d.worker.dockerfile', + target='worker', + only=[ + './.npmrc', + './package.json', + './pnpm-lock.yaml', + './pnpm-workspace.yaml', + './packages/image', + './packages/scout', + './packages/temporal-workflows', + './packages/temporal-worker', + './packages/types', + './packages/utils', + './packages/video', + './packages/storage', + ], + live_update=[ + sync('./packages/temporal-worker', '/app'), + run('cd /app && pnpm i', trigger=['./packages/temporal-worker/package.json', './packages/temporal-worker/pnpm-lock.yaml']), + ], + # entrypoint='pnpm nodemon --ext js,ts,json,yaml --exec node --no-warnings=ExperimentalWarning --loader ts-node/esm ./src/index.ts' +) + + + docker_build( 'fp/boop', '.', @@ -252,26 +283,26 @@ docker_build( -docker_build( - 'fp/scout-worker', - '.', - # ignore=['./packages/next'], # I wish I could use this ignore to ignore file changes in this dir, but that's not how it works - dockerfile='d.scout.dockerfile', - target='scout-worker', - live_update=[ - # idk if this run() is effective - # run('cd /app && pnpm i', trigger=['./packages/scout/package.json', './packages/scout/pnpm-lock.yaml']), - sync('./packages/scout', '/app'), - ## this is a hack to avoid complete scout image rebuilds when src in ./packages/next is updated - ## ./packages/next needs to be in the build context because scout depends on types exported from next module (a feature of pnpm workspaces) - ## instead of a full rebuild, we put ./packages/next in the live_update spec so the changed files get shoved into /ignore-me - ## ideally, I would like to include ./packages/next in the build context, but ignore file changes there for rebuilds. - ## however, I don't think tilt has this capability. - sync('./packages/next', '/ignore-me'), - ], - # this entrypoint is a godsend. It lets me restart the node app (fast) without having to rebuild the docker container (slow) - entrypoint='pnpm nodemon --ext js,ts,json,yaml --exec node --no-warnings=ExperimentalWarning --loader ts-node/esm ./src/temporal/worker.ts' -) +# docker_build( +# 'fp/scout-worker', +# '.', +# # ignore=['./packages/next'], # I wish I could use this ignore to ignore file changes in this dir, but that's not how it works +# dockerfile='d.scout.dockerfile', +# target='scout-worker', +# live_update=[ +# # idk if this run() is effective +# # run('cd /app && pnpm i', trigger=['./packages/scout/package.json', './packages/scout/pnpm-lock.yaml']), +# sync('./packages/scout', '/app'), +# ## this is a hack to avoid complete scout image rebuilds when src in ./packages/next is updated +# ## ./packages/next needs to be in the build context because scout depends on types exported from next module (a feature of pnpm workspaces) +# ## instead of a full rebuild, we put ./packages/next in the live_update spec so the changed files get shoved into /ignore-me +# ## ideally, I would like to include ./packages/next in the build context, but ignore file changes there for rebuilds. +# ## however, I don't think tilt has this capability. +# sync('./packages/next', '/ignore-me'), +# ], +# # this entrypoint is a godsend. It lets me restart the node app (fast) without having to rebuild the docker container (slow) +# entrypoint='pnpm nodemon --ext js,ts,json,yaml --exec node --no-warnings=ExperimentalWarning --loader ts-node/esm ./src/temporal/worker.ts' +# ) @@ -341,15 +372,10 @@ k8s_resource( ) -k8s_resource( - workload='scout-worker', - resource_deps=['postgres', 'strapi', 'temporal-frontend'], - labels=['backend'], -) k8s_resource( - workload='scout-manager', - resource_deps=['postgres', 'strapi', 'temporal-frontend', 'scout-worker'], + workload='scout', + resource_deps=['postgres', 'strapi', 'temporal-frontend', 'worker'], labels=['backend'], ) @@ -513,6 +539,12 @@ k8s_resource( # resource_deps=['strapi', 'temporal-web'], ) +k8s_resource( + workload='worker', + labels=['backend'], + resource_deps=['strapi', 'temporal-web', 'postgres' ], +) + # k8s_resource( # workload='trigger', # labels=['backend'], diff --git a/charts/fp/templates/bot.yaml b/charts/fp/templates/bot.yaml index 4a2ba46..9b0fb6d 100644 --- a/charts/fp/templates/bot.yaml +++ b/charts/fp/templates/bot.yaml @@ -6,7 +6,7 @@ metadata: labels: app: bot spec: - replicas: {{ .Values.scout.worker.replicas }} + replicas: {{ .Values.bot.replicas }} selector: matchLabels: app: bot diff --git a/charts/fp/templates/scout.yaml b/charts/fp/templates/scout.yaml index 21c2365..5599daf 100644 --- a/charts/fp/templates/scout.yaml +++ b/charts/fp/templates/scout.yaml @@ -1,99 +1,73 @@ -apiVersion: apps/v1 -kind: ReplicaSet -metadata: - name: scout-worker - namespace: futureporn - labels: - app: scout-worker -spec: - replicas: {{ .Values.scout.worker.replicas }} - selector: - matchLabels: - app: scout-worker - template: - metadata: - labels: - app: scout-worker - spec: - containers: - - name: scout-worker - image: "{{ .Values.scout.worker.imageName }}" - imagePullPolicy: Always - ports: - - containerPort: 8080 - env: - - name: TEMPORAL_SERVICE_ADDRESS - value: "temporal-frontend.futureporn.svc.cluster.local:7233" - - name: TEMPORAL_NAMESPACE - value: "futureporn" - - name: TEMPORAL_TASK_QUEUE - value: "scout" - - name: S3_BUCKET_NAME - value: "{{ .Values.scout.s3BucketName }}" - - name: CDN_BUCKET_URL - value: "{{ .Values.scout.cdnBucketUrl }}" - - name: STRAPI_URL - value: https://strapi.fp.sbtp.xyz - - name: S3_BUCKET_APPLICATION_KEY - valueFrom: - secretKeyRef: - name: scout - key: s3BucketApplicationKey - - name: S3_BUCKET_KEY_ID - valueFrom: - secretKeyRef: - name: scout - key: s3BucketKeyId - - name: SCOUT_NITTER_ACCESS_KEY - valueFrom: - secretKeyRef: - name: scout - key: nitterAccessKey - - name: SCOUT_NITTER_URL - value: https://nitter.sbtp.xyz - - name: SCOUT_RECENTS_TOKEN - valueFrom: - secretKeyRef: - name: scout - key: recentsToken - - name: SCOUT_STRAPI_API_KEY - valueFrom: - secretKeyRef: - name: scout - key: strapiApiKey - # - name: SCOUT_IMAP_SERVER - # valueFrom: - # secretKeyRef: - # name: scout - # key: imapServer - # - name: SCOUT_IMAP_PORT - # valueFrom: - # secretKeyRef: - # name: scout - # key: imapPort - # - name: SCOUT_IMAP_USERNAME - # valueFrom: - # secretKeyRef: - # name: scout - # key: imapUsername - # - name: SCOUT_IMAP_PASSWORD - # valueFrom: - # secretKeyRef: - # name: scout - # key: imapPassword - # - name: SCOUT_IMAP_ACCESS_TOKEN - # valueFrom: - # secretKeyRef: - # name: scout - # key: imapAccessToken - # Add any other necessary environment variables - resources: - limits: - cpu: "500m" - memory: "512Mi" - requests: - cpu: "250m" - memory: "256Mi" +# apiVersion: apps/v1 +# kind: ReplicaSet +# metadata: +# name: scout-worker +# namespace: futureporn +# labels: +# app: scout-worker +# spec: +# replicas: {{ .Values.scout.replicas }} +# selector: +# matchLabels: +# app: scout-worker +# template: +# metadata: +# labels: +# app: scout-worker +# spec: +# containers: +# - name: scout-worker +# image: "{{ .Values.scout.imageName }}" +# imagePullPolicy: Always +# ports: +# - containerPort: 8080 +# env: +# - name: TEMPORAL_SERVICE_ADDRESS +# value: "temporal-frontend.futureporn.svc.cluster.local:7233" +# - name: TEMPORAL_NAMESPACE +# value: "futureporn" +# - name: TEMPORAL_TASK_QUEUE +# value: "scout" +# - name: S3_BUCKET_NAME +# value: "{{ .Values.scout.s3BucketName }}" +# - name: CDN_BUCKET_URL +# value: "{{ .Values.scout.cdnBucketUrl }}" +# - name: STRAPI_URL +# value: https://strapi.fp.sbtp.xyz +# - name: S3_BUCKET_APPLICATION_KEY +# valueFrom: +# secretKeyRef: +# name: scout +# key: s3BucketApplicationKey +# - name: S3_BUCKET_KEY_ID +# valueFrom: +# secretKeyRef: +# name: scout +# key: s3BucketKeyId +# - name: SCOUT_NITTER_ACCESS_KEY +# valueFrom: +# secretKeyRef: +# name: scout +# key: nitterAccessKey +# - name: SCOUT_NITTER_URL +# value: https://nitter.sbtp.xyz +# - name: SCOUT_RECENTS_TOKEN +# valueFrom: +# secretKeyRef: +# name: scout +# key: recentsToken +# - name: SCOUT_STRAPI_API_KEY +# valueFrom: +# secretKeyRef: +# name: scout +# key: strapiApiKey +# resources: +# limits: +# cpu: "500m" +# memory: "512Mi" +# requests: +# cpu: "250m" +# memory: "256Mi" @@ -101,23 +75,23 @@ spec: apiVersion: apps/v1 kind: Deployment metadata: - name: scout-manager + name: scout namespace: futureporn labels: - app: scout-manager + app: scout spec: - replicas: 1 + replicas: {{ .Values.scout.replicas }} selector: matchLabels: - app: scout-manager + app: scout template: metadata: labels: - app: scout-manager + app: scout spec: containers: - - name: scout-manager - image: "{{ .Values.scout.manager.imageName }}" + - name: scout + image: "{{ .Values.scout.imageName }}" ports: - name: http containerPort: 3000 @@ -146,57 +120,4 @@ spec: valueFrom: secretKeyRef: name: scout - key: imapAccessToken - # env: - # - name: POSTGRES_REALTIME_CONNECTION_STRING - # valueFrom: - # secretKeyRef: - # name: realtime - # key: postgresRealtimeConnectionString - # - name: CDN_BUCKET_URL - # value: "{{ .Values.scout.cdnBucketUrl }}" - # - name: STRAPI_URL - # value: https://strapi.fp.sbtp.xyz - # - name: SCOUT_NITTER_ACCESS_KEY - # valueFrom: - # secretKeyRef: - # name: scout - # key: nitterAccessKey - # - name: SCOUT_NITTER_URL - # value: https://nitter.sbtp.xyz - # - name: SCOUT_RECENTS_TOKEN - # valueFrom: - # secretKeyRef: - # name: scout - # key: recentsToken - # - name: SCOUT_IMAP_SERVER - # valueFrom: - # secretKeyRef: - # name: scout - # key: imapServer - # - name: SCOUT_IMAP_PORT - # valueFrom: - # secretKeyRef: - # name: scout - # key: imapPort - # - name: SCOUT_IMAP_USERNAME - # valueFrom: - # secretKeyRef: - # name: scout - # key: imapUsername - # - name: SCOUT_IMAP_PASSWORD - # valueFrom: - # secretKeyRef: - # name: scout - # key: imapPassword - # - name: SCOUT_IMAP_ACCESS_TOKEN - # valueFrom: - # secretKeyRef: - # name: scout - # key: imapAccessToken - # - name: SCOUT_STRAPI_API_KEY - # valueFrom: - # secretKeyRef: - # name: scout - # key: strapiApiKey - + key: imapAccessToken \ No newline at end of file diff --git a/charts/fp/templates/worker.yaml b/charts/fp/templates/worker.yaml new file mode 100644 index 0000000..618cedb --- /dev/null +++ b/charts/fp/templates/worker.yaml @@ -0,0 +1,67 @@ +apiVersion: apps/v1 +kind: ReplicaSet +metadata: + name: worker + namespace: futureporn + labels: + app: worker +spec: + replicas: {{ .Values.worker.replicas }} + selector: + matchLabels: + app: worker + template: + metadata: + labels: + app: worker + spec: + containers: + - name: worker + image: "{{ .Values.worker.imageName }}" + imagePullPolicy: Always + ports: + - containerPort: 8080 + env: + - name: TEMPORAL_SERVICE_ADDRESS + value: "temporal-frontend.futureporn.svc.cluster.local:7233" + - name: TEMPORAL_NAMESPACE + value: "futureporn" + - name: TEMPORAL_TASK_QUEUE + value: "futureporn" + # - name: STRAPI_URL + # value: https://strapi.fp.sbtp.xyz + # - name: S3_BUCKET_APPLICATION_KEY + # valueFrom: + # secretKeyRef: + # name: scout + # key: s3BucketApplicationKey + # - name: S3_BUCKET_KEY_ID + # valueFrom: + # secretKeyRef: + # name: scout + # key: s3BucketKeyId + # - name: SCOUT_NITTER_ACCESS_KEY + # valueFrom: + # secretKeyRef: + # name: scout + # key: nitterAccessKey + # - name: SCOUT_NITTER_URL + # value: https://nitter.sbtp.xyz + # - name: SCOUT_RECENTS_TOKEN + # valueFrom: + # secretKeyRef: + # name: scout + # key: recentsToken + # - name: SCOUT_STRAPI_API_KEY + # valueFrom: + # secretKeyRef: + # name: scout + # key: strapiApiKey + resources: + limits: + cpu: "500m" + memory: "512Mi" + requests: + cpu: "250m" + memory: "256Mi" + diff --git a/charts/fp/values.yaml b/charts/fp/values.yaml index 2e600ad..b42535f 100644 --- a/charts/fp/values.yaml +++ b/charts/fp/values.yaml @@ -10,12 +10,17 @@ next: nodeExtraCaCerts: /app/letsencrypt-stg-root-x1.pem capture: imageName: fp/capture +worker: + imageName: fp/worker + replicas: 3 + cdnBucketUrl: https://fp-dev.b-cdn.net + s3BucketName: fp-dev scout: - manager: - imageName: fp/scout-manager - worker: - imageName: fp/scout-worker - replicas: 1 + replicas: 1 + imageName: fp/scout + # worker: + # imageName: fp/scout- + # replicas: 1 pubsubServerUrl: https://realtime.futureporn.svc.cluster.local/faye hostname: next.futureporn.svc.cluster.local cdnBucketUrl: https://fp-dev.b-cdn.net @@ -25,6 +30,7 @@ strapi: port: 1339 url: https://strapi.fp.sbtp.xyz hostname: strapi.fp.sbtp.xyz + # hostname: strapi.futureporn.svc.cluster.local ## https://gitea.futureporn.net/futureporn/pm/issues/126 ingressClassName: traefik ngrok: hostname: grateful-engaging-cicada.ngrok-free.app @@ -53,6 +59,7 @@ bot: discordChannelId: "1185024773231759481" discordGuildId: "1084674137391374338" imageName: fp/bot + replicas: 1 trigger: imageName: ghcr.io/triggerdotdev/trigger.dev:self-host-rc.3 worker: diff --git a/d.next.dockerfile b/d.next.dockerfile index 979233e..3015d0e 100644 --- a/d.next.dockerfile +++ b/d.next.dockerfile @@ -21,23 +21,32 @@ ENV NEXT_TELEMETRY_DISABLED 1 ENV NODE_EXTRA_CA_CERTS ${NODE_EXTRA_CA_CERTS} COPY pnpm-lock.yaml ./ RUN pnpm fetch -COPY ./packages/next /app -RUN --mount=type=cache,id=pnpm-store,target=/pnpm/store pnpm install +# COPY pnpm-lock.yaml .npmrc package.json . +COPY ./packages/next ./packages/next +COPY ./packages/types ./packages/types +# COPY ./packages/strapi ./packages/strapi +# COPY ./packages/scout ./packages/scout +# COPY ./packages/image ./packages/image +# COPY ./packages/utils ./packages/utils +# COPY ./packages/temporal-workflows ./packages/temporal-workflows + +RUN --mount=type=cache,id=pnpm-store,target=/pnpm/store pnpm install --recursive --frozen-lockfile --prefer-offline FROM install AS dev CMD ["pnpm", "run", "dev"] FROM install AS build -RUN pnpm run build +RUN pnpm run -r build +RUN pnpm --filter=next deploy --prod /prod/next FROM deps AS next RUN apt-get update && apt-get install -y -qq --no-install-recommends dumb-init -COPY --chown=node:node --from=build /app/package.json /app/pnpm-lock.yaml ./ +COPY --chown=node:node --from=build /prod/next/package.json /prod/next/pnpm-lock.yaml ./ RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --prod --frozen-lockfile -COPY --chown=node:node --from=build /app/public ./public -COPY --chown=node:node --from=build /app/.next/standalone ./ -COPY --chown=node:node --from=build /app/.next/static ./.next/static +COPY --chown=node:node --from=build /prod/next/public ./public +COPY --chown=node:node --from=build /prod/next/.next/standalone ./ +COPY --chown=node:node --from=build /prod/next/.next/static ./.next/static ENV TZ=UTC ENV NODE_ENV=production ENV HOSTNAME="0.0.0.0" diff --git a/d.scout.dockerfile b/d.scout.dockerfile index 68f10fa..e8673ac 100644 --- a/d.scout.dockerfile +++ b/d.scout.dockerfile @@ -11,11 +11,15 @@ COPY package.json pnpm-lock.yaml . COPY ./packages/scout/pnpm-lock.yaml ./packages/scout/ COPY ./packages/taco/pnpm-lock.yaml ./packages/taco/ COPY ./packages/types/pnpm-lock.yaml ./packages/types/ +COPY ./packages/temporal-workflows/pnpm-lock.yaml ./packages/temporal-workflows/ +COPY ./packages/temporal-worker/pnpm-lock.yaml ./packages/temporal-worker/ RUN pnpm fetch RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --recursive --frozen-lockfile COPY ./packages/scout/ ./packages/scout/ COPY ./packages/taco/ ./packages/taco/ COPY ./packages/types/ ./packages/types/ +COPY ./packages/temporal-workflows/ ./packages/temporal-workflows/ +COPY ./packages/temporal-worker/ ./packages/temporal-worker/ RUN pnpm -r build RUN pnpm deploy --filter=scout --prod /prod/scout diff --git a/d.strapi.dockerfile b/d.strapi.dockerfile index e063003..5a3b99c 100644 --- a/d.strapi.dockerfile +++ b/d.strapi.dockerfile @@ -1,7 +1,8 @@ FROM node:20 AS base -# Installing libvips-dev for sharp Compatibility +## Installing libvips-dev for sharp Compatibility +## (only needed on alpine) # RUN apk update && apk add --no-cache build-base gcc autoconf automake zlib-dev libpng-dev nasm bash vips-dev git -RUN corepack enable +RUN corepack enable && corepack prepare pnpm@9.5.0 --activate ENV PNPM_HOME="/pnpm" ENV PATH="$PNPM_HOME:$PATH" ARG NODE_ENV=development @@ -10,21 +11,39 @@ EXPOSE 1339 ENTRYPOINT ["pnpm"] FROM base AS build +WORKDIR /app RUN mkdir -p /prod/strapi -WORKDIR /opt/ -COPY ./packages/strapi/package.json ./packages/strapi/pnpm-lock.yaml ./ +COPY pnpm-workspace.yaml pnpm-lock.yaml .npmrc package.json . +COPY ./packages/types ./packages/types +COPY ./packages/strapi ./packages/strapi RUN pnpm fetch -RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install -g node-gyp -RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --frozen-lockfile -ENV PATH /opt/node_modules/.bin:$PATH -WORKDIR /opt/app -COPY ./packages/strapi/. . +RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install -g node-gyp --prefer-offline +RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --recursive --prefer-offline RUN pnpm -r build RUN pnpm deploy --filter=strapi /prod/strapi +RUN ls -lah ./ +RUN ls -lah ./packages +RUN ls -lah ./packages/strapi +RUN ls -lah /prod/strapi + + +# FROM base AS build +# RUN mkdir -p /prod/strapi +# WORKDIR /opt/ +# COPY ./packages/strapi/package.json ./packages/strapi/pnpm-lock.yaml ./ +# RUN pnpm fetch +# RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install -g node-gyp +# RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --frozen-lockfile +# ENV PATH /opt/node_modules/.bin:$PATH +# WORKDIR /opt/app +# COPY ./packages/strapi/. . +# RUN pnpm -r build +# RUN pnpm deploy --filter=strapi /prod/strapi -FROM build AS dev +FROM base AS dev +COPY --from=build /prod/strapi . CMD ["run", "develop"] diff --git a/d.worker.dockerfile b/d.worker.dockerfile new file mode 100644 index 0000000..9cd57c1 --- /dev/null +++ b/d.worker.dockerfile @@ -0,0 +1,41 @@ +FROM node:20 as base +ENV PNPM_HOME="/pnpm" +ENV PATH="$PNPM_HOME:$PATH" +WORKDIR /app +RUN corepack enable && corepack prepare pnpm@9.5.0 --activate + +FROM base AS install +COPY pnpm-lock.yaml .npmrc package.json . +COPY ./packages/types/ ./packages/types/ +COPY ./packages/storage/ ./packages/storage/ +COPY ./packages/scout/ ./packages/scout/ +COPY ./packages/image/ ./packages/image/ +COPY ./packages/utils/ ./packages/utils/ +COPY ./packages/temporal-worker/ ./packages/temporal-worker/ +COPY ./packages/temporal-workflows/ ./packages/temporal-workflows/ +RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --recursive --frozen-lockfile --prefer-offline + + +FROM install AS build +RUN pnpm -r build +RUN pnpm deploy --filter=temporal-worker --prod /prod/temporal-worker + +# FROM base as build +# RUN mkdir -p /prod/worker +# COPY pnpm-workspace.yaml package.json pnpm-lock.yaml .npmrc . +# COPY ./packages/temporal-workflows/pnpm-lock.yaml ./packages/temporal-workflows/ +# COPY ./packages/temporal-worker/pnpm-lock.yaml ./packages/temporal-worker/ +# # RUN pnpm fetch +# RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --recursive --frozen-lockfile --prefer-offline +# COPY ./packages/temporal-workflows/ ./packages/temporal-workflows/ +# COPY ./packages/temporal-worker/ ./packages/temporal-worker/ +# RUN ls -la . +# RUN ls -la ./packages +# RUN ls -la ./packages/temporal-workflows +# RUN pnpm -r build +# RUN pnpm deploy --filter=temporal-worker --prod /prod/worker + +FROM base as worker +COPY --from=build /prod/temporal-worker . +ENTRYPOINT ["pnpm", "start"] + diff --git a/packages/bot/pnpm-lock.yaml b/packages/bot/pnpm-lock.yaml index 0b5b89f..99bedfa 100644 --- a/packages/bot/pnpm-lock.yaml +++ b/packages/bot/pnpm-lock.yaml @@ -25,40 +25,6 @@ importers: specifier: ^5.5.3 version: 5.5.3 - ../..: {} - - ../archive: {} - - ../boop: {} - - ../capture: {} - - ../image: {} - - ../infra: {} - - ../next: {} - - ../scout: {} - - ../storage: {} - - ../strapi: {} - - ../taco: {} - - ../temporal-worker: {} - - ../temporal-workflows: {} - - ../types: {} - - ../uppy: {} - - ../utils: {} - - ../video: {} - packages: '@cspotcode/source-map-support@0.8.1': diff --git a/packages/next/package.json b/packages/next/package.json index ce92beb..204a676 100644 --- a/packages/next/package.json +++ b/packages/next/package.json @@ -59,11 +59,12 @@ "react-hook-form": "^7.52.1", "react-loading-skeleton": "^3.4.0", "react-toastify": "^9.1.3", + "sass": "^1.77.8", "sharp": "^0.33.4", "slugify": "^1.6.6", "styled-components": "5.3.3", - "yup": "^1.4.0", - "types": "workspace:*" + "types": "workspace:*", + "yup": "^1.4.0" }, "devDependencies": { "@types/node": "^20.14.9", diff --git a/packages/next/pnpm-lock.yaml b/packages/next/pnpm-lock.yaml index fec7cdf..3decc22 100644 --- a/packages/next/pnpm-lock.yaml +++ b/packages/next/pnpm-lock.yaml @@ -121,13 +121,13 @@ importers: version: 13.1.3 next: specifier: 14.0.4 - version: 14.0.4(@babel/core@7.24.7)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 14.0.4(@babel/core@7.24.7)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.8) next-goatcounter: specifier: ^1.0.5 - version: 1.0.5(next@14.0.4(@babel/core@7.24.7)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 1.0.5(next@14.0.4(@babel/core@7.24.7)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.8))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) nextjs-toploader: specifier: ^1.6.12 - version: 1.6.12(next@14.0.4(@babel/core@7.24.7)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 1.6.12(next@14.0.4(@babel/core@7.24.7)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.8))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) plyr: specifier: ^3.7.8 version: 3.7.8 @@ -155,6 +155,9 @@ importers: react-toastify: specifier: ^9.1.3 version: 9.1.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + sass: + specifier: ^1.77.8 + version: 1.77.8 sharp: specifier: ^0.33.4 version: 0.33.4 @@ -891,6 +894,10 @@ packages: resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} engines: {node: '>=8'} + anymatch@3.1.3: + resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} + engines: {node: '>= 8'} + argparse@1.0.10: resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} @@ -964,6 +971,10 @@ packages: base64-js@1.5.1: resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + binary-extensions@2.3.0: + resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} + engines: {node: '>=8'} + bl@4.1.0: resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} @@ -1020,6 +1031,10 @@ packages: resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} engines: {node: '>=10'} + chokidar@3.6.0: + resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} + engines: {node: '>= 8.10.0'} + chownr@1.1.4: resolution: {integrity: sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==} @@ -1400,6 +1415,11 @@ packages: fs.realpath@1.0.0: resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} + fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + function-bind@1.1.2: resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} @@ -1519,6 +1539,9 @@ packages: resolution: {integrity: sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==} engines: {node: '>= 4'} + immutable@4.3.6: + resolution: {integrity: sha512-Ju0+lEMyzMVZarkTn/gqRpdqd5dOPaz1mCZ0SH3JV6iFw81PldE/PEB1hWVEA288HPt4WXW8O7AWxB10M+03QQ==} + import-fresh@3.3.0: resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} engines: {node: '>=6'} @@ -1559,6 +1582,10 @@ packages: is-bigint@1.0.4: resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==} + is-binary-path@2.1.0: + resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} + engines: {node: '>=8'} + is-boolean-object@1.1.2: resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==} engines: {node: '>= 0.4'} @@ -1855,6 +1882,10 @@ packages: node-releases@2.0.14: resolution: {integrity: sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==} + normalize-path@3.0.0: + resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} + engines: {node: '>=0.10.0'} + nprogress@0.2.0: resolution: {integrity: sha512-I19aIingLgR1fmhftnbWWO3dXc0hSxqHQHQb3H8m+K3TnEn/iSeTZZOyvKXWqQESMwuUVnatlCnZdLBZZt2VSA==} @@ -2052,6 +2083,10 @@ packages: resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} engines: {node: '>= 6'} + readdirp@3.6.0: + resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} + engines: {node: '>=8.10.0'} + reflect.getprototypeof@1.0.6: resolution: {integrity: sha512-fmfw4XgoDke3kdI6h4xcUz1dG8uaiv5q9gcEwLS4Pnth2kxT+GZ7YehS1JTMGBQmtV7Y4GFGbs2re2NqhdozUg==} engines: {node: '>= 0.4'} @@ -2105,6 +2140,11 @@ packages: resolution: {integrity: sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==} engines: {node: '>= 0.4'} + sass@1.77.8: + resolution: {integrity: sha512-4UHg6prsrycW20fqLGPShtEvo/WyHRVRHwOP4DzkUrObWoWI05QBSfzU71TVB7PFaL104TwNaHpjlWXAZbQiNQ==} + engines: {node: '>=14.0.0'} + hasBin: true + sax@1.4.1: resolution: {integrity: sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==} @@ -3162,6 +3202,11 @@ snapshots: dependencies: color-convert: 2.0.1 + anymatch@3.1.3: + dependencies: + normalize-path: 3.0.0 + picomatch: 2.3.1 + argparse@1.0.10: dependencies: sprintf-js: 1.0.3 @@ -3274,6 +3319,8 @@ snapshots: base64-js@1.5.1: {} + binary-extensions@2.3.0: {} + bl@4.1.0: dependencies: buffer: 5.7.1 @@ -3342,6 +3389,18 @@ snapshots: ansi-styles: 4.3.0 supports-color: 7.2.0 + chokidar@3.6.0: + dependencies: + anymatch: 3.1.3 + braces: 3.0.3 + glob-parent: 5.1.2 + is-binary-path: 2.1.0 + is-glob: 4.0.3 + normalize-path: 3.0.0 + readdirp: 3.6.0 + optionalDependencies: + fsevents: 2.3.3 + chownr@1.1.4: {} classnames@2.5.1: {} @@ -3628,7 +3687,7 @@ snapshots: eslint: 8.57.0 eslint-import-resolver-node: 0.3.9 eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.3.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(eslint@8.57.0))(eslint@8.57.0) - eslint-plugin-import: 2.29.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.3.3))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0) + eslint-plugin-import: 2.29.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.3.3))(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.3.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0) eslint-plugin-jsx-a11y: 6.9.0(eslint@8.57.0) eslint-plugin-react: 7.34.3(eslint@8.57.0) eslint-plugin-react-hooks: 4.6.2(eslint@8.57.0) @@ -3652,7 +3711,7 @@ snapshots: enhanced-resolve: 5.17.0 eslint: 8.57.0 eslint-module-utils: 2.8.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.3.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.3.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0) - eslint-plugin-import: 2.29.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.3.3))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0) + eslint-plugin-import: 2.29.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.3.3))(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.3.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0) fast-glob: 3.3.2 get-tsconfig: 4.7.5 is-core-module: 2.14.0 @@ -3674,7 +3733,7 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-plugin-import@2.29.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.3.3))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0): + eslint-plugin-import@2.29.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.3.3))(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.3.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0): dependencies: array-includes: 3.1.8 array.prototype.findlastindex: 1.2.5 @@ -3878,6 +3937,9 @@ snapshots: fs.realpath@1.0.0: {} + fsevents@2.3.3: + optional: true + function-bind@1.1.2: {} function.prototype.name@1.1.6: @@ -4006,6 +4068,8 @@ snapshots: ignore@5.3.1: {} + immutable@4.3.6: {} + import-fresh@3.3.0: dependencies: parent-module: 1.0.1 @@ -4048,6 +4112,10 @@ snapshots: dependencies: has-bigints: 1.0.2 + is-binary-path@2.1.0: + dependencies: + binary-extensions: 2.3.0 + is-boolean-object@1.1.2: dependencies: call-bind: 1.0.7 @@ -4263,13 +4331,13 @@ snapshots: natural-compare@1.4.0: {} - next-goatcounter@1.0.5(next@14.0.4(@babel/core@7.24.7)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + next-goatcounter@1.0.5(next@14.0.4(@babel/core@7.24.7)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.8))(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: - next: 14.0.4(@babel/core@7.24.7)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + next: 14.0.4(@babel/core@7.24.7)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.8) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - next@14.0.4(@babel/core@7.24.7)(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + next@14.0.4(@babel/core@7.24.7)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.8): dependencies: '@next/env': 14.0.4 '@swc/helpers': 0.5.2 @@ -4291,13 +4359,14 @@ snapshots: '@next/swc-win32-arm64-msvc': 14.0.4 '@next/swc-win32-ia32-msvc': 14.0.4 '@next/swc-win32-x64-msvc': 14.0.4 + sass: 1.77.8 transitivePeerDependencies: - '@babel/core' - babel-plugin-macros - nextjs-toploader@1.6.12(next@14.0.4(@babel/core@7.24.7)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + nextjs-toploader@1.6.12(next@14.0.4(@babel/core@7.24.7)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.8))(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: - next: 14.0.4(@babel/core@7.24.7)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + next: 14.0.4(@babel/core@7.24.7)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.8) nprogress: 0.2.0 prop-types: 15.8.1 react: 18.3.1 @@ -4311,6 +4380,8 @@ snapshots: node-releases@2.0.14: {} + normalize-path@3.0.0: {} + nprogress@0.2.0: {} object-assign@4.1.1: {} @@ -4525,6 +4596,10 @@ snapshots: string_decoder: 1.3.0 util-deprecate: 1.0.2 + readdirp@3.6.0: + dependencies: + picomatch: 2.3.1 + reflect.getprototypeof@1.0.6: dependencies: call-bind: 1.0.7 @@ -4587,6 +4662,12 @@ snapshots: es-errors: 1.3.0 is-regex: 1.1.4 + sass@1.77.8: + dependencies: + chokidar: 3.6.0 + immutable: 4.3.6 + source-map-js: 1.2.0 + sax@1.4.1: {} scheduler@0.23.2: diff --git a/packages/scout/package.json b/packages/scout/package.json index 953f326..4746e44 100644 --- a/packages/scout/package.json +++ b/packages/scout/package.json @@ -37,7 +37,6 @@ "imapflow": "^1.0.160", "limiter": "2.0.1", "mailparser": "^3.7.1", - "next": "workspace:*", "node-fetch": "^3.3.0", "nodemon": "^3.1.3", "p-retry": "^5.1.2", @@ -48,12 +47,12 @@ "ts-node": "^10.9.2", "tsx": "^4.7.2", "types": "workspace:^", - "typescript": "^5.4.5", "xpath": "^0.0.34" }, "packageManager": "pnpm@9.2.0", "devDependencies": { "chai": "^5.1.0", - "mocha": "^10.4.0" + "mocha": "^10.4.0", + "typescript": "^5.4.5" } } diff --git a/packages/scout/pnpm-lock.yaml b/packages/scout/pnpm-lock.yaml index e97ddec..35c0474 100644 --- a/packages/scout/pnpm-lock.yaml +++ b/packages/scout/pnpm-lock.yaml @@ -65,9 +65,6 @@ importers: mailparser: specifier: ^3.7.1 version: 3.7.1 - next: - specifier: workspace:* - version: link:../next node-fetch: specifier: ^3.3.0 version: 3.3.2 @@ -98,9 +95,6 @@ importers: types: specifier: workspace:^ version: link:../types - typescript: - specifier: ^5.4.5 - version: 5.5.3 xpath: specifier: ^0.0.34 version: 0.0.34 @@ -111,6 +105,9 @@ importers: mocha: specifier: ^10.4.0 version: 10.6.0 + typescript: + specifier: ^5.4.5 + version: 5.5.3 packages: diff --git a/packages/scout/src/index.ts b/packages/scout/src/index.ts index 4b3e9d2..21cc9f2 100644 --- a/packages/scout/src/index.ts +++ b/packages/scout/src/index.ts @@ -8,7 +8,7 @@ import { checkEmail } from './parsers.js' // import { createStreamInDb } from './signals.js' import { Email } from './imap.js' import { Client, Connection } from '@temporalio/client' -import { NotificationData, processEmail } from './temporal/workflows.js' +import { NotificationData, processEmailNotification } from 'temporal-workflows' import { FetchMessageObject } from 'imapflow' import { createId } from '@paralleldrive/cuid2' diff --git a/packages/storage/package.json b/packages/storage/package.json index 06bdd58..a075ff4 100644 --- a/packages/storage/package.json +++ b/packages/storage/package.json @@ -1,5 +1,6 @@ { "name": "storage", + "type": "module", "version": "1.0.0", "description": "", "main": "index.js", diff --git a/packages/storage/src/s3.ts b/packages/storage/src/s3.ts index 40e166c..788c9b8 100644 --- a/packages/storage/src/s3.ts +++ b/packages/storage/src/s3.ts @@ -3,7 +3,7 @@ dotenv.config({ path: '../../.env', }); -import { S3Client, S3ClientConfig } from "@aws-sdk/client-s3"; +import { S3Client, type S3ClientConfig } from "@aws-sdk/client-s3"; import { Upload } from "@aws-sdk/lib-storage"; import { createId } from '@paralleldrive/cuid2'; import { basename } from 'node:path'; diff --git a/packages/strapi/package.json b/packages/strapi/package.json index b31fe17..fcd34d9 100644 --- a/packages/strapi/package.json +++ b/packages/strapi/package.json @@ -19,7 +19,12 @@ "@strapi/plugin-i18n": "4.25.3", "@strapi/plugin-users-permissions": "4.25.3", "@strapi/strapi": "4.25.3", + "@strapi/utils": "^4.25.3", "canvas": "^2.11.2", + "date-fns": "^3.6.0", + "dotenv": "^16.4.5", + "lodash": "^4.17.21", + "node-fetch": "^2.7.0", "pg": "8.8.0", "react": "^18.0.0", "react-dom": "^18.0.0", @@ -37,5 +42,6 @@ "node": "20.x.x", "npm": ">=6.0.0" }, + "packageManager": "pnpm@9.5.0", "license": "MIT" } diff --git a/packages/strapi/pnpm-lock.yaml b/packages/strapi/pnpm-lock.yaml index 7f88e67..f74f8d0 100644 --- a/packages/strapi/pnpm-lock.yaml +++ b/packages/strapi/pnpm-lock.yaml @@ -32,9 +32,24 @@ importers: '@strapi/strapi': specifier: 4.25.3 version: 4.25.3(@babel/runtime@7.24.7)(@codemirror/autocomplete@6.17.0(@codemirror/language@6.10.2)(@codemirror/state@6.4.1)(@codemirror/view@6.28.4)(@lezer/common@1.2.1))(@codemirror/language@6.10.2)(@codemirror/lint@6.8.1)(@codemirror/search@6.5.6)(@codemirror/state@6.4.1)(@codemirror/theme-one-dark@6.1.2)(@codemirror/view@6.28.4)(@swc/helpers@0.5.11)(@types/hoist-non-react-statics@3.3.5)(@types/node@20.14.10)(@types/react@18.3.3)(codemirror@5.65.16)(pg@8.8.0)(react-dom@18.3.1(react@18.3.1))(react-router-dom@5.3.4(react@18.3.1))(react@18.3.1)(redux@4.2.1)(styled-components@5.3.3(@babel/core@7.24.7)(react-dom@18.3.1(react@18.3.1))(react-is@18.3.1)(react@18.3.1))(terser@5.31.2)(type-fest@2.19.0) + '@strapi/utils': + specifier: ^4.25.3 + version: 4.25.3 canvas: specifier: ^2.11.2 version: 2.11.2 + date-fns: + specifier: ^3.6.0 + version: 3.6.0 + dotenv: + specifier: ^16.4.5 + version: 16.4.5 + lodash: + specifier: ^4.17.21 + version: 4.17.21 + node-fetch: + specifier: ^2.7.0 + version: 2.7.0 pg: specifier: 8.8.0 version: 8.8.0 @@ -2901,6 +2916,9 @@ packages: resolution: {integrity: sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==} engines: {node: '>=0.11'} + date-fns@3.6.0: + resolution: {integrity: sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww==} + debounce@1.2.1: resolution: {integrity: sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug==} @@ -3118,6 +3136,10 @@ packages: resolution: {integrity: sha512-05POuPJyPpO6jqzTNweQFfAyMSD4qa4lvsMOWyTRTdpHKy6nnnN+IYWaXF+lHivhBH/ufDKlR4IWCAN3oPnHuw==} engines: {node: '>=12'} + dotenv@16.4.5: + resolution: {integrity: sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==} + engines: {node: '>=12'} + duplexer@0.1.2: resolution: {integrity: sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==} @@ -10544,6 +10566,8 @@ snapshots: dependencies: '@babel/runtime': 7.24.7 + date-fns@3.6.0: {} + debounce@1.2.1: {} debug@2.6.9: @@ -10744,6 +10768,8 @@ snapshots: dotenv@14.2.0: {} + dotenv@16.4.5: {} + duplexer@0.1.2: {} eastasianwidth@0.2.0: {} diff --git a/packages/strapi/src/extensions/README.md b/packages/strapi/src/extensions/README.md new file mode 100644 index 0000000..52db426 --- /dev/null +++ b/packages/strapi/src/extensions/README.md @@ -0,0 +1,13 @@ +# strapi extensions + +note by CJ + +Reminder: Plugins don't go here. Plugins are added using pnpm. example: `pnpm add strapi-chatgpt` + + +This extensions directory is the place for plugin override code. + +@see https://docs.strapi.io/dev-docs/plugins-extension + + +We are using overrides patch in patreon support. In ./users-permissions/services/providers-registry.js we make some changes. When user logs in via Patreon, we determine if the Patreon account is a Futureporn supporter. Based on that information, we update the user role to one of 'Authenticated' or 'Patron'. \ No newline at end of file diff --git a/packages/strapi/src/extensions/users-permissions/.eslintignore b/packages/strapi/src/extensions/users-permissions/.eslintignore deleted file mode 100644 index 1723d82..0000000 --- a/packages/strapi/src/extensions/users-permissions/.eslintignore +++ /dev/null @@ -1,2 +0,0 @@ -node_modules/ -.eslintrc.js diff --git a/packages/strapi/src/extensions/users-permissions/.eslintrc.js b/packages/strapi/src/extensions/users-permissions/.eslintrc.js deleted file mode 100644 index a6c2c1e..0000000 --- a/packages/strapi/src/extensions/users-permissions/.eslintrc.js +++ /dev/null @@ -1,14 +0,0 @@ -module.exports = { - root: true, - overrides: [ - { - files: ['admin/**/*'], - extends: ['custom/front'], - }, - { - files: ['**/*'], - excludedFiles: ['admin/**/*'], - extends: ['custom/back'], - }, - ], -}; diff --git a/packages/strapi/src/extensions/users-permissions/LICENSE b/packages/strapi/src/extensions/users-permissions/LICENSE deleted file mode 100644 index 638baf8..0000000 --- a/packages/strapi/src/extensions/users-permissions/LICENSE +++ /dev/null @@ -1,22 +0,0 @@ -Copyright (c) 2015-present Strapi Solutions SAS - -Portions of the Strapi software are licensed as follows: - -* All software that resides under an "ee/" directory (the “EE Software”), if that directory exists, is licensed under the license defined in "ee/LICENSE". - -* All software outside of the above-mentioned directories or restrictions above is available under the "MIT Expat" license as set forth below. - -MIT Expat License - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. \ No newline at end of file diff --git a/packages/strapi/src/extensions/users-permissions/README.md b/packages/strapi/src/extensions/users-permissions/README.md deleted file mode 100644 index af1f65a..0000000 --- a/packages/strapi/src/extensions/users-permissions/README.md +++ /dev/null @@ -1 +0,0 @@ -# Strapi plugin diff --git a/packages/strapi/src/extensions/users-permissions/admin/src/components/BoundRoute/getMethodColor.js b/packages/strapi/src/extensions/users-permissions/admin/src/components/BoundRoute/getMethodColor.js deleted file mode 100644 index 1ad903b..0000000 --- a/packages/strapi/src/extensions/users-permissions/admin/src/components/BoundRoute/getMethodColor.js +++ /dev/null @@ -1,41 +0,0 @@ -const getMethodColor = (verb) => { - switch (verb) { - case 'POST': { - return { - text: 'success600', - border: 'success200', - background: 'success100', - }; - } - case 'GET': { - return { - text: 'secondary600', - border: 'secondary200', - background: 'secondary100', - }; - } - case 'PUT': { - return { - text: 'warning600', - border: 'warning200', - background: 'warning100', - }; - } - case 'DELETE': { - return { - text: 'danger600', - border: 'danger200', - background: 'danger100', - }; - } - default: { - return { - text: 'neutral600', - border: 'neutral200', - background: 'neutral100', - }; - } - } -}; - -export default getMethodColor; diff --git a/packages/strapi/src/extensions/users-permissions/admin/src/components/BoundRoute/index.js b/packages/strapi/src/extensions/users-permissions/admin/src/components/BoundRoute/index.js deleted file mode 100644 index 7680ff0..0000000 --- a/packages/strapi/src/extensions/users-permissions/admin/src/components/BoundRoute/index.js +++ /dev/null @@ -1,72 +0,0 @@ -import React from 'react'; - -import { Box, Flex, Typography } from '@strapi/design-system'; -import map from 'lodash/map'; -import tail from 'lodash/tail'; -import PropTypes from 'prop-types'; -import { useIntl } from 'react-intl'; -import styled from 'styled-components'; - -import getMethodColor from './getMethodColor'; - -const MethodBox = styled(Box)` - margin: -1px; - border-radius: ${({ theme }) => theme.spaces[1]} 0 0 ${({ theme }) => theme.spaces[1]}; -`; - -function BoundRoute({ route }) { - const { formatMessage } = useIntl(); - - const { method, handler: title, path } = route; - const formattedRoute = path ? tail(path.split('/')) : []; - const [controller = '', action = ''] = title ? title.split('.') : []; - const colors = getMethodColor(route.method); - - return ( - - - {formatMessage({ - id: 'users-permissions.BoundRoute.title', - defaultMessage: 'Bound route to', - })} -   - {controller} - - .{action} - - - - - - {method} - - - - {map(formattedRoute, (value) => ( - - /{value} - - ))} - - - - ); -} - -BoundRoute.defaultProps = { - route: { - handler: 'Nocontroller.error', - method: 'GET', - path: '/there-is-no-path', - }, -}; - -BoundRoute.propTypes = { - route: PropTypes.shape({ - handler: PropTypes.string, - method: PropTypes.string, - path: PropTypes.string, - }), -}; - -export default BoundRoute; diff --git a/packages/strapi/src/extensions/users-permissions/admin/src/components/FormModal/Input/index.js b/packages/strapi/src/extensions/users-permissions/admin/src/components/FormModal/Input/index.js deleted file mode 100644 index e5eaf94..0000000 --- a/packages/strapi/src/extensions/users-permissions/admin/src/components/FormModal/Input/index.js +++ /dev/null @@ -1,123 +0,0 @@ -/** - * - * Input - * - */ - -import React from 'react'; - -import { TextInput, ToggleInput } from '@strapi/design-system'; -import PropTypes from 'prop-types'; -import { useIntl } from 'react-intl'; - -const Input = ({ - description, - disabled, - intlLabel, - error, - name, - onChange, - placeholder, - providerToEditName, - type, - value, -}) => { - const { formatMessage } = useIntl(); - const inputValue = - name === 'noName' - ? `${window.strapi.backendURL}/api/connect/${providerToEditName}/callback` - : value; - - const label = formatMessage( - { id: intlLabel.id, defaultMessage: intlLabel.defaultMessage }, - { provider: providerToEditName, ...intlLabel.values } - ); - const hint = description - ? formatMessage( - { id: description.id, defaultMessage: description.defaultMessage }, - { provider: providerToEditName, ...description.values } - ) - : ''; - - if (type === 'bool') { - return ( - { - onChange({ target: { name, value: e.target.checked } }); - }} - /> - ); - } - - const formattedPlaceholder = placeholder - ? formatMessage( - { id: placeholder.id, defaultMessage: placeholder.defaultMessage }, - { ...placeholder.values } - ) - : ''; - - const errorMessage = error ? formatMessage({ id: error, defaultMessage: error }) : ''; - - return ( - - ); -}; - -Input.defaultProps = { - description: null, - disabled: false, - error: '', - placeholder: null, - value: '', -}; - -Input.propTypes = { - description: PropTypes.shape({ - id: PropTypes.string.isRequired, - defaultMessage: PropTypes.string.isRequired, - values: PropTypes.object, - }), - disabled: PropTypes.bool, - error: PropTypes.string, - intlLabel: PropTypes.shape({ - id: PropTypes.string.isRequired, - defaultMessage: PropTypes.string.isRequired, - values: PropTypes.object, - }).isRequired, - name: PropTypes.string.isRequired, - onChange: PropTypes.func.isRequired, - placeholder: PropTypes.shape({ - id: PropTypes.string.isRequired, - defaultMessage: PropTypes.string.isRequired, - values: PropTypes.object, - }), - providerToEditName: PropTypes.string.isRequired, - type: PropTypes.string.isRequired, - value: PropTypes.oneOfType([PropTypes.bool, PropTypes.string]), -}; - -export default Input; diff --git a/packages/strapi/src/extensions/users-permissions/admin/src/components/FormModal/index.js b/packages/strapi/src/extensions/users-permissions/admin/src/components/FormModal/index.js deleted file mode 100644 index 83c0592..0000000 --- a/packages/strapi/src/extensions/users-permissions/admin/src/components/FormModal/index.js +++ /dev/null @@ -1,126 +0,0 @@ -/** - * - * FormModal - * - */ - -import React from 'react'; - -import { - Button, - Flex, - Grid, - GridItem, - ModalBody, - ModalFooter, - ModalHeader, - ModalLayout, -} from '@strapi/design-system'; -import { Breadcrumbs, Crumb } from '@strapi/design-system/v2'; -import { Form } from '@strapi/helper-plugin'; -import { Formik } from 'formik'; -import PropTypes from 'prop-types'; -import { useIntl } from 'react-intl'; - -import Input from './Input'; - -const FormModal = ({ - headerBreadcrumbs, - initialData, - isSubmiting, - layout, - isOpen, - onSubmit, - onToggle, - providerToEditName, -}) => { - const { formatMessage } = useIntl(); - - if (!isOpen) { - return null; - } - - return ( - - - - {headerBreadcrumbs.map((crumb, index, arr) => ( - - {crumb} - - ))} - - - onSubmit(values)} - initialValues={initialData} - validationSchema={layout.schema} - validateOnChange={false} - > - {({ errors, handleChange, values }) => { - return ( -
- - - - {layout.form.map((row) => { - return row.map((input) => { - return ( - - - - ); - }); - })} - - - - - {formatMessage({ - id: 'app.components.Button.cancel', - defaultMessage: 'Cancel', - })} - - } - endActions={ - - } - /> - - ); - }} -
-
- ); -}; - -FormModal.defaultProps = { - initialData: null, - providerToEditName: null, -}; - -FormModal.propTypes = { - headerBreadcrumbs: PropTypes.arrayOf(PropTypes.string).isRequired, - initialData: PropTypes.object, - layout: PropTypes.shape({ - form: PropTypes.arrayOf(PropTypes.array), - schema: PropTypes.object, - }).isRequired, - isOpen: PropTypes.bool.isRequired, - isSubmiting: PropTypes.bool.isRequired, - onSubmit: PropTypes.func.isRequired, - onToggle: PropTypes.func.isRequired, - providerToEditName: PropTypes.string, -}; - -export default FormModal; diff --git a/packages/strapi/src/extensions/users-permissions/admin/src/components/Permissions/PermissionRow/CheckboxWrapper.js b/packages/strapi/src/extensions/users-permissions/admin/src/components/Permissions/PermissionRow/CheckboxWrapper.js deleted file mode 100644 index e3165e2..0000000 --- a/packages/strapi/src/extensions/users-permissions/admin/src/components/Permissions/PermissionRow/CheckboxWrapper.js +++ /dev/null @@ -1,30 +0,0 @@ -import { Box } from '@strapi/design-system'; -import styled, { css } from 'styled-components'; - -const activeCheckboxWrapperStyles = css` - background: ${(props) => props.theme.colors.primary100}; - svg { - opacity: 1; - } -`; - -const CheckboxWrapper = styled(Box)` - display: flex; - justify-content: space-between; - align-items: center; - - svg { - opacity: 0; - path { - fill: ${(props) => props.theme.colors.primary600}; - } - } - - /* Show active style both on hover and when the action is selected */ - ${(props) => props.isActive && activeCheckboxWrapperStyles} - &:hover { - ${activeCheckboxWrapperStyles} - } -`; - -export default CheckboxWrapper; diff --git a/packages/strapi/src/extensions/users-permissions/admin/src/components/Permissions/PermissionRow/SubCategory.js b/packages/strapi/src/extensions/users-permissions/admin/src/components/Permissions/PermissionRow/SubCategory.js deleted file mode 100644 index a9a91bd..0000000 --- a/packages/strapi/src/extensions/users-permissions/admin/src/components/Permissions/PermissionRow/SubCategory.js +++ /dev/null @@ -1,131 +0,0 @@ -import React, { useCallback, useMemo } from 'react'; - -import { - Box, - Checkbox, - Flex, - Typography, - Grid, - GridItem, - VisuallyHidden, -} from '@strapi/design-system'; -import { Cog as CogIcon } from '@strapi/icons'; -import get from 'lodash/get'; -import PropTypes from 'prop-types'; -import { useIntl } from 'react-intl'; -import styled from 'styled-components'; - -import { useUsersPermissions } from '../../../contexts/UsersPermissionsContext'; - -import CheckboxWrapper from './CheckboxWrapper'; - -const Border = styled.div` - flex: 1; - align-self: center; - border-top: 1px solid ${({ theme }) => theme.colors.neutral150}; -`; - -const SubCategory = ({ subCategory }) => { - const { formatMessage } = useIntl(); - const { onChange, onChangeSelectAll, onSelectedAction, selectedAction, modifiedData } = - useUsersPermissions(); - - const currentScopedModifiedData = useMemo(() => { - return get(modifiedData, subCategory.name, {}); - }, [modifiedData, subCategory]); - - const hasAllActionsSelected = useMemo(() => { - return Object.values(currentScopedModifiedData).every((action) => action.enabled === true); - }, [currentScopedModifiedData]); - - const hasSomeActionsSelected = useMemo(() => { - return ( - Object.values(currentScopedModifiedData).some((action) => action.enabled === true) && - !hasAllActionsSelected - ); - }, [currentScopedModifiedData, hasAllActionsSelected]); - - const handleChangeSelectAll = useCallback( - ({ target: { name } }) => { - onChangeSelectAll({ target: { name, value: !hasAllActionsSelected } }); - }, - [hasAllActionsSelected, onChangeSelectAll] - ); - - const isActionSelected = useCallback( - (actionName) => { - return selectedAction === actionName; - }, - [selectedAction] - ); - - return ( - - - - - {subCategory.label} - - - - - - handleChangeSelectAll({ target: { name: subCategory.name, value } }) - } - indeterminate={hasSomeActionsSelected} - > - {formatMessage({ id: 'app.utils.select-all', defaultMessage: 'Select all' })} - - - - - - {subCategory.actions.map((action) => { - const name = `${action.name}.enabled`; - - return ( - - - onChange({ target: { name, value } })} - > - {action.label} - - - - - ); - })} - - - - ); -}; - -SubCategory.propTypes = { - subCategory: PropTypes.object.isRequired, -}; - -export default SubCategory; diff --git a/packages/strapi/src/extensions/users-permissions/admin/src/components/Permissions/PermissionRow/index.js b/packages/strapi/src/extensions/users-permissions/admin/src/components/Permissions/PermissionRow/index.js deleted file mode 100644 index 08ff3ff..0000000 --- a/packages/strapi/src/extensions/users-permissions/admin/src/components/Permissions/PermissionRow/index.js +++ /dev/null @@ -1,55 +0,0 @@ -import React, { useMemo } from 'react'; - -import { Box } from '@strapi/design-system'; -import sortBy from 'lodash/sortBy'; -import PropTypes from 'prop-types'; - -import SubCategory from './SubCategory'; - -const PermissionRow = ({ name, permissions }) => { - const subCategories = useMemo(() => { - return sortBy( - Object.values(permissions.controllers).reduce((acc, curr, index) => { - const currentName = `${name}.controllers.${Object.keys(permissions.controllers)[index]}`; - const actions = sortBy( - Object.keys(curr).reduce((acc, current) => { - return [ - ...acc, - { - ...curr[current], - label: current, - name: `${currentName}.${current}`, - }, - ]; - }, []), - 'label' - ); - - return [ - ...acc, - { - actions, - label: Object.keys(permissions.controllers)[index], - name: currentName, - }, - ]; - }, []), - 'label' - ); - }, [name, permissions]); - - return ( - - {subCategories.map((subCategory) => ( - - ))} - - ); -}; - -PermissionRow.propTypes = { - name: PropTypes.string.isRequired, - permissions: PropTypes.object.isRequired, -}; - -export default PermissionRow; diff --git a/packages/strapi/src/extensions/users-permissions/admin/src/components/Permissions/index.js b/packages/strapi/src/extensions/users-permissions/admin/src/components/Permissions/index.js deleted file mode 100644 index 260ae00..0000000 --- a/packages/strapi/src/extensions/users-permissions/admin/src/components/Permissions/index.js +++ /dev/null @@ -1,57 +0,0 @@ -import React, { useReducer } from 'react'; - -import { Accordion, AccordionContent, AccordionToggle, Box, Flex } from '@strapi/design-system'; -import { useIntl } from 'react-intl'; - -import { useUsersPermissions } from '../../contexts/UsersPermissionsContext'; -import formatPluginName from '../../utils/formatPluginName'; - -import init from './init'; -import PermissionRow from './PermissionRow'; -import { initialState, reducer } from './reducer'; - -const Permissions = () => { - const { modifiedData } = useUsersPermissions(); - const { formatMessage } = useIntl(); - const [{ collapses }, dispatch] = useReducer(reducer, initialState, (state) => - init(state, modifiedData) - ); - - const handleToggle = (index) => - dispatch({ - type: 'TOGGLE_COLLAPSE', - index, - }); - - return ( - - {collapses.map((collapse, index) => ( - handleToggle(index)} - key={collapse.name} - variant={index % 2 === 0 ? 'secondary' : undefined} - > - - - - - - - - ))} - - ); -}; - -export default Permissions; diff --git a/packages/strapi/src/extensions/users-permissions/admin/src/components/Permissions/init.js b/packages/strapi/src/extensions/users-permissions/admin/src/components/Permissions/init.js deleted file mode 100644 index 4125920..0000000 --- a/packages/strapi/src/extensions/users-permissions/admin/src/components/Permissions/init.js +++ /dev/null @@ -1,9 +0,0 @@ -const init = (initialState, permissions) => { - const collapses = Object.keys(permissions) - .sort() - .map((name) => ({ name, isOpen: false })); - - return { ...initialState, collapses }; -}; - -export default init; diff --git a/packages/strapi/src/extensions/users-permissions/admin/src/components/Permissions/reducer.js b/packages/strapi/src/extensions/users-permissions/admin/src/components/Permissions/reducer.js deleted file mode 100644 index 705e580..0000000 --- a/packages/strapi/src/extensions/users-permissions/admin/src/components/Permissions/reducer.js +++ /dev/null @@ -1,27 +0,0 @@ -import produce from 'immer'; - -const initialState = { - collapses: [], -}; - -const reducer = (state, action) => - // eslint-disable-next-line consistent-return - produce(state, (draftState) => { - switch (action.type) { - case 'TOGGLE_COLLAPSE': { - draftState.collapses = state.collapses.map((collapse, index) => { - if (index === action.index) { - return { ...collapse, isOpen: !collapse.isOpen }; - } - - return { ...collapse, isOpen: false }; - }); - - break; - } - default: - return draftState; - } - }); - -export { initialState, reducer }; diff --git a/packages/strapi/src/extensions/users-permissions/admin/src/components/Policies/index.js b/packages/strapi/src/extensions/users-permissions/admin/src/components/Policies/index.js deleted file mode 100644 index e9c53b3..0000000 --- a/packages/strapi/src/extensions/users-permissions/admin/src/components/Policies/index.js +++ /dev/null @@ -1,62 +0,0 @@ -import React from 'react'; - -import { Flex, GridItem, Typography } from '@strapi/design-system'; -import get from 'lodash/get'; -import isEmpty from 'lodash/isEmpty'; -import without from 'lodash/without'; -import { useIntl } from 'react-intl'; - -import { useUsersPermissions } from '../../contexts/UsersPermissionsContext'; -import BoundRoute from '../BoundRoute'; - -const Policies = () => { - const { formatMessage } = useIntl(); - const { selectedAction, routes } = useUsersPermissions(); - - const path = without(selectedAction.split('.'), 'controllers'); - const controllerRoutes = get(routes, path[0]); - const pathResolved = path.slice(1).join('.'); - - const displayedRoutes = isEmpty(controllerRoutes) - ? [] - : controllerRoutes.filter((o) => o.handler.endsWith(pathResolved)); - - return ( - - {selectedAction ? ( - - {displayedRoutes.map((route, key) => ( - // eslint-disable-next-line react/no-array-index-key - - ))} - - ) : ( - - - {formatMessage({ - id: 'users-permissions.Policies.header.title', - defaultMessage: 'Advanced settings', - })} - - - {formatMessage({ - id: 'users-permissions.Policies.header.hint', - defaultMessage: - "Select the application's actions or the plugin's actions and click on the cog icon to display the bound route", - })} - - - )} - - ); -}; - -export default Policies; diff --git a/packages/strapi/src/extensions/users-permissions/admin/src/components/UsersPermissions/index.js b/packages/strapi/src/extensions/users-permissions/admin/src/components/UsersPermissions/index.js deleted file mode 100644 index 6f40fa3..0000000 --- a/packages/strapi/src/extensions/users-permissions/admin/src/components/UsersPermissions/index.js +++ /dev/null @@ -1,95 +0,0 @@ -import React, { forwardRef, memo, useImperativeHandle, useReducer } from 'react'; - -import { Flex, Grid, GridItem, Typography } from '@strapi/design-system'; -import PropTypes from 'prop-types'; -import { useIntl } from 'react-intl'; - -import { UsersPermissionsProvider } from '../../contexts/UsersPermissionsContext'; -import getTrad from '../../utils/getTrad'; -import Permissions from '../Permissions'; -import Policies from '../Policies'; - -import init from './init'; -import reducer, { initialState } from './reducer'; - -const UsersPermissions = forwardRef(({ permissions, routes }, ref) => { - const { formatMessage } = useIntl(); - const [state, dispatch] = useReducer(reducer, initialState, (state) => - init(state, permissions, routes) - ); - - useImperativeHandle(ref, () => ({ - getPermissions() { - return { - permissions: state.modifiedData, - }; - }, - resetForm() { - dispatch({ type: 'ON_RESET' }); - }, - setFormAfterSubmit() { - dispatch({ type: 'ON_SUBMIT_SUCCEEDED' }); - }, - })); - - const handleChange = ({ target: { name, value } }) => - dispatch({ - type: 'ON_CHANGE', - keys: name.split('.'), - value: value === 'empty__string_value' ? '' : value, - }); - - const handleChangeSelectAll = ({ target: { name, value } }) => - dispatch({ - type: 'ON_CHANGE_SELECT_ALL', - keys: name.split('.'), - value, - }); - - const handleSelectedAction = (actionToSelect) => - dispatch({ - type: 'SELECT_ACTION', - actionToSelect, - }); - - const providerValue = { - ...state, - onChange: handleChange, - onChangeSelectAll: handleChangeSelectAll, - onSelectedAction: handleSelectedAction, - }; - - return ( - - - - - - - {formatMessage({ - id: getTrad('Plugins.header.title'), - defaultMessage: 'Permissions', - })} - - - {formatMessage({ - id: getTrad('Plugins.header.description'), - defaultMessage: 'Only actions bound by a route are listed below.', - })} - - - - - - - - - ); -}); - -UsersPermissions.propTypes = { - permissions: PropTypes.object.isRequired, - routes: PropTypes.object.isRequired, -}; - -export default memo(UsersPermissions); diff --git a/packages/strapi/src/extensions/users-permissions/admin/src/components/UsersPermissions/init.js b/packages/strapi/src/extensions/users-permissions/admin/src/components/UsersPermissions/init.js deleted file mode 100644 index e124042..0000000 --- a/packages/strapi/src/extensions/users-permissions/admin/src/components/UsersPermissions/init.js +++ /dev/null @@ -1,10 +0,0 @@ -const init = (state, permissions, routes) => { - return { - ...state, - initialData: permissions, - modifiedData: permissions, - routes, - }; -}; - -export default init; diff --git a/packages/strapi/src/extensions/users-permissions/admin/src/components/UsersPermissions/reducer.js b/packages/strapi/src/extensions/users-permissions/admin/src/components/UsersPermissions/reducer.js deleted file mode 100644 index 8a03a18..0000000 --- a/packages/strapi/src/extensions/users-permissions/admin/src/components/UsersPermissions/reducer.js +++ /dev/null @@ -1,62 +0,0 @@ -/* eslint-disable consistent-return */ -import produce from 'immer'; -import get from 'lodash/get'; -import set from 'lodash/set'; -import take from 'lodash/take'; - -export const initialState = { - initialData: {}, - modifiedData: {}, - routes: {}, - selectedAction: '', - policies: [], -}; - -const reducer = (state, action) => - produce(state, (draftState) => { - switch (action.type) { - case 'ON_CHANGE': { - const keysLength = action.keys.length; - const isChangingCheckbox = action.keys[keysLength - 1] === 'enabled'; - - if (action.value && isChangingCheckbox) { - const selectedAction = take(action.keys, keysLength - 1).join('.'); - draftState.selectedAction = selectedAction; - } - - set(draftState, ['modifiedData', ...action.keys], action.value); - break; - } - case 'ON_CHANGE_SELECT_ALL': { - const pathToValue = ['modifiedData', ...action.keys]; - const oldValues = get(state, pathToValue, {}); - const updatedValues = Object.keys(oldValues).reduce((acc, current) => { - acc[current] = { ...oldValues[current], enabled: action.value }; - - return acc; - }, {}); - - set(draftState, pathToValue, updatedValues); - - break; - } - case 'ON_RESET': { - draftState.modifiedData = state.initialData; - break; - } - case 'ON_SUBMIT_SUCCEEDED': { - draftState.initialData = state.modifiedData; - break; - } - - case 'SELECT_ACTION': { - const { actionToSelect } = action; - draftState.selectedAction = actionToSelect === state.selectedAction ? '' : actionToSelect; - break; - } - default: - return draftState; - } - }); - -export default reducer; diff --git a/packages/strapi/src/extensions/users-permissions/admin/src/contexts/UsersPermissionsContext/index.js b/packages/strapi/src/extensions/users-permissions/admin/src/contexts/UsersPermissionsContext/index.js deleted file mode 100644 index ce66c34..0000000 --- a/packages/strapi/src/extensions/users-permissions/admin/src/contexts/UsersPermissionsContext/index.js +++ /dev/null @@ -1,18 +0,0 @@ -import React, { createContext, useContext } from 'react'; - -import PropTypes from 'prop-types'; - -const UsersPermissions = createContext({}); - -const UsersPermissionsProvider = ({ children, value }) => { - return {children}; -}; - -const useUsersPermissions = () => useContext(UsersPermissions); - -UsersPermissionsProvider.propTypes = { - children: PropTypes.node.isRequired, - value: PropTypes.object.isRequired, -}; - -export { UsersPermissions, UsersPermissionsProvider, useUsersPermissions }; diff --git a/packages/strapi/src/extensions/users-permissions/admin/src/hooks/index.js b/packages/strapi/src/extensions/users-permissions/admin/src/hooks/index.js deleted file mode 100644 index 9988733..0000000 --- a/packages/strapi/src/extensions/users-permissions/admin/src/hooks/index.js +++ /dev/null @@ -1,5 +0,0 @@ -// eslint-disable-next-line import/prefer-default-export -export { default as useForm } from './useForm'; -export { default as useRolesList } from './useRolesList'; -export * from './usePlugins'; -export { default as useFetchRole } from './useFetchRole'; diff --git a/packages/strapi/src/extensions/users-permissions/admin/src/hooks/useFetchRole/index.js b/packages/strapi/src/extensions/users-permissions/admin/src/hooks/useFetchRole/index.js deleted file mode 100644 index 629e001..0000000 --- a/packages/strapi/src/extensions/users-permissions/admin/src/hooks/useFetchRole/index.js +++ /dev/null @@ -1,67 +0,0 @@ -import { useCallback, useEffect, useReducer, useRef } from 'react'; - -import { useFetchClient, useNotification } from '@strapi/helper-plugin'; - -import pluginId from '../../pluginId'; - -import reducer, { initialState } from './reducer'; - -const useFetchRole = (id) => { - const [state, dispatch] = useReducer(reducer, initialState); - const toggleNotification = useNotification(); - const isMounted = useRef(null); - const { get } = useFetchClient(); - - useEffect(() => { - isMounted.current = true; - - if (id) { - fetchRole(id); - } else { - dispatch({ - type: 'GET_DATA_SUCCEEDED', - role: {}, - }); - } - - return () => (isMounted.current = false); - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [id]); - - const fetchRole = async (roleId) => { - try { - const { - data: { role }, - } = await get(`/${pluginId}/roles/${roleId}`); - - // Prevent updating state on an unmounted component - if (isMounted.current) { - dispatch({ - type: 'GET_DATA_SUCCEEDED', - role, - }); - } - } catch (err) { - console.error(err); - - dispatch({ - type: 'GET_DATA_ERROR', - }); - toggleNotification({ - type: 'warning', - message: { id: 'notification.error' }, - }); - } - }; - - const handleSubmitSucceeded = useCallback((data) => { - dispatch({ - type: 'ON_SUBMIT_SUCCEEDED', - ...data, - }); - }, []); - - return { ...state, onSubmitSucceeded: handleSubmitSucceeded }; -}; - -export default useFetchRole; diff --git a/packages/strapi/src/extensions/users-permissions/admin/src/hooks/useFetchRole/reducer.js b/packages/strapi/src/extensions/users-permissions/admin/src/hooks/useFetchRole/reducer.js deleted file mode 100644 index 99dcf0d..0000000 --- a/packages/strapi/src/extensions/users-permissions/admin/src/hooks/useFetchRole/reducer.js +++ /dev/null @@ -1,31 +0,0 @@ -/* eslint-disable consistent-return */ -import produce from 'immer'; - -export const initialState = { - role: {}, - isLoading: true, -}; - -const reducer = (state, action) => - produce(state, (draftState) => { - switch (action.type) { - case 'GET_DATA_SUCCEEDED': { - draftState.role = action.role; - draftState.isLoading = false; - break; - } - case 'GET_DATA_ERROR': { - draftState.isLoading = false; - break; - } - case 'ON_SUBMIT_SUCCEEDED': { - draftState.role.name = action.name; - draftState.role.description = action.description; - break; - } - default: - return draftState; - } - }); - -export default reducer; diff --git a/packages/strapi/src/extensions/users-permissions/admin/src/hooks/useForm/index.js b/packages/strapi/src/extensions/users-permissions/admin/src/hooks/useForm/index.js deleted file mode 100644 index 0cf0ef6..0000000 --- a/packages/strapi/src/extensions/users-permissions/admin/src/hooks/useForm/index.js +++ /dev/null @@ -1,70 +0,0 @@ -import { useCallback, useEffect, useReducer, useRef } from 'react'; - -import { useFetchClient, useNotification, useRBAC } from '@strapi/helper-plugin'; - -import { getRequestURL } from '../../utils'; - -import reducer, { initialState } from './reducer'; - -const useUserForm = (endPoint, permissions) => { - const { isLoading: isLoadingForPermissions, allowedActions } = useRBAC(permissions); - const [{ isLoading, modifiedData }, dispatch] = useReducer(reducer, initialState); - const toggleNotification = useNotification(); - const isMounted = useRef(true); - - const { get } = useFetchClient(); - - useEffect(() => { - const getData = async () => { - try { - dispatch({ - type: 'GET_DATA', - }); - - const { data } = await get(getRequestURL(endPoint)); - - dispatch({ - type: 'GET_DATA_SUCCEEDED', - data, - }); - } catch (err) { - // The user aborted the request - if (isMounted.current) { - dispatch({ - type: 'GET_DATA_ERROR', - }); - console.error(err); - toggleNotification({ - type: 'warning', - message: { id: 'notification.error' }, - }); - } - } - }; - - if (!isLoadingForPermissions) { - getData(); - } - - return () => { - isMounted.current = false; - }; - }, [isLoadingForPermissions, endPoint, get, toggleNotification]); - - const dispatchSubmitSucceeded = useCallback((data) => { - dispatch({ - type: 'ON_SUBMIT_SUCCEEDED', - data, - }); - }, []); - - return { - allowedActions, - dispatchSubmitSucceeded, - isLoading, - isLoadingForPermissions, - modifiedData, - }; -}; - -export default useUserForm; diff --git a/packages/strapi/src/extensions/users-permissions/admin/src/hooks/useForm/reducer.js b/packages/strapi/src/extensions/users-permissions/admin/src/hooks/useForm/reducer.js deleted file mode 100644 index 1d05786..0000000 --- a/packages/strapi/src/extensions/users-permissions/admin/src/hooks/useForm/reducer.js +++ /dev/null @@ -1,40 +0,0 @@ -import produce from 'immer'; - -const initialState = { - isLoading: true, - modifiedData: {}, -}; - -const reducer = (state, action) => - // eslint-disable-next-line consistent-return - produce(state, (draftState) => { - switch (action.type) { - case 'GET_DATA': { - draftState.isLoading = true; - draftState.modifiedData = {}; - - break; - } - case 'GET_DATA_SUCCEEDED': { - draftState.isLoading = false; - draftState.modifiedData = action.data; - - break; - } - case 'GET_DATA_ERROR': { - draftState.isLoading = true; - break; - } - case 'ON_SUBMIT_SUCCEEDED': { - draftState.modifiedData = action.data; - - break; - } - default: { - return draftState; - } - } - }); - -export default reducer; -export { initialState }; diff --git a/packages/strapi/src/extensions/users-permissions/admin/src/hooks/usePlugins.js b/packages/strapi/src/extensions/users-permissions/admin/src/hooks/usePlugins.js deleted file mode 100644 index ce1f0e8..0000000 --- a/packages/strapi/src/extensions/users-permissions/admin/src/hooks/usePlugins.js +++ /dev/null @@ -1,71 +0,0 @@ -import { useEffect } from 'react'; - -import { useNotification, useFetchClient, useAPIErrorHandler } from '@strapi/helper-plugin'; -import { useQueries } from 'react-query'; - -import pluginId from '../pluginId'; -import { cleanPermissions, getTrad } from '../utils'; - -export const usePlugins = () => { - const toggleNotification = useNotification(); - const { get } = useFetchClient(); - const { formatAPIError } = useAPIErrorHandler(getTrad); - - const [ - { - data: permissions, - isLoading: isLoadingPermissions, - error: permissionsError, - refetch: refetchPermissions, - }, - { data: routes, isLoading: isLoadingRoutes, error: routesError, refetch: refetchRoutes }, - ] = useQueries([ - { - queryKey: [pluginId, 'permissions'], - async queryFn() { - const res = await get(`/${pluginId}/permissions`); - - return res.data.permissions; - }, - }, - { - queryKey: [pluginId, 'routes'], - async queryFn() { - const res = await get(`/${pluginId}/routes`); - - return res.data.routes; - }, - }, - ]); - - const refetchQueries = async () => { - await Promise.all([refetchPermissions(), refetchRoutes()]); - }; - - useEffect(() => { - if (permissionsError) { - toggleNotification({ - type: 'warning', - message: formatAPIError(permissionsError), - }); - } - }, [toggleNotification, permissionsError, formatAPIError]); - - useEffect(() => { - if (routesError) { - toggleNotification({ - type: 'warning', - message: formatAPIError(routesError), - }); - } - }, [toggleNotification, routesError, formatAPIError]); - - const isLoading = isLoadingPermissions || isLoadingRoutes; - - return { - permissions: permissions ? cleanPermissions(permissions) : {}, - routes: routes ?? {}, - getData: refetchQueries, - isLoading, - }; -}; diff --git a/packages/strapi/src/extensions/users-permissions/admin/src/hooks/useRolesList/index.js b/packages/strapi/src/extensions/users-permissions/admin/src/hooks/useRolesList/index.js deleted file mode 100644 index aae9175..0000000 --- a/packages/strapi/src/extensions/users-permissions/admin/src/hooks/useRolesList/index.js +++ /dev/null @@ -1,65 +0,0 @@ -import { useCallback, useEffect, useReducer, useRef } from 'react'; - -import { useFetchClient, useNotification } from '@strapi/helper-plugin'; -import get from 'lodash/get'; - -import pluginId from '../../pluginId'; - -import init from './init'; -import reducer, { initialState } from './reducer'; - -const useRolesList = (shouldFetchData = true) => { - const [{ roles, isLoading }, dispatch] = useReducer(reducer, initialState, () => - init(initialState, shouldFetchData) - ); - const toggleNotification = useNotification(); - - const isMounted = useRef(true); - const fetchClient = useFetchClient(); - - const fetchRolesList = useCallback(async () => { - try { - dispatch({ - type: 'GET_DATA', - }); - - const { - data: { roles }, - } = await fetchClient.get(`/${pluginId}/roles`); - - dispatch({ - type: 'GET_DATA_SUCCEEDED', - data: roles, - }); - } catch (err) { - const message = get(err, ['response', 'payload', 'message'], 'An error occured'); - - if (isMounted.current) { - dispatch({ - type: 'GET_DATA_ERROR', - }); - - if (message !== 'Forbidden') { - toggleNotification({ - type: 'warning', - message, - }); - } - } - } - }, [fetchClient, toggleNotification]); - - useEffect(() => { - if (shouldFetchData) { - fetchRolesList(); - } - - return () => { - isMounted.current = false; - }; - }, [shouldFetchData, fetchRolesList]); - - return { roles, isLoading, getData: fetchRolesList }; -}; - -export default useRolesList; diff --git a/packages/strapi/src/extensions/users-permissions/admin/src/hooks/useRolesList/init.js b/packages/strapi/src/extensions/users-permissions/admin/src/hooks/useRolesList/init.js deleted file mode 100644 index dfe71d9..0000000 --- a/packages/strapi/src/extensions/users-permissions/admin/src/hooks/useRolesList/init.js +++ /dev/null @@ -1,5 +0,0 @@ -const init = (initialState, shouldFetchData) => { - return { ...initialState, isLoading: shouldFetchData }; -}; - -export default init; diff --git a/packages/strapi/src/extensions/users-permissions/admin/src/hooks/useRolesList/reducer.js b/packages/strapi/src/extensions/users-permissions/admin/src/hooks/useRolesList/reducer.js deleted file mode 100644 index a6d347b..0000000 --- a/packages/strapi/src/extensions/users-permissions/admin/src/hooks/useRolesList/reducer.js +++ /dev/null @@ -1,31 +0,0 @@ -/* eslint-disable consistent-return */ -import produce from 'immer'; - -export const initialState = { - roles: [], - isLoading: true, -}; - -const reducer = (state, action) => - produce(state, (draftState) => { - switch (action.type) { - case 'GET_DATA': { - draftState.isLoading = true; - draftState.roles = []; - break; - } - case 'GET_DATA_SUCCEEDED': { - draftState.roles = action.data; - draftState.isLoading = false; - break; - } - case 'GET_DATA_ERROR': { - draftState.isLoading = false; - break; - } - default: - return draftState; - } - }); - -export default reducer; diff --git a/packages/strapi/src/extensions/users-permissions/admin/src/index.js b/packages/strapi/src/extensions/users-permissions/admin/src/index.js deleted file mode 100644 index ba721ed..0000000 --- a/packages/strapi/src/extensions/users-permissions/admin/src/index.js +++ /dev/null @@ -1,125 +0,0 @@ -// NOTE TO PLUGINS DEVELOPERS: -// If you modify this file by adding new options to the plugin entry point -// Here's the file: strapi/docs/3.0.0-beta.x/plugin-development/frontend-field-api.md -// Here's the file: strapi/docs/3.0.0-beta.x/guides/registering-a-field-in-admin.md -// Also the strapi-generate-plugins/files/admin/src/index.js needs to be updated -// IF THE DOC IS NOT UPDATED THE PULL REQUEST WILL NOT BE MERGED -import { prefixPluginTranslations } from '@strapi/helper-plugin'; - -import pluginPkg from '../../package.json'; - -import pluginPermissions from './permissions'; -import pluginId from './pluginId'; -import getTrad from './utils/getTrad'; - -const name = pluginPkg.strapi.name; - -export default { - register(app) { - // Create the plugin's settings section - app.createSettingSection( - { - id: pluginId, - intlLabel: { - id: getTrad('Settings.section-label'), - defaultMessage: 'Users & Permissions plugin', - }, - }, - [ - { - intlLabel: { - id: 'global.roles', - defaultMessage: 'Roles', - }, - id: 'roles', - to: `/settings/${pluginId}/roles`, - async Component() { - const component = await import( - /* webpackChunkName: "users-roles-settings-page" */ './pages/Roles' - ); - - return component; - }, - permissions: pluginPermissions.accessRoles, - }, - { - intlLabel: { - id: getTrad('HeaderNav.link.providers'), - defaultMessage: 'Providers', - }, - id: 'providers', - to: `/settings/${pluginId}/providers`, - async Component() { - const component = await import( - /* webpackChunkName: "users-providers-settings-page" */ './pages/Providers' - ); - - return component; - }, - permissions: pluginPermissions.readProviders, - }, - { - intlLabel: { - id: getTrad('HeaderNav.link.emailTemplates'), - defaultMessage: 'Email templates', - }, - id: 'email-templates', - to: `/settings/${pluginId}/email-templates`, - async Component() { - const component = await import( - /* webpackChunkName: "users-email-settings-page" */ './pages/EmailTemplates' - ); - - return component; - }, - permissions: pluginPermissions.readEmailTemplates, - }, - { - intlLabel: { - id: getTrad('HeaderNav.link.advancedSettings'), - defaultMessage: 'Advanced Settings', - }, - id: 'advanced-settings', - to: `/settings/${pluginId}/advanced-settings`, - async Component() { - const component = await import( - /* webpackChunkName: "users-advanced-settings-page" */ './pages/AdvancedSettings' - ); - - return component; - }, - permissions: pluginPermissions.readAdvancedSettings, - }, - ] - ); - - app.registerPlugin({ - id: pluginId, - name, - }); - }, - bootstrap() {}, - async registerTrads({ locales }) { - const importedTrads = await Promise.all( - locales.map((locale) => { - return import( - /* webpackChunkName: "users-permissions-translation-[request]" */ `./translations/${locale}.json` - ) - .then(({ default: data }) => { - return { - data: prefixPluginTranslations(data, pluginId), - locale, - }; - }) - .catch(() => { - return { - data: {}, - locale, - }; - }); - }) - ); - - return Promise.resolve(importedTrads); - }, -}; diff --git a/packages/strapi/src/extensions/users-permissions/admin/src/pages/AdvancedSettings/index.js b/packages/strapi/src/extensions/users-permissions/admin/src/pages/AdvancedSettings/index.js deleted file mode 100644 index 3f0726f..0000000 --- a/packages/strapi/src/extensions/users-permissions/admin/src/pages/AdvancedSettings/index.js +++ /dev/null @@ -1,246 +0,0 @@ -import React, { useMemo } from 'react'; - -import { - Box, - Button, - ContentLayout, - Flex, - Grid, - GridItem, - HeaderLayout, - Main, - Option, - Select, - Typography, - useNotifyAT, -} from '@strapi/design-system'; -import { - CheckPagePermissions, - Form, - GenericInput, - LoadingIndicatorPage, - SettingsPageTitle, - useFocusWhenNavigate, - useNotification, - useOverlayBlocker, - useRBAC, -} from '@strapi/helper-plugin'; -import { Check } from '@strapi/icons'; -import { Formik } from 'formik'; -import { useIntl } from 'react-intl'; -import { useMutation, useQuery, useQueryClient } from 'react-query'; - -import pluginPermissions from '../../permissions'; -import { getTrad } from '../../utils'; - -import { fetchData, putAdvancedSettings } from './utils/api'; -import layout from './utils/layout'; -import schema from './utils/schema'; - -const ProtectedAdvancedSettingsPage = () => ( - - - -); - -const AdvancedSettingsPage = () => { - const { formatMessage } = useIntl(); - const toggleNotification = useNotification(); - const { lockApp, unlockApp } = useOverlayBlocker(); - const { notifyStatus } = useNotifyAT(); - const queryClient = useQueryClient(); - useFocusWhenNavigate(); - - const updatePermissions = useMemo( - () => ({ update: pluginPermissions.updateAdvancedSettings }), - [] - ); - const { - isLoading: isLoadingForPermissions, - allowedActions: { canUpdate }, - } = useRBAC(updatePermissions); - - const { status: isLoadingData, data } = useQuery('advanced', () => fetchData(), { - onSuccess() { - notifyStatus( - formatMessage({ - id: getTrad('Form.advancedSettings.data.loaded'), - defaultMessage: 'Advanced settings data has been loaded', - }) - ); - }, - onError() { - toggleNotification({ - type: 'warning', - message: { id: getTrad('notification.error'), defaultMessage: 'An error occured' }, - }); - }, - }); - - const isLoading = isLoadingForPermissions || isLoadingData !== 'success'; - - const submitMutation = useMutation((body) => putAdvancedSettings(body), { - async onSuccess() { - await queryClient.invalidateQueries('advanced'); - toggleNotification({ - type: 'success', - message: { id: getTrad('notification.success.saved'), defaultMessage: 'Saved' }, - }); - - unlockApp(); - }, - onError() { - toggleNotification({ - type: 'warning', - message: { id: getTrad('notification.error'), defaultMessage: 'An error occured' }, - }); - unlockApp(); - }, - refetchActive: true, - }); - - const { isLoading: isSubmittingForm } = submitMutation; - - const handleSubmit = async (body) => { - lockApp(); - - const urlConfirmation = body.email_confirmation ? body.email_confirmation_redirection : ''; - - await submitMutation.mutateAsync({ ...body, email_confirmation_redirection: urlConfirmation }); - }; - - if (isLoading) { - return ( -
- - - - - -
- ); - } - - return ( -
- - - {({ errors, values, handleChange, isSubmitting }) => { - return ( -
- } - size="S" - > - {formatMessage({ id: 'global.save', defaultMessage: 'Save' })} - - } - /> - - - - - {formatMessage({ - id: 'global.settings', - defaultMessage: 'Settings', - })} - - - - - - {layout.map((input) => { - let value = values[input.name]; - - if (!value) { - value = input.type === 'bool' ? false : ''; - } - - return ( - - - - ); - })} - - - - - - ); - }} -
-
- ); -}; - -export default ProtectedAdvancedSettingsPage; diff --git a/packages/strapi/src/extensions/users-permissions/admin/src/pages/AdvancedSettings/utils/api.js b/packages/strapi/src/extensions/users-permissions/admin/src/pages/AdvancedSettings/utils/api.js deleted file mode 100644 index 238862a..0000000 --- a/packages/strapi/src/extensions/users-permissions/admin/src/pages/AdvancedSettings/utils/api.js +++ /dev/null @@ -1,18 +0,0 @@ -import { getFetchClient } from '@strapi/helper-plugin'; - -import { getRequestURL } from '../../../utils'; - -const fetchData = async () => { - const { get } = getFetchClient(); - const { data } = await get(getRequestURL('advanced')); - - return data; -}; - -const putAdvancedSettings = (body) => { - const { put } = getFetchClient(); - - return put(getRequestURL('advanced'), body); -}; - -export { fetchData, putAdvancedSettings }; diff --git a/packages/strapi/src/extensions/users-permissions/admin/src/pages/AdvancedSettings/utils/layout.js b/packages/strapi/src/extensions/users-permissions/admin/src/pages/AdvancedSettings/utils/layout.js deleted file mode 100644 index 094e5a6..0000000 --- a/packages/strapi/src/extensions/users-permissions/admin/src/pages/AdvancedSettings/utils/layout.js +++ /dev/null @@ -1,96 +0,0 @@ -import { getTrad } from '../../../utils'; - -const layout = [ - { - intlLabel: { - id: getTrad('EditForm.inputToggle.label.email'), - defaultMessage: 'One account per email address', - }, - description: { - id: getTrad('EditForm.inputToggle.description.email'), - defaultMessage: - 'Disallow the user to create multiple accounts using the same email address with different authentication providers.', - }, - name: 'unique_email', - type: 'bool', - size: { - col: 12, - xs: 12, - }, - }, - { - intlLabel: { - id: getTrad('EditForm.inputToggle.label.sign-up'), - defaultMessage: 'Enable sign-ups', - }, - description: { - id: getTrad('EditForm.inputToggle.description.sign-up'), - defaultMessage: - 'When disabled (OFF), the registration process is forbidden. No one can subscribe anymore no matter the used provider.', - }, - name: 'allow_register', - type: 'bool', - size: { - col: 12, - xs: 12, - }, - }, - { - intlLabel: { - id: getTrad('EditForm.inputToggle.label.email-reset-password'), - defaultMessage: 'Reset password page', - }, - description: { - id: getTrad('EditForm.inputToggle.description.email-reset-password'), - defaultMessage: "URL of your application's reset password page.", - }, - placeholder: { - id: getTrad('EditForm.inputToggle.placeholder.email-reset-password'), - defaultMessage: 'ex: https://youtfrontend.com/reset-password', - }, - name: 'email_reset_password', - type: 'text', - size: { - col: 6, - xs: 12, - }, - }, - { - intlLabel: { - id: getTrad('EditForm.inputToggle.label.email-confirmation'), - defaultMessage: 'Enable email confirmation', - }, - description: { - id: getTrad('EditForm.inputToggle.description.email-confirmation'), - defaultMessage: 'When enabled (ON), new registered users receive a confirmation email.', - }, - name: 'email_confirmation', - type: 'bool', - size: { - col: 12, - xs: 12, - }, - }, - { - intlLabel: { - id: getTrad('EditForm.inputToggle.label.email-confirmation-redirection'), - defaultMessage: 'Redirection url', - }, - description: { - id: getTrad('EditForm.inputToggle.description.email-confirmation-redirection'), - defaultMessage: 'After you confirmed your email, choose where you will be redirected.', - }, - placeholder: { - id: getTrad('EditForm.inputToggle.placeholder.email-confirmation-redirection'), - defaultMessage: 'ex: https://youtfrontend.com/email-confirmation', - }, - name: 'email_confirmation_redirection', - type: 'text', - size: { - col: 6, - xs: 12, - }, - }, -]; - -export default layout; diff --git a/packages/strapi/src/extensions/users-permissions/admin/src/pages/AdvancedSettings/utils/schema.js b/packages/strapi/src/extensions/users-permissions/admin/src/pages/AdvancedSettings/utils/schema.js deleted file mode 100644 index b8958a8..0000000 --- a/packages/strapi/src/extensions/users-permissions/admin/src/pages/AdvancedSettings/utils/schema.js +++ /dev/null @@ -1,19 +0,0 @@ -import { translatedErrors } from '@strapi/helper-plugin'; -import * as yup from 'yup'; - -// eslint-disable-next-line prefer-regex-literals -const URL_REGEX = new RegExp('(^$)|((.+:\\/\\/.*)(d*)\\/?(.*))'); - -const schema = yup.object().shape({ - email_confirmation_redirection: yup.mixed().when('email_confirmation', { - is: true, - then: yup.string().matches(URL_REGEX).required(), - otherwise: yup.string().nullable(), - }), - email_reset_password: yup - .string(translatedErrors.string) - .matches(URL_REGEX, translatedErrors.regex) - .nullable(), -}); - -export default schema; diff --git a/packages/strapi/src/extensions/users-permissions/admin/src/pages/EmailTemplates/components/EmailForm.js b/packages/strapi/src/extensions/users-permissions/admin/src/pages/EmailTemplates/components/EmailForm.js deleted file mode 100644 index 5d98122..0000000 --- a/packages/strapi/src/extensions/users-permissions/admin/src/pages/EmailTemplates/components/EmailForm.js +++ /dev/null @@ -1,176 +0,0 @@ -import React from 'react'; - -import { - Button, - Grid, - GridItem, - ModalBody, - ModalFooter, - ModalHeader, - ModalLayout, - Textarea, -} from '@strapi/design-system'; -import { Breadcrumbs, Crumb } from '@strapi/design-system/v2'; -import { Form, GenericInput } from '@strapi/helper-plugin'; -import { Formik } from 'formik'; -import PropTypes from 'prop-types'; -import { useIntl } from 'react-intl'; - -import { getTrad } from '../../../utils'; -import schema from '../utils/schema'; - -const EmailForm = ({ template, onToggle, onSubmit }) => { - const { formatMessage } = useIntl(); - - return ( - - - - - {formatMessage({ - id: getTrad('PopUpForm.header.edit.email-templates'), - defaultMessage: 'Edit email template', - })} - - - {formatMessage({ id: getTrad(template.display), defaultMessage: template.display })} - - - - - {({ errors, values, handleChange, isSubmitting }) => { - return ( -
- - - - - - - - - - - - - - - -