From 49d2ecc4601f32f4f3b6840cd546b91704fe20a3 Mon Sep 17 00:00:00 2001 From: Maidul Islam Date: Wed, 3 May 2023 15:41:11 -0400 Subject: [PATCH 01/12] switch install command to run prod docker compose --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 1f7d85307..20885e728 100644 --- a/README.md +++ b/README.md @@ -78,16 +78,16 @@ To set up and run Infisical locally, make sure you have Git and Docker installed Linux/macOS: ```console -git clone https://github.com/Infisical/infisical && cd "$(basename $_ .git)" && cp .env.example .env && docker-compose -f docker-compose.dev.yml up --build +git clone https://github.com/Infisical/infisical && cd "$(basename $_ .git)" && cp .env.example .env && docker-compose -f docker-compose.yml up ``` Windows Command Prompt: ```console -git clone https://github.com/Infisical/infisical && cd infisical && copy .env.example .env && docker-compose -f docker-compose.dev.yml up --build +git clone https://github.com/Infisical/infisical && cd infisical && copy .env.example .env && docker-compose -f docker-compose.yml up ``` -Login to the web app at `http://localhost:8080` by entering the test user email `test@localhost.local` and password `testInfisical1`. +Login to the web app at `http://localhost:80` by entering the test user email `test@localhost.local` and password `testInfisical1`. ## Open-source vs. paid From fd4ea97e18f891fa78c38395fa238abb0af40989 Mon Sep 17 00:00:00 2001 From: Maidul Islam Date: Wed, 3 May 2023 15:45:16 -0400 Subject: [PATCH 02/12] remove default smtp since Infisical no longer requires SMTP --- .env.example | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.env.example b/.env.example index f317b2908..0aa34238c 100644 --- a/.env.example +++ b/.env.example @@ -30,11 +30,11 @@ MONGO_PASSWORD=example # Required SITE_URL=http://localhost:8080 -# Mail/SMTP - SMTP_HOST='smtp-server' -SMTP_PORT='1025' -SMTP_NAME='local' -SMTP_USERNAME='team@infisical.com' +# Mail/SMTP +SMTP_HOST= +SMTP_PORT= +SMTP_NAME= +SMTP_USERNAME= SMTP_PASSWORD= # Integration From c9b4e11539ac0f47f4221b4667e2c63c61698c64 Mon Sep 17 00:00:00 2001 From: Maidul Islam Date: Wed, 3 May 2023 15:48:20 -0400 Subject: [PATCH 03/12] add note to ENCRYPTION_KEY to indicate non prod --- .env.example | 1 + 1 file changed, 1 insertion(+) diff --git a/.env.example b/.env.example index 0aa34238c..fcd1231b8 100644 --- a/.env.example +++ b/.env.example @@ -1,5 +1,6 @@ # Keys # Required key for platform encryption/decryption ops +# THIS IS A SAMPLE ENCRYPTION KEY AND SHOULD NOT BE USED FOR PRODUCTION ENCRYPTION_KEY=6c1fe4e407b8911c104518103505b218 # JWT From 2d2bbbd0ad5915a8273ad6ae9397e1a4880f0c73 Mon Sep 17 00:00:00 2001 From: Maidul Islam Date: Wed, 3 May 2023 15:51:15 -0400 Subject: [PATCH 04/12] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 20885e728..ae863df21 100644 --- a/README.md +++ b/README.md @@ -87,7 +87,7 @@ Windows Command Prompt: git clone https://github.com/Infisical/infisical && cd infisical && copy .env.example .env && docker-compose -f docker-compose.yml up ``` -Login to the web app at `http://localhost:80` by entering the test user email `test@localhost.local` and password `testInfisical1`. +Create an account at `http://localhost:80` ## Open-source vs. paid From 0eceeb6aa907bbb261b45f8ab252f6cf4333becc Mon Sep 17 00:00:00 2001 From: Maidul Islam Date: Wed, 3 May 2023 16:57:09 -0400 Subject: [PATCH 05/12] create standalone infisical docker file --- Dockerfile.stand-alone-infisical | 102 ++++++++++++++++++++++++++ ecosystem.config.js | 32 ++++++++ nginx/default-stand-alone-docker.conf | 36 +++++++++ 3 files changed, 170 insertions(+) create mode 100644 Dockerfile.stand-alone-infisical create mode 100644 ecosystem.config.js create mode 100644 nginx/default-stand-alone-docker.conf diff --git a/Dockerfile.stand-alone-infisical b/Dockerfile.stand-alone-infisical new file mode 100644 index 000000000..49b74415e --- /dev/null +++ b/Dockerfile.stand-alone-infisical @@ -0,0 +1,102 @@ +ARG POSTHOG_HOST=https://app.posthog.com +ARG POSTHOG_API_KEY=posthog-api-key + +FROM node:16-alpine AS frontend-dependencies + +WORKDIR /app + +COPY frontend/package.json frontend/package-lock.json frontend/next.config.js ./ + +# Install dependencies +RUN npm ci --only-production --ignore-scripts + +# Rebuild the source code only when needed +FROM node:16-alpine AS frontend-builder +WORKDIR /app + +# Copy dependencies +COPY --from=frontend-dependencies /app/node_modules ./node_modules +# Copy all files +COPY /frontend . + +ENV NODE_ENV production +ENV NEXT_PUBLIC_ENV production +ARG POSTHOG_HOST +ENV NEXT_PUBLIC_POSTHOG_HOST $POSTHOG_HOST +ARG POSTHOG_API_KEY +ENV NEXT_PUBLIC_POSTHOG_API_KEY $POSTHOG_API_KEY + +# Build +RUN npm run build + +# Production image +FROM node:16-alpine AS frontend-runner +WORKDIR /app + +RUN addgroup --system --gid 1001 nodejs +RUN adduser --system --uid 1001 nextjs + +RUN mkdir -p /app/.next/cache/images && chown nextjs:nodejs /app/.next/cache/images +VOLUME /app/.next/cache/images + +ARG POSTHOG_API_KEY +ENV NEXT_PUBLIC_POSTHOG_API_KEY=$POSTHOG_API_KEY \ + BAKED_NEXT_PUBLIC_POSTHOG_API_KEY=$POSTHOG_API_KEY + +COPY --chown=nextjs:nodejs --chmod=555 frontend/scripts ./scripts +COPY --from=frontend-builder /app/public ./public +RUN chown nextjs:nodejs ./public/data +COPY --from=frontend-builder --chown=nextjs:nodejs /app/.next/standalone ./ +COPY --from=frontend-builder --chown=nextjs:nodejs /app/.next/static ./.next/static + +USER nextjs + +ENV NEXT_TELEMETRY_DISABLED 1 + +## +## BACKEND +## +FROM node:16-alpine AS backend-build + +WORKDIR /app + +COPY backend/package*.json ./ +RUN npm ci --only-production + +COPY /backend . +RUN npm run build + +# Production stage +FROM node:16-alpine AS backend-runner + +WORKDIR /app + +COPY backend/package*.json ./ +RUN npm ci --only-production + +COPY --from=backend-build /app . + +# Production stage +FROM node:14-alpine AS production + +WORKDIR / + +# Install PM2 +RUN npm install -g pm2 +# Copy ecosystem.config.js +COPY ecosystem.config.js . + +RUN apk add --no-cache nginx + +COPY nginx/default-stand-alone-docker.conf /etc/nginx/nginx.conf + +COPY --from=backend-runner /app /backend + +COPY --from=frontend-runner /app/ /app/ + +EXPOSE 80 +ENV HTTPS_ENABLED false + +CMD ["pm2-runtime", "start", "ecosystem.config.js"] + + diff --git a/ecosystem.config.js b/ecosystem.config.js new file mode 100644 index 000000000..5c8cc6832 --- /dev/null +++ b/ecosystem.config.js @@ -0,0 +1,32 @@ +module.exports = { + apps: [ + { + name: 'frontend', + script: "./scripts/start.sh", + instances: 1, + cwd: "./app", + interpreter: 'sh', + exec_mode: "fork", + autorestart: true, + watch: false, + max_memory_restart: '500M', + }, + { + name: 'backend', + script: 'npm', + args: 'run start', + cwd: "./backend", + instances: 1, + exec_mode: "fork", + autorestart: true, + watch: false, + max_memory_restart: '500M', + }, + { + name: "nginx", + script: "nginx", + args: "-g 'daemon off;'", + exec_interpreter: "none", + }, + ], +}; \ No newline at end of file diff --git a/nginx/default-stand-alone-docker.conf b/nginx/default-stand-alone-docker.conf new file mode 100644 index 000000000..b40e0fb13 --- /dev/null +++ b/nginx/default-stand-alone-docker.conf @@ -0,0 +1,36 @@ +events {} +http { + server { + listen 80; + + location /api { + proxy_set_header X-Real-RIP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + + proxy_set_header Host $http_host; + proxy_set_header X-NginX-Proxy true; + + proxy_pass http://localhost:4000; # for backend + proxy_redirect off; + + # proxy_cookie_path / "/; secure; HttpOnly; SameSite=strict"; + proxy_cookie_path / "/; HttpOnly; SameSite=strict"; + } + + location / { + include /etc/nginx/mime.types; + + proxy_set_header X-Real-RIP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + + proxy_set_header Host $http_host; + proxy_set_header X-NginX-Proxy true; + + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + + proxy_pass http://localhost:3000; # for frontend + proxy_redirect off; + } + } +} \ No newline at end of file From 9043db47275bd5c9fed21fb8d34eb36ea490f0c0 Mon Sep 17 00:00:00 2001 From: Maidul Islam Date: Wed, 3 May 2023 17:14:24 -0400 Subject: [PATCH 06/12] add github workflow to release standalone app --- .../release-standalone-docker-img.yml | 47 +++++++++++++++++++ ...fisical => Dockerfile.standalone-infisical | 0 2 files changed, 47 insertions(+) create mode 100644 .github/workflows/release-standalone-docker-img.yml rename Dockerfile.stand-alone-infisical => Dockerfile.standalone-infisical (100%) diff --git a/.github/workflows/release-standalone-docker-img.yml b/.github/workflows/release-standalone-docker-img.yml new file mode 100644 index 000000000..4cc8ce046 --- /dev/null +++ b/.github/workflows/release-standalone-docker-img.yml @@ -0,0 +1,47 @@ +name: Release standalone docker image +on: + push: + tags: + - "infisical-standalone/v*.*.*" + +jobs: + infisical-standalone: + name: Build infisical standalone image + runs-on: ubuntu-latest + steps: + - name: Extract version from tag + id: extract_version + run: echo "::set-output name=version::${GITHUB_REF_NAME#infisical/}" + - name: โ˜๏ธ Checkout source + uses: actions/checkout@v3 + - name: ๐Ÿ“ฆ Install dependencies to test all dependencies + run: npm ci --only-production + working-directory: backend + - name: ๐Ÿงช Run tests + run: npm run test:ci + working-directory: backend + - name: Save commit hashes for tag + id: commit + uses: pr-mpt/actions-commit-hash@v2 + - name: ๐Ÿ”ง Set up Docker Buildx + uses: docker/setup-buildx-action@v2 + - name: ๐Ÿ‹ Login to Docker Hub + uses: docker/login-action@v2 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + - name: Set up Depot CLI + uses: depot/setup-action@v1 + - name: ๐Ÿ“ฆ Build backend and export to Docker + uses: depot/build-push-action@v1 + with: + project: 64mmf0n610 + token: ${{ secrets.DEPOT_PROJECT_TOKEN }} + push: true + context: . + tags: | + infisical/standalone-infisical:${{ steps.commit.outputs.short }} + infisical/standalone-infisical:latest + infisical/standalone-infisical:${{ steps.extract_version.outputs.version }} + platforms: linux/amd64,linux/arm64 + file: Dockerfile.standalone-infisical diff --git a/Dockerfile.stand-alone-infisical b/Dockerfile.standalone-infisical similarity index 100% rename from Dockerfile.stand-alone-infisical rename to Dockerfile.standalone-infisical From 65b12eee5e56bfdecc546ccc9e70d182f9bef64f Mon Sep 17 00:00:00 2001 From: Maidul Islam Date: Wed, 3 May 2023 17:22:32 -0400 Subject: [PATCH 07/12] update standlone gwf --- .github/workflows/release-standalone-docker-img.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/release-standalone-docker-img.yml b/.github/workflows/release-standalone-docker-img.yml index 4cc8ce046..c3279c0d3 100644 --- a/.github/workflows/release-standalone-docker-img.yml +++ b/.github/workflows/release-standalone-docker-img.yml @@ -40,8 +40,6 @@ jobs: push: true context: . tags: | - infisical/standalone-infisical:${{ steps.commit.outputs.short }} infisical/standalone-infisical:latest - infisical/standalone-infisical:${{ steps.extract_version.outputs.version }} platforms: linux/amd64,linux/arm64 file: Dockerfile.standalone-infisical From 38f578c4ae028720a19c5d7283689288e2c95790 Mon Sep 17 00:00:00 2001 From: Vladyslav Matsiiako Date: Wed, 3 May 2023 16:06:50 -0700 Subject: [PATCH 08/12] Fixed the issue with favicon --- frontend/src/pages/dashboard/[id].tsx | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/frontend/src/pages/dashboard/[id].tsx b/frontend/src/pages/dashboard/[id].tsx index e754279f3..9f5a0e765 100644 --- a/frontend/src/pages/dashboard/[id].tsx +++ b/frontend/src/pages/dashboard/[id].tsx @@ -816,17 +816,17 @@ export default function Dashboard() { }; return
+ + {t('common:head-title', { title: t('dashboard:title') })} + + + + + {!envInURL ? : (data ? (
- - {t('common:head-title', { title: t('dashboard:title') })} - - - - -
Date: Thu, 4 May 2023 20:42:49 +0530 Subject: [PATCH 09/12] feat(ui): fixed lagging issues with new dashboard --- .../src/components/navigation/NavHeader.tsx | 63 +- frontend/src/hooks/api/secrets/index.ts | 7 +- frontend/src/hooks/api/secrets/queries.tsx | 118 +- frontend/src/hooks/api/secrets/types.ts | 1 + frontend/src/layouts/AppLayout/AppLayout.tsx | 46 +- frontend/src/pages/dashboard/[id].tsx | 1237 +---------------- .../DashboardPage/DashboardEnvOverview.tsx | 237 ++-- .../src/views/DashboardPage/DashboardPage.tsx | 129 +- .../DashboardPage/DashboardPage.utils.ts | 98 +- .../EnvComparisonRow/EnvComparisonRow.tsx | 215 +-- .../SecretDetailDrawer/SecretDetailDrawer.tsx | 34 +- .../components/SecretInputRow/MaskedInput.tsx | 107 ++ .../SecretInputRow/SecretInputRow.tsx | 646 ++++----- .../SecretTableHeader/SecretTableHeader.tsx | 50 +- 14 files changed, 1009 insertions(+), 1979 deletions(-) create mode 100644 frontend/src/views/DashboardPage/components/SecretInputRow/MaskedInput.tsx diff --git a/frontend/src/components/navigation/NavHeader.tsx b/frontend/src/components/navigation/NavHeader.tsx index c8af1ce46..d807b45b7 100644 --- a/frontend/src/components/navigation/NavHeader.tsx +++ b/frontend/src/components/navigation/NavHeader.tsx @@ -1,3 +1,4 @@ +import Link from 'next/link'; import { useRouter } from 'next/router'; import { faAngleRight } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; @@ -21,6 +22,7 @@ import { Select, SelectItem, Tooltip } from '../v2'; * @param {string} obj.onEnvChange - the action that happens when an env is changed * @returns */ +// TODO(akhilmhdh): simply this header and nav system later export default function NavHeader({ pageName, isProjectRelated, @@ -38,7 +40,7 @@ export default function NavHeader({ }): JSX.Element { const { currentWorkspace } = useWorkspace(); const { currentOrg } = useOrganization(); - const router = useRouter() + const router = useRouter(); return (
@@ -59,31 +61,40 @@ export default function NavHeader({ )} - {pageName === 'Secrets' - ? {pageName} - :
{pageName}
} - {currentEnv && - <> - -
- - - -
- } + {pageName === 'Secrets' ? ( + + {pageName} + + ) : ( +
{pageName}
+ )} + {currentEnv && ( + <> + +
+ + + +
+ + )}
); } diff --git a/frontend/src/hooks/api/secrets/index.ts b/frontend/src/hooks/api/secrets/index.ts index c27cecfb1..013b9aef5 100644 --- a/frontend/src/hooks/api/secrets/index.ts +++ b/frontend/src/hooks/api/secrets/index.ts @@ -1 +1,6 @@ -export { useBatchSecretsOp, useGetProjectSecrets, useGetSecretVersion } from './queries'; +export { + useBatchSecretsOp, + useGetProjectSecrets, + useGetProjectSecretsByKey, + useGetSecretVersion +} from './queries'; diff --git a/frontend/src/hooks/api/secrets/queries.tsx b/frontend/src/hooks/api/secrets/queries.tsx index 031c661d1..ecc26c63d 100644 --- a/frontend/src/hooks/api/secrets/queries.tsx +++ b/frontend/src/hooks/api/secrets/queries.tsx @@ -19,7 +19,10 @@ import { export const secretKeys = { // this is also used in secretSnapshot part - getProjectSecret: (workspaceId: string, env: string | string[]) => [{ workspaceId, env }, 'secrets'], + getProjectSecret: (workspaceId: string, env: string | string[]) => [ + { workspaceId, env }, + 'secrets' + ], getSecretVersion: (secretId: string) => [{ secretId }, 'secret-versions'] }; @@ -32,11 +35,11 @@ const fetchProjectEncryptedSecrets = async (workspaceId: string, env: string | s } }); return data.secrets; - } - + } + if (typeof env === 'object') { let allEnvData: any = []; - + // eslint-disable-next-line no-restricted-syntax for (const envPoint of env) { // eslint-disable-next-line no-await-in-loop @@ -48,13 +51,12 @@ const fetchProjectEncryptedSecrets = async (workspaceId: string, env: string | s }); allEnvData = allEnvData.concat(data.secrets); } - + return allEnvData; - // eslint-disable-next-line no-else-return + // eslint-disable-next-line no-else-return } else { return null; } - }; export const useGetProjectSecrets = ({ @@ -117,7 +119,10 @@ export const useGetProjectSecrets = ({ }; if (encSecret.type === 'personal') { - personalSecrets[`${decryptedSecret.key}-${decryptedSecret.env}`] = { id: encSecret._id, value: secretValue }; + personalSecrets[`${decryptedSecret.key}-${decryptedSecret.env}`] = { + id: encSecret._id, + value: secretValue + }; } else { if (!duplicateSecretKey?.[`${decryptedSecret.key}-${decryptedSecret.env}`]) { sharedSecrets.push(decryptedSecret); @@ -126,17 +131,106 @@ export const useGetProjectSecrets = ({ } }); sharedSecrets.forEach((val) => { - if (personalSecrets?.[val.key]) { - val.idOverride = personalSecrets[val.key].id; - val.valueOverride = personalSecrets[val.key].value; + const dupKey = `${val.key}-${val.env}`; + if (personalSecrets?.[dupKey]) { + val.idOverride = personalSecrets[dupKey].id; + val.valueOverride = personalSecrets[dupKey].value; val.overrideAction = 'modified'; } }); - return { secrets: sharedSecrets }; } }); +export const useGetProjectSecretsByKey = ({ + workspaceId, + env, + decryptFileKey, + isPaused +}: GetProjectSecretsDTO) => + useQuery({ + // wait for all values to be available + enabled: Boolean(decryptFileKey && workspaceId && env) && !isPaused, + queryKey: secretKeys.getProjectSecret(workspaceId, env), + queryFn: () => fetchProjectEncryptedSecrets(workspaceId, env), + select: (data) => { + const PRIVATE_KEY = localStorage.getItem('PRIVATE_KEY') as string; + const latestKey = decryptFileKey; + const key = decryptAssymmetric({ + ciphertext: latestKey.encryptedKey, + nonce: latestKey.nonce, + publicKey: latestKey.sender.publicKey, + privateKey: PRIVATE_KEY + }); + + const sharedSecrets: Record = {}; + const personalSecrets: Record = {}; + // this used for add-only mode in dashboard + // type won't be there thus only one key is shown + const duplicateSecretKey: Record = {}; + const uniqSecKeys: Record = {}; + data.forEach((encSecret: EncryptedSecret) => { + const secretKey = decryptSymmetric({ + ciphertext: encSecret.secretKeyCiphertext, + iv: encSecret.secretKeyIV, + tag: encSecret.secretKeyTag, + key + }); + if (!uniqSecKeys?.[secretKey]) uniqSecKeys[secretKey] = true; + + const secretValue = decryptSymmetric({ + ciphertext: encSecret.secretValueCiphertext, + iv: encSecret.secretValueIV, + tag: encSecret.secretValueTag, + key + }); + + const secretComment = decryptSymmetric({ + ciphertext: encSecret.secretCommentCiphertext, + iv: encSecret.secretCommentIV, + tag: encSecret.secretCommentTag, + key + }); + + const decryptedSecret = { + _id: encSecret._id, + env: encSecret.environment, + key: secretKey, + value: secretValue, + tags: encSecret.tags, + comment: secretComment, + createdAt: encSecret.createdAt, + updatedAt: encSecret.updatedAt + }; + + if (encSecret.type === 'personal') { + personalSecrets[`${decryptedSecret.key}-${decryptedSecret.env}`] = { + id: encSecret._id, + value: secretValue + }; + } else { + if (!duplicateSecretKey?.[`${decryptedSecret.key}-${decryptedSecret.env}`]) { + if (!sharedSecrets?.[secretKey]) sharedSecrets[secretKey] = []; + sharedSecrets[secretKey].push(decryptedSecret); + } + duplicateSecretKey[`${decryptedSecret.key}-${decryptedSecret.env}`] = true; + } + }); + Object.keys(sharedSecrets).forEach((secName) => { + sharedSecrets[secName].forEach((val) => { + const dupKey = `${val.key}-${val.env}`; + if (personalSecrets?.[dupKey]) { + val.idOverride = personalSecrets[dupKey].id; + val.valueOverride = personalSecrets[dupKey].value; + val.overrideAction = 'modified'; + } + }); + }); + + return { secrets: sharedSecrets, uniqueSecCount: Object.keys(uniqSecKeys).length }; + } + }); + const fetchEncryptedSecretVersion = async (secretId: string, offset: number, limit: number) => { const { data } = await apiRequest.get<{ secretVersions: EncryptedSecretVersion[] }>( `/api/v1/secret/${secretId}/secret-versions`, diff --git a/frontend/src/hooks/api/secrets/types.ts b/frontend/src/hooks/api/secrets/types.ts index 567fecc9a..eb1157e91 100644 --- a/frontend/src/hooks/api/secrets/types.ts +++ b/frontend/src/hooks/api/secrets/types.ts @@ -62,6 +62,7 @@ type SecretTagArg = { _id: string; name: string; slug: string }; export type UpdateSecretArg = { _id: string; type: 'shared' | 'personal'; + secretName: string; secretKeyCiphertext: string; secretKeyIV: string; secretKeyTag: string; diff --git a/frontend/src/layouts/AppLayout/AppLayout.tsx b/frontend/src/layouts/AppLayout/AppLayout.tsx index 39a80b7b4..4c1f15ebd 100644 --- a/frontend/src/layouts/AppLayout/AppLayout.tsx +++ b/frontend/src/layouts/AppLayout/AppLayout.tsx @@ -8,11 +8,7 @@ import { Controller, useForm } from 'react-hook-form'; import Link from 'next/link'; import { useRouter } from 'next/router'; import { useTranslation } from 'next-i18next'; -import { - faBookOpen, - faMobile, - faPlus, -} from '@fortawesome/free-solid-svg-icons'; +import { faBookOpen, faMobile, faPlus } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { yupResolver } from '@hookform/resolvers/yup'; import queryString from 'query-string'; @@ -110,7 +106,6 @@ export const AppLayout = ({ children }: LayoutProps) => { ) { router.push('/noprojects'); } else if (router.asPath !== '/noprojects') { - // const pathSegments = router.asPath.split('/').filter(segment => segment.length > 0); // let intendedWorkspaceId; @@ -123,8 +118,8 @@ export const AppLayout = ({ children }: LayoutProps) => { // .split('/') // [router.asPath.split('/').length - 1].split('?')[0]; // } - - const pathSegments = router.asPath.split('/').filter(segment => segment.length > 0); + + const pathSegments = router.asPath.split('/').filter((segment) => segment.length > 0); let intendedWorkspaceId; if (pathSegments.length >= 2 && pathSegments[0] === 'dashboard') { @@ -140,7 +135,7 @@ export const AppLayout = ({ children }: LayoutProps) => { // const lastPathSegment = router.asPath.split('/').pop().split('?'); // [intendedWorkspaceId] = lastPathSegment; } - + if (!intendedWorkspaceId) return; if (!['callback', 'create', 'authorize'].includes(intendedWorkspaceId)) { @@ -149,7 +144,8 @@ export const AppLayout = ({ children }: LayoutProps) => { // If a user is not a member of a workspace they are trying to access, just push them to one of theirs if ( - !['callback', 'create', 'authorize'].includes(intendedWorkspaceId) && userWorkspaces[0]?._id !== undefined && + !['callback', 'create', 'authorize'].includes(intendedWorkspaceId) && + userWorkspaces[0]?._id !== undefined && !userWorkspaces .map((workspace: { _id: string }) => workspace._id) .includes(intendedWorkspaceId) @@ -240,21 +236,21 @@ export const AppLayout = ({ children }: LayoutProps) => { return ( <> -
+