diff --git a/.env.example b/.env.example index 169e6db0d..e8f9b747b 100644 --- a/.env.example +++ b/.env.example @@ -64,7 +64,7 @@ POSTHOG_PROJECT_API_KEY= STRIPE_SECRET_KEY= STRIPE_PUBLISHABLE_KEY= STRIPE_WEBHOOK_SECRET= -STRIPE_PRODUCT_CARD_AUTH= -STRIPE_PRODUCT_PRO= STRIPE_PRODUCT_STARTER= +STRIPE_PRODUCT_TEAM= +STRIPE_PRODUCT_PRO= NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY= \ No newline at end of file diff --git a/.eslintignore b/.eslintignore index 7a3d61558..1e484b986 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,3 +1,4 @@ node_modules built healthcheck.js +tailwind.config.js \ No newline at end of file diff --git a/.github/values.yaml b/.github/values.yaml index f1551d61a..5fd38b031 100644 --- a/.github/values.yaml +++ b/.github/values.yaml @@ -1,36 +1,93 @@ +##### +# INFISICAL K8 DEFAULT VALUES FILE +# PLEASE REPLACE VALUES/EDIT AS REQUIRED +##### + +nameOverride: "" + frontend: - replicaCount: 1 + name: frontend + podAnnotations: {} + deploymentAnnotations: + secrets.infisical.com/auto-reload: "true" + replicaCount: 2 image: - repository: - pullPolicy: Always + repository: infisical/frontend + pullPolicy: Always tag: "latest" kubeSecretRef: managed-secret-frontend + service: + # type of the frontend service + type: ClusterIP + # define the nodePort if service type is NodePort + # nodePort: + annotations: {} backend: - replicaCount: 1 + name: backend + podAnnotations: {} + deploymentAnnotations: + secrets.infisical.com/auto-reload: "true" + replicaCount: 2 image: - repository: + repository: infisical/backend pullPolicy: Always tag: "latest" kubeSecretRef: managed-backend-secret + service: + annotations: {} + +mongodb: + name: mongodb + podAnnotations: {} + image: + repository: mongo + pullPolicy: IfNotPresent + tag: "latest" + service: + annotations: {} + +# By default the backend will be connected to a Mongo instance in the cluster. +# However, it is recommended to add a managed document DB connection string because the DB instance in the cluster does not have persistence yet ( data will be deleted on next deploy). +# Learn about connection string type here https://www.mongodb.com/docs/manual/reference/connection-string/ +mongodbConnection: {} + # externalMongoDBConnectionString: <> ingress: enabled: true annotations: kubernetes.io/ingress.class: "nginx" - cert-manager.io/cluster-issuer: "letsencrypt-prod" - hostName: gamma.infisical.com + hostName: gamma.infisical.com # replace with your domain frontend: path: / pathType: Prefix backend: path: /api pathType: Prefix - tls: - - secretName: echo-tls - hosts: - - gamma.infisical.com + tls: [] -backendEnvironmentVariables: -frontendEnvironmentVariables: \ No newline at end of file +## Complete Ingress example +# ingress: +# enabled: true +# annotations: +# kubernetes.io/ingress.class: "nginx" +# cert-manager.io/issuer: letsencrypt-nginx +# hostName: k8.infisical.com +# frontend: +# path: / +# pathType: Prefix +# backend: +# path: /api +# pathType: Prefix +# tls: +# - secretName: letsencrypt-nginx +# hosts: +# - k8.infisical.com + +### +### YOU MUST FILL IN ALL SECRETS BELOW +### +backendEnvironmentVariables: {} + +frontendEnvironmentVariables: {} diff --git a/.github/workflows/docker-image.yml b/.github/workflows/docker-image.yml index b4f9546ae..15142984d 100644 --- a/.github/workflows/docker-image.yml +++ b/.github/workflows/docker-image.yml @@ -45,8 +45,9 @@ jobs: token: ${{ secrets.DEPOT_PROJECT_TOKEN }} push: true context: backend - tags: infisical/backend:${{ steps.commit.outputs.short }}, - infisical/backend:latest + tags: | + infisical/backend:${{ steps.commit.outputs.short }} + infisical/backend:latest platforms: linux/amd64,linux/arm64 frontend-image: @@ -94,8 +95,9 @@ jobs: push: true token: ${{ secrets.DEPOT_PROJECT_TOKEN }} context: frontend - tags: infisical/frontend:${{ steps.commit.outputs.short }}, - infisical/frontend:latest + tags: | + infisical/frontend:${{ steps.commit.outputs.short }} + infisical/frontend:latest platforms: linux/amd64,linux/arm64 build-args: | POSTHOG_API_KEY=${{ secrets.PUBLIC_POSTHOG_API_KEY }} @@ -135,4 +137,4 @@ jobs: exit 1 else echo "Helm upgrade was successful" - fi \ No newline at end of file + fi diff --git a/Makefile b/Makefile index 9e1f5c3f6..7ef83d948 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,7 @@ up-dev: docker-compose -f docker-compose.dev.yml up --build i-dev: - infisical export && infisical export > .env && docker-compose -f docker-compose.dev.yml up --build + infisical run -- docker-compose -f docker-compose.dev.yml up --build up-prod: docker-compose -f docker-compose.yml up --build diff --git a/README.md b/README.md index 711e206f7..8db0b919d 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ git commit activity - Cloudsmith downloads + Cloudsmith downloads Slack community channel @@ -37,6 +37,12 @@ Dashboard + +**Read this in other languages**: [English language](i18n/README.en.md) +[Spanish language](i18n/README.es.md) +[Korean language](i18n/README.ko.md) +[Turkish language](i18n/README.tr.md) + **[Infisical](https://infisical.com)** is an open source, E2EE tool to help teams manage and sync secrets and configs across their development workflow and infrastructure. It's designed to be simple and take minutes to get going. - **[User-Friendly Dashboard](https://infisical.com/docs/getting-started/dashboard/project)** to manage your team's secrets and configs within projects @@ -144,7 +150,9 @@ We're currently setting the foundation and building [integrations](https://infis - 🔜 Fly.io + + ✔️ Fly.io + @@ -157,7 +165,7 @@ We're currently setting the foundation and building [integrations](https://infis - 🔜 Railway + 🔜 Railway (https://github.com/Infisical/infisical/issues/271) @@ -192,7 +200,7 @@ We're currently setting the foundation and building [integrations](https://infis - 🔜 Railway + 🔜 Forge @@ -203,7 +211,9 @@ We're currently setting the foundation and building [integrations](https://infis 🔜 Supabase - 🔜 Render (https://github.com/Infisical/infisical/issues/132) + + ✔️ Render + @@ -337,7 +347,7 @@ Infisical officially launched as v.1.0 on November 21st, 2022. There are a lot o - + ## 🌎 Translations diff --git a/backend/environment.d.ts b/backend/environment.d.ts index 291a33550..8012416f6 100644 --- a/backend/environment.d.ts +++ b/backend/environment.d.ts @@ -3,8 +3,10 @@ export {}; declare global { namespace NodeJS { interface ProcessEnv { + PORT: string; EMAIL_TOKEN_LIFETIME: string; ENCRYPTION_KEY: string; + SALT_ROUNDS: string; JWT_AUTH_LIFETIME: string; JWT_AUTH_SECRET: string; JWT_REFRESH_LIFETIME: string; @@ -19,23 +21,31 @@ declare global { CLIENT_ID_HEROKU: string; CLIENT_ID_VERCEL: string; CLIENT_ID_NETLIFY: string; + CLIENT_ID_GITHUB: string; CLIENT_SECRET_HEROKU: string; CLIENT_SECRET_VERCEL: string; CLIENT_SECRET_NETLIFY: string; + CLIENT_SECRET_GITHUB: string; + CLIENT_SLUG_VERCEL: string; POSTHOG_HOST: string; POSTHOG_PROJECT_API_KEY: string; SENTRY_DSN: string; SITE_URL: string; SMTP_HOST: string; - SMTP_NAME: string; - SMTP_PASSWORD: string; + SMTP_SECURE: string; + SMTP_PORT: string; SMTP_USERNAME: string; - STRIPE_PRODUCT_CARD_AUTH: string; - STRIPE_PRODUCT_PRO: string; + SMTP_PASSWORD: string; + SMTP_FROM_ADDRESS: string; + SMTP_FROM_NAME: string; STRIPE_PRODUCT_STARTER: string; + STRIPE_PRODUCT_TEAM: string; + STRIPE_PRODUCT_PRO: string; STRIPE_PUBLISHABLE_KEY: string; STRIPE_SECRET_KEY: string; STRIPE_WEBHOOK_SECRET: string; + TELEMETRY_ENABLED: string; + LICENSE_KEY: string; } } } diff --git a/backend/src/config/index.ts b/backend/src/config/index.ts index 652b3c7b2..2ecd1af8c 100644 --- a/backend/src/config/index.ts +++ b/backend/src/config/index.ts @@ -13,11 +13,11 @@ const MONGO_URL = process.env.MONGO_URL!; const NODE_ENV = process.env.NODE_ENV! || 'production'; const VERBOSE_ERROR_OUTPUT = process.env.VERBOSE_ERROR_OUTPUT! === 'true' && true; const LOKI_HOST = process.env.LOKI_HOST || undefined; -const CLIENT_SECRET_HEROKU = process.env.CLIENT_SECRET_HEROKU!; const CLIENT_ID_HEROKU = process.env.CLIENT_ID_HEROKU!; const CLIENT_ID_VERCEL = process.env.CLIENT_ID_VERCEL!; const CLIENT_ID_NETLIFY = process.env.CLIENT_ID_NETLIFY!; const CLIENT_ID_GITHUB = process.env.CLIENT_ID_GITHUB!; +const CLIENT_SECRET_HEROKU = process.env.CLIENT_SECRET_HEROKU!; const CLIENT_SECRET_VERCEL = process.env.CLIENT_SECRET_VERCEL!; const CLIENT_SECRET_NETLIFY = process.env.CLIENT_SECRET_NETLIFY!; const CLIENT_SECRET_GITHUB = process.env.CLIENT_SECRET_GITHUB!; @@ -35,9 +35,9 @@ const SMTP_USERNAME = process.env.SMTP_USERNAME!; const SMTP_PASSWORD = process.env.SMTP_PASSWORD!; const SMTP_FROM_ADDRESS = process.env.SMTP_FROM_ADDRESS!; const SMTP_FROM_NAME = process.env.SMTP_FROM_NAME! || 'Infisical'; -const STRIPE_PRODUCT_CARD_AUTH = process.env.STRIPE_PRODUCT_CARD_AUTH!; -const STRIPE_PRODUCT_PRO = process.env.STRIPE_PRODUCT_PRO!; const STRIPE_PRODUCT_STARTER = process.env.STRIPE_PRODUCT_STARTER!; +const STRIPE_PRODUCT_PRO = process.env.STRIPE_PRODUCT_PRO!; +const STRIPE_PRODUCT_TEAM = process.env.STRIPE_PRODUCT_TEAM!; const STRIPE_PUBLISHABLE_KEY = process.env.STRIPE_PUBLISHABLE_KEY!; const STRIPE_SECRET_KEY = process.env.STRIPE_SECRET_KEY!; const STRIPE_WEBHOOK_SECRET = process.env.STRIPE_WEBHOOK_SECRET!; @@ -80,9 +80,9 @@ export { SMTP_PASSWORD, SMTP_FROM_ADDRESS, SMTP_FROM_NAME, - STRIPE_PRODUCT_CARD_AUTH, - STRIPE_PRODUCT_PRO, STRIPE_PRODUCT_STARTER, + STRIPE_PRODUCT_TEAM, + STRIPE_PRODUCT_PRO, STRIPE_PUBLISHABLE_KEY, STRIPE_SECRET_KEY, STRIPE_WEBHOOK_SECRET, diff --git a/backend/src/controllers/v1/authController.ts b/backend/src/controllers/v1/authController.ts index 882db688f..19850680e 100644 --- a/backend/src/controllers/v1/authController.ts +++ b/backend/src/controllers/v1/authController.ts @@ -12,6 +12,8 @@ import { JWT_AUTH_SECRET, JWT_REFRESH_SECRET } from '../../config'; +import LoginSRPDetail from '../../models/LoginSRPDetail'; +import { BadRequestError } from '../../utils/errors'; declare module 'jsonwebtoken' { export interface UserIDJwtPayload extends jwt.JwtPayload { @@ -19,8 +21,6 @@ declare module 'jsonwebtoken' { } } -const clientPublicKeys: any = {}; - /** * Log in user step 1: Return [salt] and [serverPublicKey] as part of step 1 of SRP protocol * @param req @@ -46,13 +46,15 @@ export const login1 = async (req: Request, res: Response) => { salt: user.salt, verifier: user.verifier }, - () => { + async () => { // generate server-side public key const serverPublicKey = server.getPublicKey(); - clientPublicKeys[email] = { - clientPublicKey, - serverBInt: bigintConversion.bigintToBuf(server.bInt) - }; + + await LoginSRPDetail.findOneAndReplace({ email: email }, { + email: email, + clientPublicKey: clientPublicKey, + serverBInt: bigintConversion.bigintToBuf(server.bInt), + }, { upsert: true, returnNewDocument: false }) return res.status(200).send({ serverPublicKey, @@ -85,15 +87,21 @@ export const login2 = async (req: Request, res: Response) => { if (!user) throw new Error('Failed to find user'); + const loginSRPDetailFromDB = await LoginSRPDetail.findOneAndDelete({ email: email }) + + if (!loginSRPDetailFromDB) { + return BadRequestError(Error("It looks like some details from the first login are not found. Please try login one again")) + } + const server = new jsrp.server(); server.init( { salt: user.salt, verifier: user.verifier, - b: clientPublicKeys[email].serverBInt + b: loginSRPDetailFromDB.serverBInt }, async () => { - server.setClientPublicKey(clientPublicKeys[email].clientPublicKey); + server.setClientPublicKey(loginSRPDetailFromDB.clientPublicKey); // compare server and client shared keys if (server.checkClientProof(clientProof)) { diff --git a/backend/src/controllers/v1/organizationController.ts b/backend/src/controllers/v1/organizationController.ts index 353d47e3f..6fbccffeb 100644 --- a/backend/src/controllers/v1/organizationController.ts +++ b/backend/src/controllers/v1/organizationController.ts @@ -2,10 +2,7 @@ import { Request, Response } from 'express'; import * as Sentry from '@sentry/node'; import { SITE_URL, - STRIPE_SECRET_KEY, - STRIPE_PRODUCT_STARTER, - STRIPE_PRODUCT_PRO, - STRIPE_PRODUCT_CARD_AUTH + STRIPE_SECRET_KEY } from '../../config'; import Stripe from 'stripe'; @@ -23,12 +20,6 @@ import { createOrganization as create } from '../../helpers/organization'; import { addMembershipsOrg } from '../../helpers/membershipOrg'; import { OWNER, ACCEPTED } from '../../variables'; -const productToPriceMap = { - starter: STRIPE_PRODUCT_STARTER, - pro: STRIPE_PRODUCT_PRO, - cardAuth: STRIPE_PRODUCT_CARD_AUTH -}; - export const getOrganizations = async (req: Request, res: Response) => { let organizations; try { @@ -340,7 +331,6 @@ export const createOrganizationPortalSession = async ( if (paymentMethods.data.length < 1) { // case: no payment method on file - productToPriceMap['cardAuth']; session = await stripe.checkout.sessions.create({ customer: req.membershipOrg.organization.customerId, mode: 'setup', diff --git a/backend/src/controllers/v2/secretsController.ts b/backend/src/controllers/v2/secretsController.ts index 828a4e8e1..4a5a919fd 100644 --- a/backend/src/controllers/v2/secretsController.ts +++ b/backend/src/controllers/v2/secretsController.ts @@ -105,19 +105,21 @@ export const createSecrets = async (req: Request, res: Response) => { secretValueCiphertext: string; secretValueIV: string; secretValueTag: string; - }) => ({ - version: 1, - workspace: new Types.ObjectId(workspaceId), - type, - user: type === SECRET_PERSONAL ? req.user : undefined, - environment, - secretKeyCiphertext, - secretKeyIV, - secretKeyTag, - secretValueCiphertext, - secretValueIV, - secretValueTag - })) + }) => { + return ({ + version: 1, + workspace: new Types.ObjectId(workspaceId), + type, + user: type === SECRET_PERSONAL ? req.user : undefined, + environment, + secretKeyCiphertext, + secretKeyIV, + secretKeyTag, + secretValueCiphertext, + secretValueIV, + secretValueTag + }); + }) ); setTimeout(async () => { diff --git a/backend/src/helpers/database.ts b/backend/src/helpers/database.ts index 1ba3bb911..9ba592ea3 100644 --- a/backend/src/helpers/database.ts +++ b/backend/src/helpers/database.ts @@ -1,5 +1,4 @@ import mongoose from 'mongoose'; -import { ISecret, Secret } from '../models'; import { EESecretService } from '../ee/services'; import { getLogger } from '../utils/logger'; @@ -16,6 +15,10 @@ const initDatabaseHelper = async ({ }) => { try { await mongoose.connect(mongoURL); + + // allow empty strings to pass the required validator + mongoose.Schema.Types.String.checkRequired(v => typeof v === 'string'); + getLogger("database").info("Database connection established"); await EESecretService.initSecretVersioning(); diff --git a/backend/src/helpers/organization.ts b/backend/src/helpers/organization.ts index e47f92fbe..4ba3592de 100644 --- a/backend/src/helpers/organization.ts +++ b/backend/src/helpers/organization.ts @@ -3,6 +3,7 @@ import Stripe from 'stripe'; import { STRIPE_SECRET_KEY, STRIPE_PRODUCT_STARTER, + STRIPE_PRODUCT_TEAM, STRIPE_PRODUCT_PRO } from '../config'; const stripe = new Stripe(STRIPE_SECRET_KEY, { @@ -14,6 +15,7 @@ import { Organization, MembershipOrg } from '../models'; const productToPriceMap = { starter: STRIPE_PRODUCT_STARTER, + team: STRIPE_PRODUCT_TEAM, pro: STRIPE_PRODUCT_PRO }; @@ -55,7 +57,7 @@ const createOrganization = async ({ } catch (err) { Sentry.setUser({ email }); Sentry.captureException(err); - throw new Error('Failed to create organization'); + throw new Error(`Failed to create organization [err=${err}]`); } return organization; diff --git a/backend/src/helpers/signup.ts b/backend/src/helpers/signup.ts index d0b392e00..3d2a397c9 100644 --- a/backend/src/helpers/signup.ts +++ b/backend/src/helpers/signup.ts @@ -108,7 +108,7 @@ const initializeDefaultOrg = async ({ roles: [ADMIN] }); } catch (err) { - throw new Error('Failed to initialize default organization and workspace'); + throw new Error(`Failed to initialize default organization and workspace [err=${err}]`); } }; diff --git a/backend/src/index.ts b/backend/src/index.ts index bc07ec3b9..a97b5b33b 100644 --- a/backend/src/index.ts +++ b/backend/src/index.ts @@ -8,6 +8,7 @@ import { DatabaseService } from './services'; import { setUpHealthEndpoint } from './services/health'; import { initSmtp } from './services/smtp'; import { setTransporter } from './helpers/nodemailer'; +import { createTestUserForDevelopment } from './utils/addDevelopmentUser'; DatabaseService.initDatabase(MONGO_URL); @@ -23,3 +24,5 @@ if (NODE_ENV !== 'test') { environment: NODE_ENV }); } + +createTestUserForDevelopment() diff --git a/backend/src/models/LoginSRPDetail.ts b/backend/src/models/LoginSRPDetail.ts new file mode 100644 index 000000000..f65e779c3 --- /dev/null +++ b/backend/src/models/LoginSRPDetail.ts @@ -0,0 +1,23 @@ +import mongoose, { Schema, model } from 'mongoose'; + +const LoginSRPDetailSchema = new Schema( + { + clientPublicKey: { + type: String, + required: true + }, + email: { + type: String, + required: true, + unique: true + }, + serverBInt: { type: mongoose.Schema.Types.Buffer }, + expireAt: { type: Date } + } +); + +const LoginSRPDetail = model('LoginSRPDetail', LoginSRPDetailSchema); + +// LoginSRPDetailSchema.index({ "expireAt": 1 }, { expireAfterSeconds: 0 }); + +export default LoginSRPDetail; diff --git a/backend/src/routes/v2/secrets.ts b/backend/src/routes/v2/secrets.ts index 45a273d35..9fca3039a 100644 --- a/backend/src/routes/v2/secrets.ts +++ b/backend/src/routes/v2/secrets.ts @@ -32,7 +32,7 @@ router.post( !secret.secretKeyCiphertext || !secret.secretKeyIV || !secret.secretKeyTag || - !secret.secretValueCiphertext || + (typeof secret.secretValueCiphertext !== 'string') || !secret.secretValueIV || !secret.secretValueTag ) { diff --git a/backend/src/utils/addDevelopmentUser.ts b/backend/src/utils/addDevelopmentUser.ts new file mode 100644 index 000000000..2020cf3ad --- /dev/null +++ b/backend/src/utils/addDevelopmentUser.ts @@ -0,0 +1,140 @@ +/************************************************************************************************ +* +* Attention: The credentials below are only for development purposes, it should never be used for production +* +************************************************************************************************/ + +import { NODE_ENV } from "../config" +import { Key, Membership, MembershipOrg, Organization, User, Workspace } from "../models"; +import { Types } from 'mongoose'; + +export const createTestUserForDevelopment = async () => { + if (NODE_ENV === "development") { + const testUserEmail = "test@localhost.local" + const testUserPassword = "testInfisical1" + const testUserId = "63cefa6ec8d3175601cfa980" + const testWorkspaceId = "63cefb15c8d3175601cfa989" + const testOrgId = "63cefb15c8d3175601cfa985" + const testMembershipId = "63cefb159185d9aa3ef0cf35" + const testMembershipOrgId = "63cefb159185d9aa3ef0cf31" + const testWorkspaceKeyId = "63cf48f0225e6955acec5eff" + + const testUser = { + _id: testUserId, + email: testUserEmail, + refreshVersion: 0, + encryptedPrivateKey: 'ITMdDXtLoxib4+53U/qzvIV/T/UalRwimogFCXv/UsulzEoiKM+aK2aqOb0=', + firstName: 'Jake', + iv: '9fp0dZHI+UuHeKkWMDvD6w==', + lastName: 'Moni', + publicKey: 'cf44BhkybbBfsE0fZHe2jvqtCj6KLXvSq4hVjV0svzk=', + salt: 'd8099dc70958090346910fb9639262b83cf526fc9b4555a171b36a9e1bcd0240', + tag: 'bQ/UTghqcQHRoSMpLQD33g==', + verifier: '12271fcd50937ca4512e1e3166adaf9d9fc7a5cd0e4c4cb3eda89f35572ede4d9eef23f64aef9220367abff9437b0b6fa55792c442f177201d87051cf77dadade254ff667170440327355fb7d6ac4745d4db302f4843632c2ed5919ebdcff343287a4cd552255d9e3ce81177edefe089617b7616683901475d393405f554634b9bf9230c041ac85624f37a60401be20b78044932580ae0868323be3749fbf856df1518153ba375fec628275f0c445f237446ea4aa7f12c1aa1d6b5fd74b7f2e88d062845a19819ec63f2d2ed9e9f37c055149649461d997d2ae1482f53b04f9de7493efbb9686fb19b2d559b9aa2b502c22dec83f9fc43290dfea89a1dc6f03580b3642b3824513853e81a441be9a0b2fde2231bac60f3287872617a36884697805eeea673cf1a351697834484ada0f282e4745015c9c2928d61e6d092f1b9c3a27eda8413175d23bb2edae62f82ccaf52bf5a6a90344a766c7e4ebf65dae9ae90b2ad4ae65dbf16e3a6948e429771cc50307ae86d454f71a746939ed061f080dd3ae369c1a0739819aca17af46a085bac1f2a5d936d198e7951a8ac3bb38b893665fe7312835abd3f61811f81efa2a8761af5070085f9b6adcca80bf9b0d81899c3d41487fba90728bb24eceb98bd69770360a232624133700ceb4d153f2ad702e0a5b7dfaf97d20bc8aa71dc8c20024a58c06a8fecdad18cb5a2f89c51eaf7' + } + + const testWorkspaceKey = { + _id: new Types.ObjectId(testWorkspaceKeyId), + workspace: testWorkspaceId, + encryptedKey: '96ZIRSU21CjVzIQ4Yp994FGWQvDdyK3gq+z+NCaJLK0ByTlvUePmf+AYGFJjkAdz', + nonce: '1jhCGqg9Wx3n0OtVxbDgiYYGq4S3EdgO', + sender: '63cefa6ec8d3175601cfa980', + receiver: '63cefa6ec8d3175601cfa980', + } + + const testWorkspace = { + _id: new Types.ObjectId(testWorkspaceId), + name: 'Example Project', + organization: testOrgId, + environments: [ + { + _id: '63cefb15c8d3175601cfa98a', + name: 'Development', + slug: 'dev' + }, + { + _id: '63cefb15c8d3175601cfa98b', + name: 'Test', + slug: 'test' + }, + { + _id: '63cefb15c8d3175601cfa98c', + name: 'Staging', + slug: 'staging' + }, + { + _id: '63cefb15c8d3175601cfa98d', + name: 'Production', + slug: 'prod' + } + ], + } + + const testOrg = { + _id: testOrgId, + name: 'Jake\'s organization' + } + + const testMembershipOrg = { + _id: testMembershipOrgId, + organization: testOrgId, + role: 'owner', + status: 'accepted', + user: testUserId, + } + + const testMembership = { + _id: testMembershipId, + role: 'admin', + user: testUserId, + workspace: testWorkspaceId + } + + try { + // create user if not exist + const userInDB = await User.findById(testUserId) + if (!userInDB) { + await User.create(testUser) + } + + // create org if not exist + const orgInDB = await Organization.findById(testOrgId) + if (!orgInDB) { + await Organization.create(testOrg) + } + + // create membership org if not exist + const membershipOrgInDB = await MembershipOrg.findById(testMembershipOrgId) + if (!membershipOrgInDB) { + await MembershipOrg.create(testMembershipOrg) + } + + // create membership + const membershipInDB = await Membership.findById(testMembershipId) + if (!membershipInDB) { + await Membership.create(testMembership) + } + + // create workspace if not exist + const workspaceInDB = await Workspace.findById(testWorkspaceId) + if (!workspaceInDB) { + await Workspace.create(testWorkspace) + } + + // create workspace key if not exist + const workspaceKeyInDB = await Key.findById(testWorkspaceKeyId) + if (!workspaceKeyInDB) { + await Key.create(testWorkspaceKey) + } + + /* eslint-disable no-console */ + console.info(`DEVELOPMENT MODE DETECTED: You may login with test user with email: ${testUserEmail} and password: ${testUserPassword}`) + /* eslint-enable no-console */ + + } catch (e) { + /* eslint-disable no-console */ + console.error(`Unable to create test user while booting up [err=${e}]`) + /* eslint-enable no-console */ + } + } +} \ No newline at end of file diff --git a/backend/src/variables/integration.ts b/backend/src/variables/integration.ts index 7cecb54c2..872b3e096 100644 --- a/backend/src/variables/integration.ts +++ b/backend/src/variables/integration.ts @@ -90,7 +90,7 @@ const INTEGRATION_OPTIONS = [ name: 'Fly.io', slug: 'flyio', image: 'Flyio.svg', - isAvailable: true, + isAvailable: false, type: 'pat', clientId: '', docsLink: '' diff --git a/cli/packages/cmd/root.go b/cli/packages/cmd/root.go index 196c20d7d..93a498860 100644 --- a/cli/packages/cmd/root.go +++ b/cli/packages/cmd/root.go @@ -17,7 +17,7 @@ var rootCmd = &cobra.Command{ Short: "Infisical CLI is used to inject environment variables into any process", Long: `Infisical is a simple, end-to-end encrypted service that enables teams to sync and manage their environment variables across their development life cycle.`, CompletionOptions: cobra.CompletionOptions{HiddenDefaultCmd: true}, - Version: "0.2.5", + Version: util.CLI_VERSION, } // Execute adds all child commands to the root command and sets flags appropriately. @@ -33,8 +33,9 @@ func init() { rootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle") rootCmd.PersistentFlags().BoolVarP(&debugLogging, "debug", "d", false, "Enable verbose logging") rootCmd.PersistentFlags().StringVar(&config.INFISICAL_URL, "domain", util.INFISICAL_DEFAULT_API_URL, "Point the CLI to your own backend [can also set via environment variable name: INFISICAL_API_URL]") - // rootCmd.PersistentPreRun = func(cmd *cobra.Command, args []string) { - // } + rootCmd.PersistentPreRun = func(cmd *cobra.Command, args []string) { + util.CheckForUpdate() + } // if config.INFISICAL_URL is set to the default value, check if INFISICAL_URL is set in the environment // this is used to allow overrides of the default value diff --git a/cli/packages/cmd/run.go b/cli/packages/cmd/run.go index dd1b492e5..4c7c9782f 100644 --- a/cli/packages/cmd/run.go +++ b/cli/packages/cmd/run.go @@ -166,7 +166,10 @@ func executeMultipleCommandWithEnvs(fullCommand string, secretsCount int, env [] if runtime.GOOS == "windows" { shell = [2]string{"cmd", "/C"} } else { - shell[0] = os.Getenv("SHELL") + currentShell := os.Getenv("SHELL") + if currentShell != "" { + shell[0] = currentShell + } } cmd := exec.Command(shell[0], shell[1], fullCommand) diff --git a/cli/packages/util/check-for-update.go b/cli/packages/util/check-for-update.go new file mode 100644 index 000000000..5fbf39a1e --- /dev/null +++ b/cli/packages/util/check-for-update.go @@ -0,0 +1,46 @@ +package util + +import ( + "encoding/json" + "fmt" + "io/ioutil" + "net/http" + "errors" +) + +func CheckForUpdate() { + latestVersion, err := getLatestTag("Infisical", "infisical") + if err != nil { + // do nothing and continue + return + } + if latestVersion != CLI_VERSION { + PrintWarning(fmt.Sprintf("Please update your CLI. You are running version %s but the latest version is %s", CLI_VERSION, latestVersion)) + } +} + +func getLatestTag(repoOwner string, repoName string) (string, error) { + url := fmt.Sprintf("https://api.github.com/repos/%s/%s/tags", repoOwner, repoName) + resp, err := http.Get(url) + if err != nil { + return "", err + } + if resp.StatusCode != 200 { + return "", errors.New(fmt.Sprintf("GitHub API returned status code %d", resp.StatusCode)) + } + + defer resp.Body.Close() + + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + return "", err + } + + var tags []struct { + Name string `json:"name"` + } + + json.Unmarshal(body, &tags) + + return tags[0].Name, nil +} diff --git a/cli/packages/util/constants.go b/cli/packages/util/constants.go index 1aa98e2a5..609cfe818 100644 --- a/cli/packages/util/constants.go +++ b/cli/packages/util/constants.go @@ -11,4 +11,5 @@ const ( KEYRING_SERVICE_NAME = "infisical" PERSONAL_SECRET_TYPE_NAME = "personal" SHARED_SECRET_TYPE_NAME = "shared" + CLI_VERSION = "v0.2.7" ) diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml index 773d2d116..6540589d8 100644 --- a/docker-compose.dev.yml +++ b/docker-compose.dev.yml @@ -58,6 +58,7 @@ services: - NEXT_PUBLIC_ENV=development - INFISICAL_TELEMETRY_ENABLED=${TELEMETRY_ENABLED} - NEXT_PUBLIC_STRIPE_PRODUCT_PRO=${STRIPE_PRODUCT_PRO} + - NEXT_PUBLIC_STRIPE_PRODUCT_TEAM=${STRIPE_PRODUCT_TEAM} - NEXT_PUBLIC_STRIPE_PRODUCT_STARTER=${STRIPE_PRODUCT_STARTER} networks: - infisical-dev @@ -93,7 +94,7 @@ services: smtp-server: container_name: infisical-dev-smtp-server - image: mailhog/mailhog + image: lytrax/mailhog:latest # https://github.com/mailhog/MailHog/issues/353#issuecomment-821137362 restart: always logging: driver: 'none' # disable saving logs diff --git a/docker-compose.yml b/docker-compose.yml index bd9022cef..6143695f5 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -40,6 +40,7 @@ services: # - NEXT_PUBLIC_POSTHOG_API_KEY=${POSTHOG_PROJECT_API_KEY} - INFISICAL_TELEMETRY_ENABLED=${TELEMETRY_ENABLED} - NEXT_PUBLIC_STRIPE_PRODUCT_PRO=${STRIPE_PRODUCT_PRO} + - NEXT_PUBLIC_STRIPE_PRODUCT_TEAM=${STRIPE_PRODUCT_TEAM} - NEXT_PUBLIC_STRIPE_PRODUCT_STARTER=${STRIPE_PRODUCT_STARTER} networks: - infisical diff --git a/docs/cli/commands/commands.mdx b/docs/cli/commands/commands.mdx index 7c1deeb1b..78870defc 100644 --- a/docs/cli/commands/commands.mdx +++ b/docs/cli/commands/commands.mdx @@ -1,5 +1,6 @@ --- title: "Commands" +description: "Infisical CLI command overview" --- ## Commands diff --git a/docs/cli/commands/export.mdx b/docs/cli/commands/export.mdx index bcbc89e89..d85057eba 100644 --- a/docs/cli/commands/export.mdx +++ b/docs/cli/commands/export.mdx @@ -1,5 +1,6 @@ --- title: "infisical export" +description: "Export Infisical secrets from CLI into different file formats" --- ```bash diff --git a/docs/cli/commands/init.mdx b/docs/cli/commands/init.mdx index 8d1c03061..d477541b8 100644 --- a/docs/cli/commands/init.mdx +++ b/docs/cli/commands/init.mdx @@ -1,5 +1,6 @@ --- title: "infisical init" +description: "Switch between Infisical projects within CLI" --- ```bash diff --git a/docs/cli/commands/login.mdx b/docs/cli/commands/login.mdx index de004c97f..36abaf94e 100644 --- a/docs/cli/commands/login.mdx +++ b/docs/cli/commands/login.mdx @@ -1,5 +1,6 @@ --- title: "infisical login" +description: "Login into Infisical from the CLI" --- ```bash diff --git a/docs/cli/commands/run.mdx b/docs/cli/commands/run.mdx index cbfcb4d98..a3f02cf44 100644 --- a/docs/cli/commands/run.mdx +++ b/docs/cli/commands/run.mdx @@ -1,5 +1,6 @@ --- title: "infisical run" +description: "The command that injects your secrets into local environment" --- diff --git a/docs/cli/commands/secrets.mdx b/docs/cli/commands/secrets.mdx index 9b4642347..0556e1866 100644 --- a/docs/cli/commands/secrets.mdx +++ b/docs/cli/commands/secrets.mdx @@ -1,5 +1,6 @@ --- title: "infisical secrets" +description: "Perform CRUD operations with Infisical secrets" --- ``` diff --git a/docs/cli/commands/vault.mdx b/docs/cli/commands/vault.mdx index f973cb727..2289c629c 100644 --- a/docs/cli/commands/vault.mdx +++ b/docs/cli/commands/vault.mdx @@ -1,5 +1,6 @@ --- title: "infisical vault" +description: "Change the vault type in Infisical" --- diff --git a/docs/cli/faq.mdx b/docs/cli/faq.mdx index 600386e81..6a98d8dc3 100644 --- a/docs/cli/faq.mdx +++ b/docs/cli/faq.mdx @@ -1,5 +1,6 @@ --- title: "FAQ" +description: "Frequently Asked Questions about Infisical" --- Frequently asked questions about the CLI can be found on this page. diff --git a/docs/cli/overview.mdx b/docs/cli/overview.mdx index 560dce083..18f2f1396 100644 --- a/docs/cli/overview.mdx +++ b/docs/cli/overview.mdx @@ -1,5 +1,6 @@ --- title: 'Install' +description: "Infisical's CLI is one of the best way to manage environments and secrets. Install it here" --- Prerequisite: Set up an account with [Infisical Cloud](https://app.infisical.com) or via a [self-hosted installation](/self-hosting/overview). diff --git a/docs/cli/token.mdx b/docs/cli/token.mdx index 5b3d2fd6b..38acab208 100644 --- a/docs/cli/token.mdx +++ b/docs/cli/token.mdx @@ -1,5 +1,6 @@ --- title: "Infisical Token" +description: "How to use Infical service token within the CLI." --- Prerequisite: [Infisical Token and How to Generate One](../../getting-started/dashboard/token). diff --git a/docs/cli/usage.mdx b/docs/cli/usage.mdx index fe08b60b3..6cb460874 100644 --- a/docs/cli/usage.mdx +++ b/docs/cli/usage.mdx @@ -1,5 +1,6 @@ --- title: "Usage" +description: "How to manage you secrets with Infisical's CLI?" --- Prerequisite: [Install the CLI](/cli/overview) diff --git a/docs/contributing/code-of-conduct.mdx b/docs/contributing/code-of-conduct.mdx index 439b49ee7..b9f1a1b7e 100644 --- a/docs/contributing/code-of-conduct.mdx +++ b/docs/contributing/code-of-conduct.mdx @@ -1,6 +1,6 @@ --- title: "Code of Conduct" -description: "" +description: "What you should know before contributing to Infisical?" --- ## Our Pledge diff --git a/docs/contributing/developing.mdx b/docs/contributing/developing.mdx index 423b83da2..64779587e 100644 --- a/docs/contributing/developing.mdx +++ b/docs/contributing/developing.mdx @@ -1,13 +1,12 @@ --- -title: 'Developing' +title: 'Local development' description: 'This guide will help you set up and run Infisical in development mode.' --- ## Clone the repo ```bash -# change location to the path you want Infisical to be installed -cd ~ +# navigate location to the path you want Infisical to be installed # clone the repo and cd to Infisical dir git clone https://github.com/Infisical/infisical @@ -16,57 +15,71 @@ cd infisical ## Set up environment variables -Start by creating a .env file at the root of the Infisical directory. It's best to start with the provided [`.env.example`](https://github.com/Infisical/infisical/blob/main/.env.example) template containing the necessary envars to fill out your .env file — you only have to modify the SMTP parameters. + +Start by creating a .env file at the root of the Infisical directory then copy the contents of the file below into the .env file. + + + ```env + # Keys + # Required key for platform encryption/decryption ops + ENCRYPTION_KEY=6c1fe4e407b8911c104518103505b218 + + # JWT + # Required secrets to sign JWT tokens + JWT_SIGNUP_SECRET=3679e04ca949f914c03332aaaeba805a + JWT_REFRESH_SECRET=5f2f3c8f0159068dc2bbb3a652a716ff + JWT_AUTH_SECRET=4be6ba5602e0fa0ac6ac05c3cd4d247f + JWT_SERVICE_SECRET=f32f716d70a42c5703f4656015e76200 + + # MongoDB + # Backend will connect to the MongoDB instance at connection string MONGO_URL which can either be a ref + # to the MongoDB container instance or Mongo Cloud + # Required + MONGO_URL=mongodb://root:example@mongo:27017/?authSource=admin + + # Optional credentials for MongoDB container instance and Mongo-Express + MONGO_USERNAME=root + MONGO_PASSWORD=example + + # Website URL + # Required + SITE_URL=http://localhost:8080 + + # Mail/SMTP + SMTP_HOST='smtp-server' + SMTP_PORT='1025' + SMTP_NAME='local' + SMTP_USERNAME='team@infisical.com' + SMTP_PASSWORD= + ``` + - The pre-populated environment variable values in the `.env.example` file are meant to be used in development only. - You'll want to fill in your own values in production, especially concerning encryption keys, secrets, and SMTP parameters. + The pre-populated environment variable values above are meant to be used in development only. They should never be used in production. -Refer to the [environment variable list](https://infisical.com/docs/self-hosting/configuration/envars) for guidance on each envar. +View all available [environment variables](https://infisical.com/docs/self-hosting/configuration/envars) and guidance for each. -### Helpful tips for developing with Infisical: +## Starting Infisical for development - -Use the `ENCRYPTION_KEY`, JWT-secret envars, `MONGO_URL`, `MONGO_USERNAME`, `MONGO_PASSWORD` provided in the `.env.example` file. +We use use Docker to easily spin up all required services to have Infisical up and running for development. If you are unfamiliar with Docker, don't worry, all you have to do is install [Docker](https://docs.docker.com/get-docker/) for your +machine and run the commands below to start up the development server. -If setting your own values: - -- `ENCRYPTION_KEY` should be a [32-byte random hex](https://www.browserling.com/tools/random-hex) -- `MONGO_URL` should take the form: `mongodb://[MONGO_USERNAME]:[MONGO_PASSWORD]@mongo:27017/?authSource=admin`. - - - -Bring and configure your own SMTP server by following our [email configuration guide](https://infisical.com/docs/self-hosting/configuration/email) (we recommend using either SendGrid or Mailgun). - -Alternatively, you can use the provided development (Mailhog) SMTP server to send and browse emails sent by the backend on http://localhost:8025; to use this option, set the following `SMTP_HOST`, `SMTP_PORT`, `SMTP_FROM_NAME`, `SMTP_USERNAME`, `SMTP_PASSWORD` below. - - -``` -SMTP_HOST=smtp-server -SMTP_PORT=1025 -SMTP_FROM_ADDRESS=team@infisical.com -SMTP_FROM_NAME=Infisical -SMTP_USERNAME=team@infisical.com -SMTP_PASSWORD= -``` - - - If using Mailhog, make sure to leave the `SMTP_PASSWORD` blank so the backend can connect to MailHog. - - -## Docker for development +#### Start local server ```bash -# build and start the services docker-compose -f docker-compose.dev.yml up --build --force-recreate ``` +#### Access local server -Then browse http://localhost:8080 +Once all the services have spun up, browse to http://localhost:8080. To sign in, you may use the default credentials listed below. + +Email: `test@localhost.local` +Password: `testInfisical1` + +#### Shutdown local server ```bash # To stop environment use Control+C (on Mac) CTRL+C (on Win) or docker-compose -f docker-compose.dev.yml down -# start services -docker-compose -f docker-compose.dev.yml up ``` \ No newline at end of file diff --git a/docs/getting-started/dashboard/audit-logs.mdx b/docs/getting-started/dashboard/audit-logs.mdx index 808a7112d..6a48d98ff 100644 --- a/docs/getting-started/dashboard/audit-logs.mdx +++ b/docs/getting-started/dashboard/audit-logs.mdx @@ -1,5 +1,6 @@ --- title: "Activity Logs" +description: "See which events are triggered within your Infisical project." --- Activity logs record all actions going through Infisical including who performed which CRUD operations on environment variables and from what IP address. They help answer questions like: diff --git a/docs/getting-started/dashboard/create-account.mdx b/docs/getting-started/dashboard/create-account.mdx index ddc1654e3..a4be2c847 100644 --- a/docs/getting-started/dashboard/create-account.mdx +++ b/docs/getting-started/dashboard/create-account.mdx @@ -1,5 +1,6 @@ --- title: "Sign up" +description: "How to create an account in Infisical?" --- ## Self-hosted diff --git a/docs/getting-started/dashboard/integrations.mdx b/docs/getting-started/dashboard/integrations.mdx index 3dc5a2656..18a5aa8a8 100644 --- a/docs/getting-started/dashboard/integrations.mdx +++ b/docs/getting-started/dashboard/integrations.mdx @@ -1,10 +1,11 @@ --- title: "Integrations" +description: "How to sync your secrets among various 3rd-party services with Infisical." --- Integrations allow environment variables to be synced across your entire infrastructure from local development to CI/CD and production. -We're still early with integrations, but expect more soon. +We're still relatively early with integrations. 6+ integrations are already avaiable but expect more coming very soon. View all available integrations and their guides diff --git a/docs/getting-started/dashboard/organization.mdx b/docs/getting-started/dashboard/organization.mdx index c58922daa..63ec2cd49 100644 --- a/docs/getting-started/dashboard/organization.mdx +++ b/docs/getting-started/dashboard/organization.mdx @@ -1,5 +1,6 @@ --- title: "Organization" +description: "How Infisical structures its organizations." --- An organization houses projects and members. diff --git a/docs/getting-started/dashboard/pit-recovery.mdx b/docs/getting-started/dashboard/pit-recovery.mdx index 8881f117f..eeba72d60 100644 --- a/docs/getting-started/dashboard/pit-recovery.mdx +++ b/docs/getting-started/dashboard/pit-recovery.mdx @@ -1,5 +1,6 @@ --- title: "Point-in-Time Recovery" +description: "How to rollback secrets and configs to any commit with Infisical." --- Point-in-time recovery allows environment variables to be rolled back to any point in time. It's powered by snapshots that get captured after mutations to environment variables. diff --git a/docs/getting-started/dashboard/project.mdx b/docs/getting-started/dashboard/project.mdx index aa64d635b..ce7df57e3 100644 --- a/docs/getting-started/dashboard/project.mdx +++ b/docs/getting-started/dashboard/project.mdx @@ -1,5 +1,6 @@ --- title: "Project" +description: "How Infisical organizes secrets into projects." --- A project houses environment variables for an application. diff --git a/docs/getting-started/dashboard/secret-versioning.mdx b/docs/getting-started/dashboard/secret-versioning.mdx index ccf94fef1..04c3086cd 100644 --- a/docs/getting-started/dashboard/secret-versioning.mdx +++ b/docs/getting-started/dashboard/secret-versioning.mdx @@ -1,5 +1,6 @@ --- title: "Secret Versioning" +description: "Version secrets and configurations with Infisical" --- Secret versioning records changes made to every secret. diff --git a/docs/getting-started/dashboard/token.mdx b/docs/getting-started/dashboard/token.mdx index 455a57929..0caaa81d7 100644 --- a/docs/getting-started/dashboard/token.mdx +++ b/docs/getting-started/dashboard/token.mdx @@ -1,5 +1,6 @@ --- title: "Infisical Token" +description: "Use Infisical service token as one of the authentication methods." --- An Infisical Token is needed to authenticate the CLI when there isn't an easy way to input your login credentials. diff --git a/docs/getting-started/features.mdx b/docs/getting-started/features.mdx index 0205f0a46..7eaf6f267 100644 --- a/docs/getting-started/features.mdx +++ b/docs/getting-started/features.mdx @@ -1,5 +1,6 @@ --- title: "Features" +description: "A list of features that Infisical has to offer." --- This is a non-exhaustive list of features that Infisical offers: @@ -30,9 +31,9 @@ We're building the future of secret management, one that's comprehensive and acc | More hosting options | Ongoing | | 1-Click Deploys | Ongoing | | Account recovery: Backup key | Ongoing | +| Access logs | Ongoing | | Account recovery: Member-assisted | Coming soon | | Slack & MS teams integrations | Coming soon | -| Access logs | Coming soon | | Version control for secrets | Coming soon | | 2FA | Coming soon | | Restricted IPs | Coming soon | diff --git a/docs/getting-started/introduction.mdx b/docs/getting-started/introduction.mdx index 72b86bf05..ff8b72c4d 100644 --- a/docs/getting-started/introduction.mdx +++ b/docs/getting-started/introduction.mdx @@ -1,5 +1,6 @@ --- title: "Introduction" +description: "What is Infisical?" --- Infisical is an [open-source](https://opensource.com/resources/what-open-source), [end-to-end encrypted](https://en.wikipedia.org/wiki/End-to-end_encryption) secret manager that enables teams to easily manage and sync their environment variables. @@ -35,3 +36,8 @@ Start syncing environment variables with [Infisical Cloud](https://app.infisical Explore integrations for Docker, AWS, Heroku, etc. + + + + Our team is happy to help you get started with Infisical. If you have any questions or want to learn how you can leverage Infisical within your infrastructure, **[set up a 1-on-1 with an Infisical engineer](https://cal.com/maidul/15min)**. + diff --git a/docs/getting-started/quickstart.mdx b/docs/getting-started/quickstart.mdx index 3c559cdcb..e3acd440d 100644 --- a/docs/getting-started/quickstart.mdx +++ b/docs/getting-started/quickstart.mdx @@ -1,5 +1,6 @@ --- title: "Quickstart" +description: "Start managing your developer secrets and configs with Infisical in 10 minutes." --- This example demonstrates how to store and inject environment variables from [Infisical Cloud](https://app.infisical.com) into your application. diff --git a/docs/integrations/cicd/githubactions.mdx b/docs/integrations/cicd/githubactions.mdx index 23dbc419e..8f93d8162 100644 --- a/docs/integrations/cicd/githubactions.mdx +++ b/docs/integrations/cicd/githubactions.mdx @@ -1,5 +1,6 @@ --- title: "GitHub Actions" +description: "How to automatically sync secrets from Infisical into your GitHub Actions." --- diff --git a/docs/integrations/cloud/flyio.mdx b/docs/integrations/cloud/flyio.mdx index 73518be96..e6d9afcef 100644 --- a/docs/integrations/cloud/flyio.mdx +++ b/docs/integrations/cloud/flyio.mdx @@ -1,5 +1,6 @@ --- title: "Fly.io" +description: "How to automatically sync secrets from Infisical into your Fly.io project." --- Prerequisites: diff --git a/docs/integrations/cloud/heroku.mdx b/docs/integrations/cloud/heroku.mdx index e16cd0d54..bbbaaf5a8 100644 --- a/docs/integrations/cloud/heroku.mdx +++ b/docs/integrations/cloud/heroku.mdx @@ -1,5 +1,6 @@ --- title: "Heroku" +description: "How to automatically sync secrets from Infisical into your Heroku project." --- Prerequisites: diff --git a/docs/integrations/cloud/netlify.mdx b/docs/integrations/cloud/netlify.mdx index e78f01368..f6b0e41e8 100644 --- a/docs/integrations/cloud/netlify.mdx +++ b/docs/integrations/cloud/netlify.mdx @@ -1,5 +1,6 @@ --- title: "Netlify" +description: "How to automatically sync secrets from Infisical into your Netlify project." --- diff --git a/docs/integrations/cloud/render.mdx b/docs/integrations/cloud/render.mdx index 612286098..9f9dbd08e 100644 --- a/docs/integrations/cloud/render.mdx +++ b/docs/integrations/cloud/render.mdx @@ -1,5 +1,6 @@ --- title: "Render" +description: "How to automatically sync secrets from Infisical into your Render project." --- Prerequisites: diff --git a/docs/integrations/cloud/vercel.mdx b/docs/integrations/cloud/vercel.mdx index bf5388976..804e3c50a 100644 --- a/docs/integrations/cloud/vercel.mdx +++ b/docs/integrations/cloud/vercel.mdx @@ -1,5 +1,6 @@ --- title: "Vercel" +description: "How to automatically sync secrets from Infisical into your Vercel project." --- Prerequisites: diff --git a/docs/integrations/frameworks/django.mdx b/docs/integrations/frameworks/django.mdx index ea786a0f7..2a62ea2f5 100644 --- a/docs/integrations/frameworks/django.mdx +++ b/docs/integrations/frameworks/django.mdx @@ -1,5 +1,6 @@ --- title: "Django" +description: "How to use Infisical to inject environment variables and secrets into a Django app." --- Prerequisites: diff --git a/docs/integrations/frameworks/dotnet.mdx b/docs/integrations/frameworks/dotnet.mdx index 7a1d358c1..7496a9d13 100644 --- a/docs/integrations/frameworks/dotnet.mdx +++ b/docs/integrations/frameworks/dotnet.mdx @@ -1,5 +1,6 @@ --- title: ".NET" +description: "How to use Infisical to inject environment variables and secrets into a .NET app." --- Prerequisites: diff --git a/docs/integrations/frameworks/express.mdx b/docs/integrations/frameworks/express.mdx index 363decf09..f73dd68e0 100644 --- a/docs/integrations/frameworks/express.mdx +++ b/docs/integrations/frameworks/express.mdx @@ -1,5 +1,6 @@ --- title: "Express, Fastify, Koa" +description: "How to use Infisical to inject environment variables and secrets into an Express app." --- Prerequisites: diff --git a/docs/integrations/frameworks/fiber.mdx b/docs/integrations/frameworks/fiber.mdx index 0c7d6aab2..896c015fb 100644 --- a/docs/integrations/frameworks/fiber.mdx +++ b/docs/integrations/frameworks/fiber.mdx @@ -1,5 +1,6 @@ --- title: "Fiber" +description: "How to use Infisical to inject environment variables and secrets into a Fiber app." --- Prerequisites: diff --git a/docs/integrations/frameworks/flask.mdx b/docs/integrations/frameworks/flask.mdx index e80a993e8..70759b1bf 100644 --- a/docs/integrations/frameworks/flask.mdx +++ b/docs/integrations/frameworks/flask.mdx @@ -1,5 +1,6 @@ --- title: "Flask" +description: "How to use Infisical to inject environment variables and secrets into a Flask app." --- Prerequisites: diff --git a/docs/integrations/frameworks/gatsby.mdx b/docs/integrations/frameworks/gatsby.mdx index 4e12265de..87be9691b 100644 --- a/docs/integrations/frameworks/gatsby.mdx +++ b/docs/integrations/frameworks/gatsby.mdx @@ -1,5 +1,6 @@ --- title: "Gatsby" +description: "How to use Infisical to inject environment variables and secrets into a Gatsby app." --- Prerequisites: diff --git a/docs/integrations/frameworks/laravel.mdx b/docs/integrations/frameworks/laravel.mdx index 0152e7c66..037d9ff73 100644 --- a/docs/integrations/frameworks/laravel.mdx +++ b/docs/integrations/frameworks/laravel.mdx @@ -1,5 +1,6 @@ --- title: "Laravel" +description: "How to use Infisical to inject environment variables and secrets into a Laravel app." --- Prerequisites: diff --git a/docs/integrations/frameworks/nestjs.mdx b/docs/integrations/frameworks/nestjs.mdx index 5e224587e..5f1ce6f8f 100644 --- a/docs/integrations/frameworks/nestjs.mdx +++ b/docs/integrations/frameworks/nestjs.mdx @@ -1,5 +1,6 @@ --- title: "NestJS" +description: "How to use Infisical to inject environment variables and secrets into a NestJS app." --- Prerequisites: diff --git a/docs/integrations/frameworks/nextjs.mdx b/docs/integrations/frameworks/nextjs.mdx index d6e46f54e..f3f99f86d 100644 --- a/docs/integrations/frameworks/nextjs.mdx +++ b/docs/integrations/frameworks/nextjs.mdx @@ -1,5 +1,6 @@ --- title: "Next.js" +description: "How to use Infisical to inject environment variables and secrets into a Next.js app." --- Prerequisites: diff --git a/docs/integrations/frameworks/nuxt.mdx b/docs/integrations/frameworks/nuxt.mdx index 8105940ee..3267d6542 100644 --- a/docs/integrations/frameworks/nuxt.mdx +++ b/docs/integrations/frameworks/nuxt.mdx @@ -1,5 +1,6 @@ --- title: "Nuxt" +description: "How to use Infisical to inject environment variables and secrets into a Nuxt app." --- Prerequisites: diff --git a/docs/integrations/frameworks/rails.mdx b/docs/integrations/frameworks/rails.mdx index 32e7cbd57..22dc471e3 100644 --- a/docs/integrations/frameworks/rails.mdx +++ b/docs/integrations/frameworks/rails.mdx @@ -1,5 +1,6 @@ --- title: "Ruby on Rails" +description: "How to use Infisical to inject environment variables and secrets into a Ruby on Rails app." --- Prerequisites: diff --git a/docs/integrations/frameworks/react.mdx b/docs/integrations/frameworks/react.mdx index 0c394ac7e..48ad5d74f 100644 --- a/docs/integrations/frameworks/react.mdx +++ b/docs/integrations/frameworks/react.mdx @@ -1,5 +1,6 @@ --- title: "React" +description: "How to use Infisical to inject environment variables and secrets into a React app." --- Prerequisites: diff --git a/docs/integrations/frameworks/remix.mdx b/docs/integrations/frameworks/remix.mdx index cc37a263e..d85844143 100644 --- a/docs/integrations/frameworks/remix.mdx +++ b/docs/integrations/frameworks/remix.mdx @@ -1,5 +1,6 @@ --- title: "Remix" +description: "How to use Infisical to inject environment variables and secrets into a Remix app." --- Prerequisites: diff --git a/docs/integrations/frameworks/vite.mdx b/docs/integrations/frameworks/vite.mdx index 2c6e80ff0..62a4bb2f6 100644 --- a/docs/integrations/frameworks/vite.mdx +++ b/docs/integrations/frameworks/vite.mdx @@ -1,5 +1,6 @@ --- title: "Vite" +description: "How to use Infisical to inject environment variables and secrets into a Vite app." --- Prerequisites: diff --git a/docs/integrations/frameworks/vue.mdx b/docs/integrations/frameworks/vue.mdx index 9bc17255c..240e4ae4b 100644 --- a/docs/integrations/frameworks/vue.mdx +++ b/docs/integrations/frameworks/vue.mdx @@ -1,5 +1,6 @@ --- title: "Vue" +description: "How to use Infisical to inject environment variables and secrets into a Vue.js app." --- Prerequisites: diff --git a/docs/integrations/overview.mdx b/docs/integrations/overview.mdx index c63e443d2..4f1e99227 100644 --- a/docs/integrations/overview.mdx +++ b/docs/integrations/overview.mdx @@ -1,5 +1,6 @@ --- title: "Overview" +description: "How to use Infisical to inject secrets and configs into various 3-rd party services and frameworks." --- Integrations allow environment variables to be synced from Infisical into your local development workflow, CI/CD pipelines, and production infrastructure. diff --git a/docs/integrations/platforms/docker-compose.mdx b/docs/integrations/platforms/docker-compose.mdx index f2cdd60c8..698316582 100644 --- a/docs/integrations/platforms/docker-compose.mdx +++ b/docs/integrations/platforms/docker-compose.mdx @@ -1,5 +1,6 @@ --- title: "Docker Compose" +description: "How to use Infisical to inject environment variables into container defined in your Docker Compose file." --- The Docker Compose integration enables you to inject environment variables from Infisical into the containers defined in your compose file. diff --git a/docs/integrations/platforms/docker.mdx b/docs/integrations/platforms/docker.mdx index 6f08c9ec8..8f53336ed 100644 --- a/docs/integrations/platforms/docker.mdx +++ b/docs/integrations/platforms/docker.mdx @@ -1,5 +1,6 @@ --- title: "Docker" +description: "How to use Infisical to inject environment variables into a Docker container." --- Infisical can be used in a Dockerfile to inject environment variables into a Docker container. @@ -31,25 +32,22 @@ Infisical can be used in a Dockerfile to inject environment variables into a Doc -## Modify the start command in your Dockerfile + ## Modify your Dockerfile start command -```dockerfile -CMD ["infisical", "--env=[env]", "projectId=[projectId]", "run", "---", "[your application start command]"] + To make your Docker container consume Infisical secrets, you can start your application with Infisical. + This will automatically pull the necessary secrets and make them available to your application as if they were natively exposed within the container. -# example -CMD ["infisical", "--env=prod", "projectId=62faf98ae0b05e83239b5da41", "run", "---", "npm run start"] -``` + ```dockerfile + CMD ["infisical", "run", "---", "[your application start command]"] -Required options: + # example with single single command + CMD ["infisical", "run", "---", "npm run start"] -| Option | Description | Default value | -| ------------- | ----------------------------------------------------------------------------------------------------------- | ------------- | -| `--env` | Used to set the environment that secrets are pulled from. Accepted values: `dev`, `staging`, `test`, `prod` | `dev` | -| `--projectId` | Used to link a local project to the platform | `None` | + # example with multiple commands + CMD ["infisical", "run", "--command", "npm run start && ..."] + ``` -## Generate an Infisical Token - -[Generate an Infisical Token](../../getting-started/dashboard/token) and keep it handy. + View more options for the `run` command [here](../../cli/commands/run) ## Feed Docker your Infisical Token @@ -58,3 +56,8 @@ The CLI looks out for an environment variable called `INFISICAL_TOKEN`. If the t ```bash docker run --env INFISICAL_TOKEN=[token]... ``` + +## Generate an Infisical Token + +[Generate an Infisical Token](../../getting-started/dashboard/token) and keep it handy. + diff --git a/docs/integrations/platforms/kubernetes.mdx b/docs/integrations/platforms/kubernetes.mdx index ee9baa85a..189dc9d7b 100644 --- a/docs/integrations/platforms/kubernetes.mdx +++ b/docs/integrations/platforms/kubernetes.mdx @@ -1,5 +1,6 @@ --- title: 'Kubernetes' +description: "This page explains how to use Infisical to inject secrets into Kubernetes clusters." --- The Infisical Secrets Operator is a custom Kubernetes controller that helps keep secrets in a cluster up to date by synchronizing them. diff --git a/docs/security/data-model.mdx b/docs/security/data-model.mdx index 6c07cb479..9f79cd254 100644 --- a/docs/security/data-model.mdx +++ b/docs/security/data-model.mdx @@ -1,5 +1,6 @@ --- title: "Data Model" +description: "Infisical's current Data Structure." --- Infisical stores a range of data namely user, secrets, keys, organization, project, and membership data. diff --git a/docs/security/mechanics.mdx b/docs/security/mechanics.mdx index 2be11c6fc..325224f90 100644 --- a/docs/security/mechanics.mdx +++ b/docs/security/mechanics.mdx @@ -1,5 +1,6 @@ --- title: "Mechanics" +description: "Quick explanation of how Infisical works." --- ## Signup diff --git a/docs/security/overview.mdx b/docs/security/overview.mdx index b4e1169df..643a54b38 100644 --- a/docs/security/overview.mdx +++ b/docs/security/overview.mdx @@ -1,12 +1,13 @@ --- title: "Overview" +description: "Infisical's security statement." --- ## Summary Infisical uses end-to-end encryption (E2EE) whenever possible to securely store and share secrets. It uses secure remote password (SRP) to handle authentication and public-key cryptography for secret sharing and syncing; secrets are symmetrically encrypted at rest by keys decryptable only by members of the project. -Infisical uses AES256-GCM for symmetric encryption and x2519-xsalsa20-poly1305 for asymmetric encryption operations mentioned in this brief; key generation and asymmetric algorithms are implemented with the [TweetNaCl.js](https://tweetnacl.js.org/#/) library which has been well-audited and recommended for use by cybersecurity firm Cure53. Lastly, the secure remote password (SRP) implementation uses [jsrp](https://github.com/alax/jsrp) package for user authentication. As part of our commitment to user privacy and security, we aim to conduct formal security and compliance audits in the following year. +Infisical uses AES256-GCM for symmetric encryption and x25519-xsalsa20-poly1305 for asymmetric encryption operations mentioned in this brief; key generation and asymmetric algorithms are implemented with the [TweetNaCl.js](https://tweetnacl.js.org/#/) library which has been well-audited and recommended for use by cybersecurity firm Cure53. Lastly, the secure remote password (SRP) implementation uses [jsrp](https://github.com/alax/jsrp) package for user authentication. As part of our commitment to user privacy and security, we aim to conduct formal security and compliance audits in the following year. ## Scope diff --git a/docs/self-hosting/configuration/email.mdx b/docs/self-hosting/configuration/email.mdx index 666ca7622..8cb6525d3 100644 --- a/docs/self-hosting/configuration/email.mdx +++ b/docs/self-hosting/configuration/email.mdx @@ -1,6 +1,6 @@ --- title: "Email" -description: "" +description: "How to configure your email when self-hosting Infisical." --- Infisical requires you to configure your own SMTP server for certain functionality like: diff --git a/docs/self-hosting/configuration/envars.mdx b/docs/self-hosting/configuration/envars.mdx index f598336b6..39d6542c9 100644 --- a/docs/self-hosting/configuration/envars.mdx +++ b/docs/self-hosting/configuration/envars.mdx @@ -1,6 +1,6 @@ --- title: "Environment Variables" -description: "" +description: "How to configure your environment variables when self-hosting Infisical." --- Configuring Infisical requires setting some environment variables. There is a file called [`.env.example`](https://github.com/Infisical/infisical/blob/main/.env.example) at the root directory of our main repo that you can use to create a `.env` file before you start the server. diff --git a/docs/self-hosting/deployments/kubernetes.mdx b/docs/self-hosting/deployments/kubernetes.mdx index 48dc8de07..28bdc2416 100644 --- a/docs/self-hosting/deployments/kubernetes.mdx +++ b/docs/self-hosting/deployments/kubernetes.mdx @@ -1,6 +1,6 @@ --- title: "Kubernetes" -description: "Deploy with Kubernetes" +description: "How to deploy Infisical with Kubernetes" --- @@ -23,35 +23,66 @@ If you're less technical and looking for a hands-free experience with minimal ov Before you can deploy the Helm chart, you must fill out the required environment variables. To do so, please copy the below file to a `.yaml` file. Refer to the available [environment variables](../../self-hosting/configuration/envars) to learn more - + ```yaml ##### -# INFISICAL K8 DEFAULT VALUES FIL +# INFISICAL K8 DEFAULT VALUES FILE # PLEASE REPLACE VALUES/EDIT AS REQUIRED ##### -frontend: - replicaCount: 1 - image: - repository: - pullPolicy: IfNotPresent - tag: "latest" - # kubeSecretRef: some-kube-secret-name +nameOverride: "" +frontend: + name: frontend + podAnnotations: {} + deploymentAnnotations: {} + replicaCount: 2 + image: + repository: infisical/frontend + pullPolicy: Always + tag: "latest" # It it highly recommended to select a specific tag for prod deployment so it is easy to rollback: https://hub.docker.com/r/infisical/frontend/tags + # kubeSecretRef: some-kube-secret-name + service: + # type of the frontend service + type: ClusterIP + # define the nodePort if service type is NodePort + # nodePort: + annotations: {} backend: - replicaCount: 1 + name: backend + podAnnotations: {} + deploymentAnnotations: {} + replicaCount: 2 image: - repository: - pullPolicy: IfNotPresent - tag: "latest" + repository: infisical/backend + pullPolicy: Always + tag: "latest" # It it highly recommended to select a specific tag for prod deployment so it is easy to rollback: https://hub.docker.com/r/infisical/backend/tags # kubeSecretRef: some-kube-secret-name + service: + annotations: {} + +mongodb: + name: mongodb + podAnnotations: {} + image: + repository: mongo + pullPolicy: IfNotPresent + tag: "latest" + service: + annotations: {} + +# By default the backend will be connected to a Mongo instance in the cluster. +# However, it is recommended to add a managed document DB connection string because the DB instance in the cluster does not have persistence yet ( data will be deleted on next deploy). +# Learn about connection string type here https://www.mongodb.com/docs/manual/reference/connection-string/ +mongodbConnection: {} + # externalMongoDBConnectionString: <> ingress: enabled: true annotations: kubernetes.io/ingress.class: "nginx" - hostName: example.com + hostName: example.com # replace with your domain frontend: path: / pathType: Prefix @@ -60,6 +91,7 @@ ingress: pathType: Prefix tls: [] + ## Complete Ingress example # ingress: # enabled: true @@ -93,15 +125,13 @@ backendEnvironmentVariables: # Mail/SMTP # Required to send emails - SMTP_HOST: MUST_REPLACE + SMTP_HOST: MUST_REPLACE SMTP_NAME: MUST_REPLACE SMTP_USERNAME: MUST_REPLACE SMTP_PASSWORD: MUST_REPLACE - # Recommended to replace with Mongo Cloud URI as the DB instance in the cluster does not have persistence yet - MONGO_URL: mongodb://root:root@mongodb-service:27017/ - frontendEnvironmentVariables: {} + ``` diff --git a/docs/self-hosting/deployments/linux.mdx b/docs/self-hosting/deployments/linux.mdx index 0282e46de..771a4104a 100644 --- a/docs/self-hosting/deployments/linux.mdx +++ b/docs/self-hosting/deployments/linux.mdx @@ -1,6 +1,6 @@ --- title: "Linux VM" -description: "Deploy with Docker-Compose" +description: "How to deploy Infisical with Docker-Compose" --- diff --git a/docs/self-hosting/overview.mdx b/docs/self-hosting/overview.mdx index b0729637c..7f3bc30bf 100644 --- a/docs/self-hosting/overview.mdx +++ b/docs/self-hosting/overview.mdx @@ -1,5 +1,6 @@ --- title: "Overview" +description: "Infisical is an open-source end-to-end encrypted secrets manager that developers can set up within 15 minutes." --- diff --git a/docs/spec.yaml b/docs/spec.yaml index f715c5d7b..3d5ca4d7d 100644 --- a/docs/spec.yaml +++ b/docs/spec.yaml @@ -2317,6 +2317,9 @@ components: Project: type: object properties: + _id: + type: string + example: '' name: type: string example: My Project diff --git a/frontend/.storybook/preview.js b/frontend/.storybook/preview.js index 4a19aa4c9..94133eee3 100644 --- a/frontend/.storybook/preview.js +++ b/frontend/.storybook/preview.js @@ -1,3 +1,4 @@ +import { themes } from '@storybook/theming'; import '../src/styles/globals.css'; export const parameters = { @@ -7,5 +8,8 @@ export const parameters = { color: /(background|color)$/i, date: /Date$/ } + }, + darkMode: { + dark: { ...themes.dark, appContentBg: '#0e1014', appBg: '#0e1014' } } }; diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 6a6a4e6c8..2ea43719e 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -7,6 +7,7 @@ "dependencies": { "@emotion/css": "^11.10.0", "@emotion/server": "^11.10.0", + "@fontsource/inter": "^4.5.15", "@fortawesome/fontawesome-svg-core": "^6.1.2", "@fortawesome/free-brands-svg-icons": "^6.1.2", "@fortawesome/free-regular-svg-icons": "^6.1.1", @@ -15,7 +16,9 @@ "@headlessui/react": "^1.6.6", "@radix-ui/react-accordion": "^1.1.0", "@radix-ui/react-alert-dialog": "^1.0.2", + "@radix-ui/react-checkbox": "^1.0.1", "@radix-ui/react-dialog": "^1.0.2", + "@radix-ui/react-dropdown-menu": "^2.0.2", "@radix-ui/react-label": "^2.0.0", "@radix-ui/react-popover": "^1.0.3", "@radix-ui/react-progress": "^1.0.1", @@ -33,6 +36,7 @@ "base64-loader": "^1.0.0", "classnames": "^2.3.1", "cookies": "^0.8.0", + "cva": "npm:class-variance-authority@^0.4.0", "fs": "^0.0.1-security", "gray-matter": "^4.0.3", "http-proxy": "^1.18.1", @@ -95,9 +99,10 @@ "eslint-plugin-storybook": "^0.6.10", "postcss": "^8.4.14", "prettier": "^2.8.3", + "prettier-plugin-tailwindcss": "^0.2.2", "storybook": "^7.0.0-beta.30", "storybook-dark-mode": "^2.0.5", - "tailwindcss": "^3.1.4", + "tailwindcss": "3.2", "typescript": "^4.9.3" } }, @@ -105,6 +110,7 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==", + "dev": true, "dependencies": { "@jridgewell/gen-mapping": "^0.1.0", "@jridgewell/trace-mapping": "^0.3.9" @@ -117,6 +123,7 @@ "version": "0.1.1", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==", + "dev": true, "dependencies": { "@jridgewell/set-array": "^1.0.0", "@jridgewell/sourcemap-codec": "^1.4.10" @@ -152,6 +159,7 @@ "version": "7.20.5", "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.20.5.tgz", "integrity": "sha512-KZXo2t10+/jxmkhNXc7pZTqRvSOIvVv/+lJwHS+B2rErwOyjuVRh60yVpb7liQ1U5t7lLJ1bz+t8tSypUZdm0g==", + "dev": true, "engines": { "node": ">=6.9.0" } @@ -160,6 +168,7 @@ "version": "7.20.5", "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.20.5.tgz", "integrity": "sha512-UdOWmk4pNWTm/4DlPUl/Pt4Gz4rcEMb7CY0Y3eJl5Yz1vI8ZJGmHWaVE55LoxRjdpx0z259GE9U5STA9atUinQ==", + "dev": true, "dependencies": { "@ampproject/remapping": "^2.1.0", "@babel/code-frame": "^7.18.6", @@ -189,6 +198,7 @@ "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, "dependencies": { "ms": "2.1.2" }, @@ -204,12 +214,14 @@ "node_modules/@babel/core/node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true }, "node_modules/@babel/core/node_modules/semver": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, "bin": { "semver": "bin/semver.js" } @@ -255,6 +267,7 @@ "version": "7.20.7", "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.20.7.tgz", "integrity": "sha512-4tGORmfQcrc+bvrjb5y3dG9Mx1IOZjsHqQVUz7XCNHO+iTmqxWnVg3KRygjGmpRLJGdQSKuvFinbIb0CnZwHAQ==", + "dev": true, "dependencies": { "@babel/compat-data": "^7.20.5", "@babel/helper-validator-option": "^7.18.6", @@ -273,6 +286,7 @@ "version": "5.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, "dependencies": { "yallist": "^3.0.2" } @@ -281,6 +295,7 @@ "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, "bin": { "semver": "bin/semver.js" } @@ -288,7 +303,8 @@ "node_modules/@babel/helper-compilation-targets/node_modules/yallist": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true }, "node_modules/@babel/helper-create-class-features-plugin": { "version": "7.20.12", @@ -447,6 +463,7 @@ "version": "7.20.11", "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.20.11.tgz", "integrity": "sha512-uRy78kN4psmji1s2QtbtcCSaj/LILFDp0f/ymhpQH5QY3nljUZCaNWz9X1dEj/8MBdBEFECs7yRhKn8i7NjZgg==", + "dev": true, "dependencies": { "@babel/helper-environment-visitor": "^7.18.9", "@babel/helper-module-imports": "^7.18.6", @@ -520,6 +537,7 @@ "version": "7.20.2", "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.20.2.tgz", "integrity": "sha512-+0woI/WPq59IrqDYbVGfshjT5Dmk/nnbdpcF8SnMhhXObpTq2KNBdLFRFrkVdbDOyUmHBCxzm5FHV1rACIkIbA==", + "dev": true, "dependencies": { "@babel/types": "^7.20.2" }, @@ -570,6 +588,7 @@ "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz", "integrity": "sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==", + "dev": true, "engines": { "node": ">=6.9.0" } @@ -593,6 +612,7 @@ "version": "7.20.6", "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.20.6.tgz", "integrity": "sha512-Pf/OjgfgFRW5bApskEz5pvidpim7tEDPlFtKcNRXWmfHGn9IEI2W2flqRQXTFb7gIPTyK++N6rVHuwKut4XK6w==", + "dev": true, "dependencies": { "@babel/template": "^7.18.10", "@babel/traverse": "^7.20.5", @@ -2793,6 +2813,11 @@ "react-dom": ">=16.8.0" } }, + "node_modules/@fontsource/inter": { + "version": "4.5.15", + "resolved": "https://registry.npmjs.org/@fontsource/inter/-/inter-4.5.15.tgz", + "integrity": "sha512-FzleM9AxZQK2nqsTDtBiY0PMEVWvnKnuu2i09+p6DHvrHsuucoV2j0tmw+kAT3L4hvsLdAIDv6MdGehsPIdT+Q==" + }, "node_modules/@fortawesome/fontawesome-common-types": { "version": "6.1.2", "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.1.2.tgz", @@ -3662,6 +3687,26 @@ "react-dom": "^16.8 || ^17.0 || ^18.0" } }, + "node_modules/@radix-ui/react-checkbox": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-checkbox/-/react-checkbox-1.0.1.tgz", + "integrity": "sha512-TisH0B8hWmYP3ONRduYCyN04rR9yLPIw/Rwyn1RoC1suSoGCa8Wn+YPdSSSarSszeIbcg3p2lBkDp2XXit4sZw==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/primitive": "1.0.0", + "@radix-ui/react-compose-refs": "1.0.0", + "@radix-ui/react-context": "1.0.0", + "@radix-ui/react-presence": "1.0.0", + "@radix-ui/react-primitive": "1.0.1", + "@radix-ui/react-use-controllable-state": "1.0.0", + "@radix-ui/react-use-previous": "1.0.0", + "@radix-ui/react-use-size": "1.0.0" + }, + "peerDependencies": { + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + } + }, "node_modules/@radix-ui/react-collapsible": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@radix-ui/react-collapsible/-/react-collapsible-1.0.1.tgz", @@ -3774,6 +3819,25 @@ "react-dom": "^16.8 || ^17.0 || ^18.0" } }, + "node_modules/@radix-ui/react-dropdown-menu": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dropdown-menu/-/react-dropdown-menu-2.0.2.tgz", + "integrity": "sha512-r0kN0fstrSi+uAdK2GkLxnnbhqVBy/9Q4o4PvGOYipW0BldQlYBMSmZprvCNj2i2mAATx16kvzIn12GnaGjbMw==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/primitive": "1.0.0", + "@radix-ui/react-compose-refs": "1.0.0", + "@radix-ui/react-context": "1.0.0", + "@radix-ui/react-id": "1.0.0", + "@radix-ui/react-menu": "2.0.2", + "@radix-ui/react-primitive": "1.0.1", + "@radix-ui/react-use-controllable-state": "1.0.0" + }, + "peerDependencies": { + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + } + }, "node_modules/@radix-ui/react-focus-guards": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.0.0.tgz", @@ -3825,6 +3889,36 @@ "react-dom": "^16.8 || ^17.0 || ^18.0" } }, + "node_modules/@radix-ui/react-menu": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-menu/-/react-menu-2.0.2.tgz", + "integrity": "sha512-H5dtBi/k3tc45IMd2Pu+Q2PyONFlsYJ5sWUlflSs8BQRghh5GhJHLRuB1yb88VOywuzzvGkaR/HUJJ65Jf2POA==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/primitive": "1.0.0", + "@radix-ui/react-collection": "1.0.1", + "@radix-ui/react-compose-refs": "1.0.0", + "@radix-ui/react-context": "1.0.0", + "@radix-ui/react-direction": "1.0.0", + "@radix-ui/react-dismissable-layer": "1.0.2", + "@radix-ui/react-focus-guards": "1.0.0", + "@radix-ui/react-focus-scope": "1.0.1", + "@radix-ui/react-id": "1.0.0", + "@radix-ui/react-popper": "1.1.0", + "@radix-ui/react-portal": "1.0.1", + "@radix-ui/react-presence": "1.0.0", + "@radix-ui/react-primitive": "1.0.1", + "@radix-ui/react-roving-focus": "1.0.2", + "@radix-ui/react-slot": "1.0.1", + "@radix-ui/react-use-callback-ref": "1.0.0", + "aria-hidden": "^1.1.1", + "react-remove-scroll": "2.5.5" + }, + "peerDependencies": { + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + } + }, "node_modules/@radix-ui/react-popover": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/@radix-ui/react-popover/-/react-popover-1.0.3.tgz", @@ -3928,6 +4022,27 @@ "react-dom": "^16.8 || ^17.0 || ^18.0" } }, + "node_modules/@radix-ui/react-roving-focus": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.0.2.tgz", + "integrity": "sha512-HLK+CqD/8pN6GfJm3U+cqpqhSKYAWiOJDe+A+8MfxBnOue39QEeMa43csUn2CXCHQT0/mewh1LrrG4tfkM9DMA==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/primitive": "1.0.0", + "@radix-ui/react-collection": "1.0.1", + "@radix-ui/react-compose-refs": "1.0.0", + "@radix-ui/react-context": "1.0.0", + "@radix-ui/react-direction": "1.0.0", + "@radix-ui/react-id": "1.0.0", + "@radix-ui/react-primitive": "1.0.1", + "@radix-ui/react-use-callback-ref": "1.0.0", + "@radix-ui/react-use-controllable-state": "1.0.0" + }, + "peerDependencies": { + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + } + }, "node_modules/@radix-ui/react-select": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@radix-ui/react-select/-/react-select-1.2.0.tgz", @@ -8864,6 +8979,7 @@ "version": "4.21.4", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.4.tgz", "integrity": "sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw==", + "dev": true, "funding": [ { "type": "opencollective", @@ -9956,6 +10072,23 @@ "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.0.tgz", "integrity": "sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA==" }, + "node_modules/cva": { + "name": "class-variance-authority", + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/class-variance-authority/-/class-variance-authority-0.4.0.tgz", + "integrity": "sha512-74enNN8O9ZNieycac/y8FxqgyzZhZbxmCitAtAeUrLPlxjSd5zA7LfpprmxEcOmQBnaGs5hYhiSGnJ0mqrtBLQ==", + "funding": { + "url": "https://joebell.co.uk" + }, + "peerDependencies": { + "typescript": ">= 4.5.5 < 5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, "node_modules/damerau-levenshtein": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", @@ -10529,7 +10662,8 @@ "node_modules/electron-to-chromium": { "version": "1.4.284", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz", - "integrity": "sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA==" + "integrity": "sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA==", + "dev": true }, "node_modules/emoji-regex": { "version": "9.2.2", @@ -10825,6 +10959,7 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true, "engines": { "node": ">=6" } @@ -12011,9 +12146,9 @@ "dev": true }, "node_modules/fast-glob": { - "version": "3.2.11", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz", - "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==", + "version": "3.2.12", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", + "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", "dev": true, "dependencies": { "@nodelib/fs.stat": "^2.0.2", @@ -12665,6 +12800,7 @@ "version": "1.0.0-beta.2", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, "engines": { "node": ">=6.9.0" } @@ -14837,6 +14973,7 @@ "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, "bin": { "json5": "lib/cli.js" }, @@ -16309,7 +16446,8 @@ "node_modules/node-releases": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.6.tgz", - "integrity": "sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==" + "integrity": "sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==", + "dev": true }, "node_modules/normalize-package-data": { "version": "2.5.0", @@ -17186,12 +17324,12 @@ } }, "node_modules/postcss-nested": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-5.0.6.tgz", - "integrity": "sha512-rKqm2Fk0KbA8Vt3AdGN0FB9OBOMDVajMG6ZCf/GoHgdxUJ4sBFp0A/uMIRm+MJUdo33YXEtjqIz8u7DAp8B7DA==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.0.0.tgz", + "integrity": "sha512-0DkamqrPcmkBDsLn+vQDIrtkSbNkv5AD/M322ySo9kqFkCIYklym2xEmWkwo+Y3/qZo34tzEPNUw4y7yMCdv5w==", "dev": true, "dependencies": { - "postcss-selector-parser": "^6.0.6" + "postcss-selector-parser": "^6.0.10" }, "engines": { "node": ">=12.0" @@ -17293,6 +17431,76 @@ "node": ">=6.0.0" } }, + "node_modules/prettier-plugin-tailwindcss": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/prettier-plugin-tailwindcss/-/prettier-plugin-tailwindcss-0.2.2.tgz", + "integrity": "sha512-5RjUbWRe305pUpc48MosoIp6uxZvZxrM6GyOgsbGLTce+ehePKNm7ziW2dLG2air9aXbGuXlHVSQQw4Lbosq3w==", + "dev": true, + "engines": { + "node": ">=12.17.0" + }, + "peerDependencies": { + "@prettier/plugin-php": "*", + "@prettier/plugin-pug": "*", + "@shopify/prettier-plugin-liquid": "*", + "@shufo/prettier-plugin-blade": "*", + "@trivago/prettier-plugin-sort-imports": "*", + "prettier": ">=2.2.0", + "prettier-plugin-astro": "*", + "prettier-plugin-css-order": "*", + "prettier-plugin-import-sort": "*", + "prettier-plugin-jsdoc": "*", + "prettier-plugin-organize-attributes": "*", + "prettier-plugin-organize-imports": "*", + "prettier-plugin-style-order": "*", + "prettier-plugin-svelte": "*", + "prettier-plugin-twig-melody": "*" + }, + "peerDependenciesMeta": { + "@prettier/plugin-php": { + "optional": true + }, + "@prettier/plugin-pug": { + "optional": true + }, + "@shopify/prettier-plugin-liquid": { + "optional": true + }, + "@shufo/prettier-plugin-blade": { + "optional": true + }, + "@trivago/prettier-plugin-sort-imports": { + "optional": true + }, + "prettier-plugin-astro": { + "optional": true + }, + "prettier-plugin-css-order": { + "optional": true + }, + "prettier-plugin-import-sort": { + "optional": true + }, + "prettier-plugin-jsdoc": { + "optional": true + }, + "prettier-plugin-organize-attributes": { + "optional": true + }, + "prettier-plugin-organize-imports": { + "optional": true + }, + "prettier-plugin-style-order": { + "optional": true + }, + "prettier-plugin-svelte": { + "optional": true + }, + "prettier-plugin-twig-melody": { + "optional": true + } + } + }, "node_modules/pretty-error": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-4.0.0.tgz", @@ -20403,9 +20611,9 @@ "integrity": "sha512-+fflfPxvHFr81hTJpQ3MIwtqgvefHZFUHFiIHpVIRXvG/nX9+gu2P7JNlFu2bfDMJ+uHhi/pUgzaYacMoXv+Ww==" }, "node_modules/tailwindcss": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.1.7.tgz", - "integrity": "sha512-r7mgumZ3k0InfVPpGWcX8X/Ut4xBfv+1O/+C73ar/m01LxGVzWvPxF/w6xIUPEztrCoz7axfx0SMdh8FH8ZvRQ==", + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.2.4.tgz", + "integrity": "sha512-AhwtHCKMtR71JgeYDaswmZXhPcW9iuI9Sp2LvZPo9upDZ7231ZJ7eA9RaURbhpXGVlrjX4cFNlB4ieTetEb7hQ==", "dev": true, "dependencies": { "arg": "^5.0.2", @@ -20414,18 +20622,19 @@ "detective": "^5.2.1", "didyoumean": "^1.2.2", "dlv": "^1.1.3", - "fast-glob": "^3.2.11", + "fast-glob": "^3.2.12", "glob-parent": "^6.0.2", "is-glob": "^4.0.3", "lilconfig": "^2.0.6", + "micromatch": "^4.0.5", "normalize-path": "^3.0.0", "object-hash": "^3.0.0", "picocolors": "^1.0.0", - "postcss": "^8.4.14", + "postcss": "^8.4.18", "postcss-import": "^14.1.0", "postcss-js": "^4.0.0", "postcss-load-config": "^3.1.4", - "postcss-nested": "5.0.6", + "postcss-nested": "6.0.0", "postcss-selector-parser": "^6.0.10", "postcss-value-parser": "^4.2.0", "quick-lru": "^5.1.1", @@ -20442,6 +20651,30 @@ "postcss": "^8.0.9" } }, + "node_modules/tailwindcss/node_modules/postcss": { + "version": "8.4.21", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.21.tgz", + "integrity": "sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + } + ], + "dependencies": { + "nanoid": "^3.3.4", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, "node_modules/tapable": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", @@ -21479,6 +21712,7 @@ "version": "1.0.10", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz", "integrity": "sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==", + "dev": true, "funding": [ { "type": "opencollective", @@ -22235,6 +22469,7 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==", + "dev": true, "requires": { "@jridgewell/gen-mapping": "^0.1.0", "@jridgewell/trace-mapping": "^0.3.9" @@ -22244,6 +22479,7 @@ "version": "0.1.1", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==", + "dev": true, "requires": { "@jridgewell/set-array": "^1.0.0", "@jridgewell/sourcemap-codec": "^1.4.10" @@ -22271,12 +22507,14 @@ "@babel/compat-data": { "version": "7.20.5", "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.20.5.tgz", - "integrity": "sha512-KZXo2t10+/jxmkhNXc7pZTqRvSOIvVv/+lJwHS+B2rErwOyjuVRh60yVpb7liQ1U5t7lLJ1bz+t8tSypUZdm0g==" + "integrity": "sha512-KZXo2t10+/jxmkhNXc7pZTqRvSOIvVv/+lJwHS+B2rErwOyjuVRh60yVpb7liQ1U5t7lLJ1bz+t8tSypUZdm0g==", + "dev": true }, "@babel/core": { "version": "7.20.5", "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.20.5.tgz", "integrity": "sha512-UdOWmk4pNWTm/4DlPUl/Pt4Gz4rcEMb7CY0Y3eJl5Yz1vI8ZJGmHWaVE55LoxRjdpx0z259GE9U5STA9atUinQ==", + "dev": true, "requires": { "@ampproject/remapping": "^2.1.0", "@babel/code-frame": "^7.18.6", @@ -22299,6 +22537,7 @@ "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, "requires": { "ms": "2.1.2" } @@ -22306,12 +22545,14 @@ "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true }, "semver": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true } } }, @@ -22347,6 +22588,7 @@ "version": "7.20.7", "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.20.7.tgz", "integrity": "sha512-4tGORmfQcrc+bvrjb5y3dG9Mx1IOZjsHqQVUz7XCNHO+iTmqxWnVg3KRygjGmpRLJGdQSKuvFinbIb0CnZwHAQ==", + "dev": true, "requires": { "@babel/compat-data": "^7.20.5", "@babel/helper-validator-option": "^7.18.6", @@ -22359,6 +22601,7 @@ "version": "5.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, "requires": { "yallist": "^3.0.2" } @@ -22366,12 +22609,14 @@ "semver": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true }, "yallist": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true } } }, @@ -22490,6 +22735,7 @@ "version": "7.20.11", "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.20.11.tgz", "integrity": "sha512-uRy78kN4psmji1s2QtbtcCSaj/LILFDp0f/ymhpQH5QY3nljUZCaNWz9X1dEj/8MBdBEFECs7yRhKn8i7NjZgg==", + "dev": true, "requires": { "@babel/helper-environment-visitor": "^7.18.9", "@babel/helper-module-imports": "^7.18.6", @@ -22545,6 +22791,7 @@ "version": "7.20.2", "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.20.2.tgz", "integrity": "sha512-+0woI/WPq59IrqDYbVGfshjT5Dmk/nnbdpcF8SnMhhXObpTq2KNBdLFRFrkVdbDOyUmHBCxzm5FHV1rACIkIbA==", + "dev": true, "requires": { "@babel/types": "^7.20.2" } @@ -22579,7 +22826,8 @@ "@babel/helper-validator-option": { "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz", - "integrity": "sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==" + "integrity": "sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==", + "dev": true }, "@babel/helper-wrap-function": { "version": "7.20.5", @@ -22597,6 +22845,7 @@ "version": "7.20.6", "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.20.6.tgz", "integrity": "sha512-Pf/OjgfgFRW5bApskEz5pvidpim7tEDPlFtKcNRXWmfHGn9IEI2W2flqRQXTFb7gIPTyK++N6rVHuwKut4XK6w==", + "dev": true, "requires": { "@babel/template": "^7.18.10", "@babel/traverse": "^7.20.5", @@ -23794,8 +24043,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.0.0.tgz", "integrity": "sha512-1eEgUGmkaljiBnRMTdksDV1W4kUnmwgp7X9G8B++9GYwl1lUdqSndSriIrTJ0N7LQaoauY9JJ2yhiOYK5+NI4A==", - "dev": true, - "requires": {} + "dev": true }, "@emotion/utils": { "version": "1.2.0", @@ -24047,6 +24295,11 @@ "use-isomorphic-layout-effect": "^1.1.1" } }, + "@fontsource/inter": { + "version": "4.5.15", + "resolved": "https://registry.npmjs.org/@fontsource/inter/-/inter-4.5.15.tgz", + "integrity": "sha512-FzleM9AxZQK2nqsTDtBiY0PMEVWvnKnuu2i09+p6DHvrHsuucoV2j0tmw+kAT3L4hvsLdAIDv6MdGehsPIdT+Q==" + }, "@fortawesome/fontawesome-common-types": { "version": "6.1.2", "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.1.2.tgz", @@ -24095,8 +24348,7 @@ "@headlessui/react": { "version": "1.6.6", "resolved": "https://registry.npmjs.org/@headlessui/react/-/react-1.6.6.tgz", - "integrity": "sha512-MFJtmj9Xh/hhBMhLccGbBoSk+sk61BlP6sJe4uQcVMtXZhCgGqd2GyIQzzmsdPdTEWGSF434CBi8mnhR6um46Q==", - "requires": {} + "integrity": "sha512-MFJtmj9Xh/hhBMhLccGbBoSk+sk61BlP6sJe4uQcVMtXZhCgGqd2GyIQzzmsdPdTEWGSF434CBi8mnhR6um46Q==" }, "@humanwhocodes/config-array": { "version": "0.11.8", @@ -24610,6 +24862,22 @@ "@radix-ui/react-primitive": "1.0.1" } }, + "@radix-ui/react-checkbox": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-checkbox/-/react-checkbox-1.0.1.tgz", + "integrity": "sha512-TisH0B8hWmYP3ONRduYCyN04rR9yLPIw/Rwyn1RoC1suSoGCa8Wn+YPdSSSarSszeIbcg3p2lBkDp2XXit4sZw==", + "requires": { + "@babel/runtime": "^7.13.10", + "@radix-ui/primitive": "1.0.0", + "@radix-ui/react-compose-refs": "1.0.0", + "@radix-ui/react-context": "1.0.0", + "@radix-ui/react-presence": "1.0.0", + "@radix-ui/react-primitive": "1.0.1", + "@radix-ui/react-use-controllable-state": "1.0.0", + "@radix-ui/react-use-previous": "1.0.0", + "@radix-ui/react-use-size": "1.0.0" + } + }, "@radix-ui/react-collapsible": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@radix-ui/react-collapsible/-/react-collapsible-1.0.1.tgz", @@ -24697,6 +24965,21 @@ "@radix-ui/react-use-escape-keydown": "1.0.2" } }, + "@radix-ui/react-dropdown-menu": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dropdown-menu/-/react-dropdown-menu-2.0.2.tgz", + "integrity": "sha512-r0kN0fstrSi+uAdK2GkLxnnbhqVBy/9Q4o4PvGOYipW0BldQlYBMSmZprvCNj2i2mAATx16kvzIn12GnaGjbMw==", + "requires": { + "@babel/runtime": "^7.13.10", + "@radix-ui/primitive": "1.0.0", + "@radix-ui/react-compose-refs": "1.0.0", + "@radix-ui/react-context": "1.0.0", + "@radix-ui/react-id": "1.0.0", + "@radix-ui/react-menu": "2.0.2", + "@radix-ui/react-primitive": "1.0.1", + "@radix-ui/react-use-controllable-state": "1.0.0" + } + }, "@radix-ui/react-focus-guards": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.0.0.tgz", @@ -24734,6 +25017,32 @@ "@radix-ui/react-primitive": "1.0.1" } }, + "@radix-ui/react-menu": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-menu/-/react-menu-2.0.2.tgz", + "integrity": "sha512-H5dtBi/k3tc45IMd2Pu+Q2PyONFlsYJ5sWUlflSs8BQRghh5GhJHLRuB1yb88VOywuzzvGkaR/HUJJ65Jf2POA==", + "requires": { + "@babel/runtime": "^7.13.10", + "@radix-ui/primitive": "1.0.0", + "@radix-ui/react-collection": "1.0.1", + "@radix-ui/react-compose-refs": "1.0.0", + "@radix-ui/react-context": "1.0.0", + "@radix-ui/react-direction": "1.0.0", + "@radix-ui/react-dismissable-layer": "1.0.2", + "@radix-ui/react-focus-guards": "1.0.0", + "@radix-ui/react-focus-scope": "1.0.1", + "@radix-ui/react-id": "1.0.0", + "@radix-ui/react-popper": "1.1.0", + "@radix-ui/react-portal": "1.0.1", + "@radix-ui/react-presence": "1.0.0", + "@radix-ui/react-primitive": "1.0.1", + "@radix-ui/react-roving-focus": "1.0.2", + "@radix-ui/react-slot": "1.0.1", + "@radix-ui/react-use-callback-ref": "1.0.0", + "aria-hidden": "^1.1.1", + "react-remove-scroll": "2.5.5" + } + }, "@radix-ui/react-popover": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/@radix-ui/react-popover/-/react-popover-1.0.3.tgz", @@ -24813,6 +25122,23 @@ "@radix-ui/react-primitive": "1.0.1" } }, + "@radix-ui/react-roving-focus": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.0.2.tgz", + "integrity": "sha512-HLK+CqD/8pN6GfJm3U+cqpqhSKYAWiOJDe+A+8MfxBnOue39QEeMa43csUn2CXCHQT0/mewh1LrrG4tfkM9DMA==", + "requires": { + "@babel/runtime": "^7.13.10", + "@radix-ui/primitive": "1.0.0", + "@radix-ui/react-collection": "1.0.1", + "@radix-ui/react-compose-refs": "1.0.0", + "@radix-ui/react-context": "1.0.0", + "@radix-ui/react-direction": "1.0.0", + "@radix-ui/react-id": "1.0.0", + "@radix-ui/react-primitive": "1.0.1", + "@radix-ui/react-use-callback-ref": "1.0.0", + "@radix-ui/react-use-controllable-state": "1.0.0" + } + }, "@radix-ui/react-select": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@radix-ui/react-select/-/react-select-1.2.0.tgz", @@ -27663,8 +27989,7 @@ "version": "5.3.2", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, - "requires": {} + "dev": true }, "acorn-node": { "version": "1.8.2", @@ -27798,8 +28123,7 @@ "version": "3.5.2", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true, - "requires": {} + "dev": true }, "ansi-align": { "version": "3.0.1", @@ -28098,8 +28422,7 @@ "axios-auth-refresh": { "version": "3.3.3", "resolved": "https://registry.npmjs.org/axios-auth-refresh/-/axios-auth-refresh-3.3.3.tgz", - "integrity": "sha512-2IbDhJ/h6ddNBBnnzn1VFK/qx17pE9aVqiafB8rx5LVHsJ1HtFpUGkbXY7PzTG+8P9HJWcyA3fNZl9BikSuilg==", - "requires": {} + "integrity": "sha512-2IbDhJ/h6ddNBBnnzn1VFK/qx17pE9aVqiafB8rx5LVHsJ1HtFpUGkbXY7PzTG+8P9HJWcyA3fNZl9BikSuilg==" }, "axobject-query": { "version": "3.1.1", @@ -28114,8 +28437,7 @@ "version": "7.0.0-bridge.0", "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-7.0.0-bridge.0.tgz", "integrity": "sha512-poPX9mZH/5CSanm50Q+1toVci6pv5KSRv/5TWCwtzQS5XEwn40BcCrgIeMFWP9CKKIniKXNxoIOnOq4VVlGXhg==", - "dev": true, - "requires": {} + "dev": true }, "babel-loader": { "version": "9.1.2", @@ -28499,6 +28821,7 @@ "version": "4.21.4", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.4.tgz", "integrity": "sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw==", + "dev": true, "requires": { "caniuse-lite": "^1.0.30001400", "electron-to-chromium": "^1.4.251", @@ -29325,6 +29648,11 @@ "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.0.tgz", "integrity": "sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA==" }, + "cva": { + "version": "npm:class-variance-authority@0.4.0", + "resolved": "https://registry.npmjs.org/class-variance-authority/-/class-variance-authority-0.4.0.tgz", + "integrity": "sha512-74enNN8O9ZNieycac/y8FxqgyzZhZbxmCitAtAeUrLPlxjSd5zA7LfpprmxEcOmQBnaGs5hYhiSGnJ0mqrtBLQ==" + }, "damerau-levenshtein": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", @@ -29776,7 +30104,8 @@ "electron-to-chromium": { "version": "1.4.284", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz", - "integrity": "sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA==" + "integrity": "sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA==", + "dev": true }, "emoji-regex": { "version": "9.2.2", @@ -30022,7 +30351,8 @@ "escalade": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==" + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true }, "escape-html": { "version": "1.0.3", @@ -30285,8 +30615,7 @@ "version": "8.6.0", "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.6.0.tgz", "integrity": "sha512-bAF0eLpLVqP5oEVUFKpMA+NnRFICwn9X8B5jrR9FcqnYBuPbqWEjTEspPWMj5ye6czoSLDweCzSo3Ko7gGrZaA==", - "dev": true, - "requires": {} + "dev": true }, "eslint-import-resolver-node": { "version": "0.3.7", @@ -30544,15 +30873,13 @@ "version": "4.6.0", "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz", "integrity": "sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==", - "dev": true, - "requires": {} + "dev": true }, "eslint-plugin-simple-import-sort": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/eslint-plugin-simple-import-sort/-/eslint-plugin-simple-import-sort-8.0.0.tgz", "integrity": "sha512-bXgJQ+lqhtQBCuWY/FUWdB27j4+lqcvXv5rUARkzbeWLwea+S5eBZEQrhnO+WgX3ZoJHVj0cn943iyXwByHHQw==", - "dev": true, - "requires": {} + "dev": true }, "eslint-plugin-storybook": { "version": "0.6.10", @@ -30913,9 +31240,9 @@ "dev": true }, "fast-glob": { - "version": "3.2.11", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz", - "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==", + "version": "3.2.12", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", + "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", "dev": true, "requires": { "@nodelib/fs.stat": "^2.0.2", @@ -31416,7 +31743,8 @@ "gensync": { "version": "1.0.0-beta.2", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==" + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true }, "get-caller-file": { "version": "2.0.5", @@ -31980,8 +32308,7 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", - "dev": true, - "requires": {} + "dev": true }, "ieee754": { "version": "1.2.1", @@ -32995,7 +33322,8 @@ "json5": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==" + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true }, "jsonfile": { "version": "6.1.0", @@ -33293,8 +33621,7 @@ "version": "7.1.8", "resolved": "https://registry.npmjs.org/markdown-to-jsx/-/markdown-to-jsx-7.1.8.tgz", "integrity": "sha512-rRSa1aFmFnpDRFAhv5vIkWM4nPaoB9vnzIjuIKa1wGupfn2hdCNeaQHKpu4/muoc8n8J7yowjTP2oncA4/Rbgg==", - "dev": true, - "requires": {} + "dev": true }, "md5.js": { "version": "1.3.5", @@ -34000,7 +34327,8 @@ "node-releases": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.6.tgz", - "integrity": "sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==" + "integrity": "sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==", + "dev": true }, "normalize-package-data": { "version": "2.5.0", @@ -34590,8 +34918,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz", "integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==", - "dev": true, - "requires": {} + "dev": true }, "postcss-modules-local-by-default": { "version": "4.0.0", @@ -34623,12 +34950,12 @@ } }, "postcss-nested": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-5.0.6.tgz", - "integrity": "sha512-rKqm2Fk0KbA8Vt3AdGN0FB9OBOMDVajMG6ZCf/GoHgdxUJ4sBFp0A/uMIRm+MJUdo33YXEtjqIz8u7DAp8B7DA==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.0.0.tgz", + "integrity": "sha512-0DkamqrPcmkBDsLn+vQDIrtkSbNkv5AD/M322ySo9kqFkCIYklym2xEmWkwo+Y3/qZo34tzEPNUw4y7yMCdv5w==", "dev": true, "requires": { - "postcss-selector-parser": "^6.0.6" + "postcss-selector-parser": "^6.0.10" } }, "postcss-selector-parser": { @@ -34696,6 +35023,12 @@ "fast-diff": "^1.1.2" } }, + "prettier-plugin-tailwindcss": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/prettier-plugin-tailwindcss/-/prettier-plugin-tailwindcss-0.2.2.tgz", + "integrity": "sha512-5RjUbWRe305pUpc48MosoIp6uxZvZxrM6GyOgsbGLTce+ehePKNm7ziW2dLG2air9aXbGuXlHVSQQw4Lbosq3w==", + "dev": true + }, "pretty-error": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-4.0.0.tgz", @@ -35087,8 +35420,7 @@ "version": "5.6.1", "resolved": "https://registry.npmjs.org/react-colorful/-/react-colorful-5.6.1.tgz", "integrity": "sha512-1exovf0uGTGyq5mXQT0zgQ80uvj2PCwvF8zY1RN9/vbJVSjSo3fsB/4L3ObbF7u70NduSiK4xu4Y6q1MHoUGEw==", - "dev": true, - "requires": {} + "dev": true }, "react-docgen": { "version": "5.4.3", @@ -35120,8 +35452,7 @@ "version": "2.2.2", "resolved": "https://registry.npmjs.org/react-docgen-typescript/-/react-docgen-typescript-2.2.2.tgz", "integrity": "sha512-tvg2ZtOpOi6QDwsb3GZhOjDkkX0h8Z2gipvTg6OVMUyoYoURhEiRNePT8NZItTVCDh39JJHnLdfCOkzoLbFnTg==", - "dev": true, - "requires": {} + "dev": true }, "react-dom": { "version": "17.0.2", @@ -35186,8 +35517,7 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/react-inspector/-/react-inspector-6.0.1.tgz", "integrity": "sha512-cxKSeFTf7jpSSVddm66sKdolG90qURAX3g1roTeaN6x0YEbtWc8JpmFN9+yIqLNH2uEkYerWLtJZIXRIFuBKrg==", - "dev": true, - "requires": {} + "dev": true }, "react-is": { "version": "16.13.1", @@ -35302,8 +35632,7 @@ "react-table": { "version": "7.8.0", "resolved": "https://registry.npmjs.org/react-table/-/react-table-7.8.0.tgz", - "integrity": "sha512-hNaz4ygkZO4bESeFfnfOft73iBUj8K5oKi1EcSHPAibEydfsX2MyU6Z8KCr3mv3C9Kqqh71U+DhZkFvibbnPbA==", - "requires": {} + "integrity": "sha512-hNaz4ygkZO4bESeFfnfOft73iBUj8K5oKi1EcSHPAibEydfsX2MyU6Z8KCr3mv3C9Kqqh71U+DhZkFvibbnPbA==" }, "read-cache": { "version": "1.0.0", @@ -35459,8 +35788,7 @@ "redux-thunk": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.4.1.tgz", - "integrity": "sha512-OOYGNY5Jy2TWvTL1KgAlVy6dcx3siPJ1wTq741EPyUKfn6W6nChdICjZwCd0p8AZBs5kWpZlbkXW2nE/zjUa+Q==", - "requires": {} + "integrity": "sha512-OOYGNY5Jy2TWvTL1KgAlVy6dcx3siPJ1wTq741EPyUKfn6W6nChdICjZwCd0p8AZBs5kWpZlbkXW2nE/zjUa+Q==" }, "regenerate": { "version": "1.4.2", @@ -36913,8 +37241,7 @@ "version": "3.3.1", "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-3.3.1.tgz", "integrity": "sha512-GPcQ+LDJbrcxHORTRes6Jy2sfvK2kS6hpSfI/fXhPt+spVzxF6LJ1dHLN9zIGmVaaP044YKaIatFaufENRiDoQ==", - "dev": true, - "requires": {} + "dev": true }, "style-to-object": { "version": "0.3.0", @@ -36944,8 +37271,7 @@ "styled-jsx": { "version": "5.0.7", "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.0.7.tgz", - "integrity": "sha512-b3sUzamS086YLRuvnaDigdAewz1/EFYlHpYBP5mZovKEdQQOIIYq8lApylub3HHZ6xFjV051kkGU7cudJmrXEA==", - "requires": {} + "integrity": "sha512-b3sUzamS086YLRuvnaDigdAewz1/EFYlHpYBP5mZovKEdQQOIIYq8lApylub3HHZ6xFjV051kkGU7cudJmrXEA==" }, "stylis": { "version": "4.0.13", @@ -36993,9 +37319,9 @@ "integrity": "sha512-+fflfPxvHFr81hTJpQ3MIwtqgvefHZFUHFiIHpVIRXvG/nX9+gu2P7JNlFu2bfDMJ+uHhi/pUgzaYacMoXv+Ww==" }, "tailwindcss": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.1.7.tgz", - "integrity": "sha512-r7mgumZ3k0InfVPpGWcX8X/Ut4xBfv+1O/+C73ar/m01LxGVzWvPxF/w6xIUPEztrCoz7axfx0SMdh8FH8ZvRQ==", + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.2.4.tgz", + "integrity": "sha512-AhwtHCKMtR71JgeYDaswmZXhPcW9iuI9Sp2LvZPo9upDZ7231ZJ7eA9RaURbhpXGVlrjX4cFNlB4ieTetEb7hQ==", "dev": true, "requires": { "arg": "^5.0.2", @@ -37004,22 +37330,36 @@ "detective": "^5.2.1", "didyoumean": "^1.2.2", "dlv": "^1.1.3", - "fast-glob": "^3.2.11", + "fast-glob": "^3.2.12", "glob-parent": "^6.0.2", "is-glob": "^4.0.3", "lilconfig": "^2.0.6", + "micromatch": "^4.0.5", "normalize-path": "^3.0.0", "object-hash": "^3.0.0", "picocolors": "^1.0.0", - "postcss": "^8.4.14", + "postcss": "^8.4.18", "postcss-import": "^14.1.0", "postcss-js": "^4.0.0", "postcss-load-config": "^3.1.4", - "postcss-nested": "5.0.6", + "postcss-nested": "6.0.0", "postcss-selector-parser": "^6.0.10", "postcss-value-parser": "^4.2.0", "quick-lru": "^5.1.1", "resolve": "^1.22.1" + }, + "dependencies": { + "postcss": { + "version": "8.4.21", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.21.tgz", + "integrity": "sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg==", + "dev": true, + "requires": { + "nanoid": "^3.3.4", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + } + } } }, "tapable": { @@ -37807,6 +38147,7 @@ "version": "1.0.10", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz", "integrity": "sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==", + "dev": true, "requires": { "escalade": "^3.1.1", "picocolors": "^1.0.0" @@ -37844,14 +38185,12 @@ "use-isomorphic-layout-effect": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.1.2.tgz", - "integrity": "sha512-49L8yCO3iGT/ZF9QttjwLF/ZD9Iwto5LnH5LmEdk/6cFmXddqi2ulF0edxTwjj+7mqvpVVGQWvbXZdn32wRSHA==", - "requires": {} + "integrity": "sha512-49L8yCO3iGT/ZF9QttjwLF/ZD9Iwto5LnH5LmEdk/6cFmXddqi2ulF0edxTwjj+7mqvpVVGQWvbXZdn32wRSHA==" }, "use-memo-one": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/use-memo-one/-/use-memo-one-1.1.3.tgz", - "integrity": "sha512-g66/K7ZQGYrI6dy8GLpVcMsBp4s17xNkYJVSMvTEevGy3nDxHOfE6z8BVE22+5G5x7t3+bhzrlTDB7ObrEE0cQ==", - "requires": {} + "integrity": "sha512-g66/K7ZQGYrI6dy8GLpVcMsBp4s17xNkYJVSMvTEevGy3nDxHOfE6z8BVE22+5G5x7t3+bhzrlTDB7ObrEE0cQ==" }, "use-sidecar": { "version": "1.1.2", @@ -37865,8 +38204,7 @@ "use-sync-external-store": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz", - "integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==", - "requires": {} + "integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==" }, "util": { "version": "0.12.5", @@ -38057,8 +38395,7 @@ "version": "1.8.0", "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz", "integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==", - "dev": true, - "requires": {} + "dev": true }, "eslint-scope": { "version": "5.1.1", @@ -38284,8 +38621,7 @@ "version": "8.12.0", "resolved": "https://registry.npmjs.org/ws/-/ws-8.12.0.tgz", "integrity": "sha512-kU62emKIdKVeEIOIKVegvqpXMSTAMLJozpHZaJNDYqBjzlSYXQGviYwN1osDLJ9av68qHd4a2oSjd7yD4pacig==", - "dev": true, - "requires": {} + "dev": true }, "xtend": { "version": "4.0.2", diff --git a/frontend/package.json b/frontend/package.json index 25efc0ccb..a8c2c2ee8 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -8,12 +8,13 @@ "start:docker": "next build && next start", "lint": "eslint --fix --ext js,ts,tsx ./src", "type-check": "tsc --project tsconfig.json", - "storybook": "storybook dev -p 6006", + "storybook": "storybook dev -p 6006 -s ./public", "build-storybook": "storybook build" }, "dependencies": { "@emotion/css": "^11.10.0", "@emotion/server": "^11.10.0", + "@fontsource/inter": "^4.5.15", "@fortawesome/fontawesome-svg-core": "^6.1.2", "@fortawesome/free-brands-svg-icons": "^6.1.2", "@fortawesome/free-regular-svg-icons": "^6.1.1", @@ -22,7 +23,9 @@ "@headlessui/react": "^1.6.6", "@radix-ui/react-accordion": "^1.1.0", "@radix-ui/react-alert-dialog": "^1.0.2", + "@radix-ui/react-checkbox": "^1.0.1", "@radix-ui/react-dialog": "^1.0.2", + "@radix-ui/react-dropdown-menu": "^2.0.2", "@radix-ui/react-label": "^2.0.0", "@radix-ui/react-popover": "^1.0.3", "@radix-ui/react-progress": "^1.0.1", @@ -40,6 +43,7 @@ "base64-loader": "^1.0.0", "classnames": "^2.3.1", "cookies": "^0.8.0", + "cva": "npm:class-variance-authority@^0.4.0", "fs": "^0.0.1-security", "gray-matter": "^4.0.3", "http-proxy": "^1.18.1", @@ -102,9 +106,10 @@ "eslint-plugin-storybook": "^0.6.10", "postcss": "^8.4.14", "prettier": "^2.8.3", + "prettier-plugin-tailwindcss": "^0.2.2", "storybook": "^7.0.0-beta.30", "storybook-dark-mode": "^2.0.5", - "tailwindcss": "^3.1.4", + "tailwindcss": "3.2", "typescript": "^4.9.3" } } diff --git a/frontend/public/data/frequentConstants.ts b/frontend/public/data/frequentConstants.ts index d2beee6d2..2ff525e54 100644 --- a/frontend/public/data/frequentConstants.ts +++ b/frontend/public/data/frequentConstants.ts @@ -30,8 +30,25 @@ const reverseContextNetlifyMapping: Mapping = { "Production": "production" } +const plansDev: Mapping = { + "starter": "prod_Mb4ATFT5QAHoPM", + "team": "prod_NEpD2WMXUS2eDn", + "professional": "prod_Mb4CetZ2jE7jdl", + "enterprise": "licence_key_required" +} + +const plansProd: Mapping = { + "starter": "prod_Mb8oR5XNwyFTul", + "team": "prod_NEp7fAB3UJWK6A", + "professional": "prod_Mb8pUIpA0OUi5N", + "enterprise": "licence_key_required" +} + +const plans = plansProd || plansDev; + export { contextNetlifyMapping, envMapping, + plans, reverseContextNetlifyMapping, reverseEnvMapping} diff --git a/frontend/public/locales/tr/activity.json b/frontend/public/locales/tr/activity.json new file mode 100644 index 000000000..80ac8f90d --- /dev/null +++ b/frontend/public/locales/tr/activity.json @@ -0,0 +1,11 @@ +{ + "title": "Aktivite Günlükleri", + "subtitle": "Bu Infisical projesi için Olay Geçmişi.", + "event": { + "readSecrets": "Sırlar Görüntülendi", + "updateSecrets": "Sırlar Güncellendi", + "addSecrets": "Sırlar Eklendi", + "deleteSecrets": "Sırlar Silindi" + }, + "ip-address": "IP Addresi" +} \ No newline at end of file diff --git a/frontend/public/locales/tr/billing.json b/frontend/public/locales/tr/billing.json new file mode 100644 index 000000000..d27ddc976 --- /dev/null +++ b/frontend/public/locales/tr/billing.json @@ -0,0 +1,28 @@ +{ + "title": "Planlar & Fiyatlandırma", + "description": "Kuruluşunuzun aboneliğini buradan görüntüleyin ve yönetin", + "subscription": "Abonelik", + "starter": { + "name": "Başlangıç", + "price-explanation": "5 takım üyesine kadar", + "text": "5 kişiyle herhangi bir projeyi ücretsiz yönet!", + "subtext": "Sonrasında aylık her üye başına 5$." + }, + "professional": { + "name": "Profesyonel", + "price-explanation": "/üye/ay", + "subtext": "Sınırsız miktarda üye ve proje dahildir.", + "text": "Anahtar yönetimine siz büyüdükçe ayak uydurun.." + }, + "enterprise": { + "name": "Kurumsal", + "text": "Anahtar yönetimine siz büyüdükçe ayak uydurun." + }, + "current-usage": "Mevcut Plan", + "free": "Ücretsiz", + "downgrade": "Düşürün", + "upgrade": "Yükseltin", + "learn-more": "Daha fazlasını öğrenim", + "custom-pricing": "Özel Fiyatlandırma", + "schedule-demo": "Bir Deneme Sürümü Planlayın " +} \ No newline at end of file diff --git a/frontend/public/locales/tr/common.json b/frontend/public/locales/tr/common.json new file mode 100644 index 000000000..38d54b476 --- /dev/null +++ b/frontend/public/locales/tr/common.json @@ -0,0 +1,34 @@ +{ + "head-title": "{{title}} | Infisical", + "error_project-already-exists": "Bu isimle bir proje zaten mevcut.", + "no-mobile": " Infisical'ı kullanmak için, lütfen daha büyük boyutlara sahip bir cihaz üzerinden giriş yapın. ", + "email": "Email", + "password": "Şifre", + "first-name": "Adınız", + "last-name": "Soyadınız", + "logout": "Çıkış Yap", + "validate-required": "Lütfen girin, sahip olduğunuz {{name}}", + "maintenance-alert": "Ufak teknik problemler yaşıyoruz. Sorunu çözmek üzere çalışıyoruz. Lütfen birkaç dakika içerisinde yeniden deneyin.", + "click-to-copy": "Kopyala", + "project-id": "Project ID", + "save-changes": "Değişiklikleri Kaydet", + "saved": "Kaydedildi", + "drop-zone": ".env yada .yaml dosyasını buraya sürükleyin", + "drop-zone-keys": "Daha çok anahatar eklemek için bir .env yada .yaml dosyasını sürükleyin.", + "role": "Rol", + "role_admin": "yönetici", + "display-name": "Ekran Adı", + "environment": "Environment", + "expired-in": "Süresi geçicek", + "language": "Dil", + "search": "Ara...", + "note": "Not", + "view-more": "Daha Fazla Göster", + "end-of-history": "Geçmişin Sonu", + "select-event": "Bir olay seçin", + "event": "Olay", + "user": "Kullanıcı", + "source": "Kaynak", + "time": "Zaman", + "timestamp": "Zaman Damgası" +} \ No newline at end of file diff --git a/frontend/public/locales/tr/dashboard.json b/frontend/public/locales/tr/dashboard.json new file mode 100644 index 000000000..c480ba18b --- /dev/null +++ b/frontend/public/locales/tr/dashboard.json @@ -0,0 +1,35 @@ +{ + "title": "Sırlar", + "og-title": "Saniyeler içerisinde .env dosyalarınızı yönetin", + "og-description": "Infisical takımların .env dosyalarını senkronize etmelerini ve yönetmelerini sağlayan uçtan uca şifrelenmiş basit bir platformdur", + "search-keys": "Anahtarları ara...", + "add-key": "Anahtar Ekle", + "personal": "Kişisel", + "personal-description": "Kişisel anahtarlar sadece sana görünür", + "shared": "Paylaşılan", + "shared-description": "Paylaşılan anahatarlar tüm takımına görünür", + "make-shared": "Paylaşılan Yap", + "make-personal": "Kişisel Yap", + "add-secret": "Yeni bir sır ekle", + "check-docs": { + "button": "Dokümanları Kontrol Et", + "title": "İyi iş!", + "line1": "Tebrikler, yeni anahtarlar eklediniz.", + "line2": "Bunları kendi Codebase' inize nasıl bağlarsınız, işte böyle." + }, + "sidebar": { + "secret": "Sır", + "key": "Anahtar", + "value": "Değer", + "override": "Bu değerin üzerine bir kişisel değer yazın ", + "version-history": "Versiyon Geçmişi", + "comments": "Yorumlar & Notlar", + "personal-explanation": "Bu bir kişisel sır. Herhangi bir takım üyesi ile paylaşılmaz.", + "generate-random-hex": "Rastegele hex oluştur", + "digits": "basamak", + "delete-key-dialog": { + "title": "Anahtarı Sil", + "confirm-delete-message": "Bu sırrı silmek istediğinden emin misin? Bu işlem geri alınamaz." + } + } +} \ No newline at end of file diff --git a/frontend/public/locales/tr/integrations.json b/frontend/public/locales/tr/integrations.json new file mode 100644 index 000000000..b8fe599f4 --- /dev/null +++ b/frontend/public/locales/tr/integrations.json @@ -0,0 +1,16 @@ +{ + "title": "Proje Entegrasyonları", + "description": "Infisical'ın üçüncü taraf hizmetlerle olan entegrasyonlarınızı yönetin.", + "no-integrations1": "Henüz ayarlanmış bir entegrasyonunuz yok. Oluşturduğunuz zaman, burada görünecekler.", + "no-integrations2": "Başlamak için aşağıdaki seçeneklerden herhangi birine tıklayın. Sadece 5 tıklama ile kurulumu halledin.", + "available": "Platform & Cloud Entegrasyonları", + "available-text1": "Bağlanmak istediğiniz entegrasyona tıklayın. Bu, ortam değişkenlerinizin seçilen üçüncü taraf hizmetlere otomatik olarak akmasını sağlar.", + "available-text2": "Not: Heroku ile entegrasyon sırasında güvenlik nedenleriyle uçtan uca şifrelemenin sürdürülmesi mümkün değildir. Teorik olarak bu, Infisical'ın ortam değişkenlerinin şifresini çözmesine izin verir. Pratikte biz bunun asla yapılmayacağının garantisini verebiliriz ve bu durum sırlarınızı çevrimiçi kötü niyetlilerden korumamıza olanak tanır. Çekirdek Infisical hizmeti her zaman uçtan uca şifreli kalacaktır. Sorularınız için support@infisical.com adresine ulaşın.", + "cloud-integrations": "Cloud Entegrasyonları", + "framework-integrations": "Framework Entegrasyonları", + "click-to-start": "Sırlarınızı senkronize etmeye başlamak için bir entegrasyona tıklayın.", + "click-to-setup": "Kurulum talimatlarını almak için bir frameworke tıklayın.", + "grant-access-to-secrets": "Infisical'a sırlarınıza erişim izni verin", + "why-infisical-needs-access": "Çoğu cloud entegrasyonu, Infisical'ın sırlarınızı aktarabilmek için sırlarınızı deşifre etmesini gerektirir.", + "grant-access-button": "Erişim izni ver" +} \ No newline at end of file diff --git a/frontend/public/locales/tr/login.json b/frontend/public/locales/tr/login.json new file mode 100644 index 000000000..f42551188 --- /dev/null +++ b/frontend/public/locales/tr/login.json @@ -0,0 +1,10 @@ +{ + "title": "Giriş Yap", + "og-title": "Infisical'a Giriş Yap", + "og-description": "Infisical ekiplerin .env dosyalarını senkronize etmelerini ve yönetmelerini sağlayan uçtan uca şifrelenmiş basit bir platformdur", + "login": "Giriş Yap", + "need-account": "Bir Infisical hesabına mı ihtiyacınız var?", + "create-account": "Hesap oluşturun", + "forgot-password": "Şifrenizi mi unuttunuz?", + "error-login": "Kimlik bilgileri yanlış." +} \ No newline at end of file diff --git a/frontend/public/locales/tr/nav.json b/frontend/public/locales/tr/nav.json new file mode 100644 index 000000000..aa6ea2df4 --- /dev/null +++ b/frontend/public/locales/tr/nav.json @@ -0,0 +1,22 @@ +{ + "support": { + "slack": "[YENİ] Slack Foruma katılın", + "docs": "Dokümanları okuyun", + "issue": "Bir Github Issue açın", + "email": "Bize mail yollayın" + }, + "user": { + "signed-in-as": "ŞU HESABA GİRİŞ YAPILDI", + "current-organization": "MEVZUT ORGANİZASYON", + "usage-billing": "Plan & Fiyatlandırma", + "invite": "Üyeleri Davet Et", + "other-organizations": "DİĞER ORGANİZASYONLAR" + }, + "menu": { + "project": "PROJE", + "secrets": "Sırlar", + "members": "Üyeler", + "integrations": "Entegrasyonlar", + "project-settings": "Proje Ayarları" + } +} \ No newline at end of file diff --git a/frontend/public/locales/tr/section-api-key.json b/frontend/public/locales/tr/section-api-key.json new file mode 100644 index 000000000..0c768ded6 --- /dev/null +++ b/frontend/public/locales/tr/section-api-key.json @@ -0,0 +1,13 @@ +{ + "api-keys": "Servis Belirteçleri", + "api-keys-description": "Her servis belirteci size, belirli bir projeye ve o proje içindeki belirli bir ortama özeldir.", + "add-new": "Yeni Belirteç Ekleyin", + "add-dialog": { + "title": "Bir API Anahtarı Ekleyin", + "description": "Adını ve son kullanma süresini belirleyin. Bir API anahtarı oluşturulduğunda, kaybolmadan önce yalnızca bir kez görebileceksiniz. Bir yere kaydettiğinizden emin olun.", + "name": "API Anahtarı Adı", + "add": "API Anahtarı Ekleyin", + "copy-service-token": "API Anahtarızı kopyalayın", + "copy-service-token-description": "Bu açılır pencereyi kapattığınızda, API anahtarınızı bir daha asla görmeyeceksiniz" + } +} \ No newline at end of file diff --git a/frontend/public/locales/tr/section-incident.json b/frontend/public/locales/tr/section-incident.json new file mode 100644 index 000000000..776c71c63 --- /dev/null +++ b/frontend/public/locales/tr/section-incident.json @@ -0,0 +1,11 @@ +{ + "incident-contacts": "Özel Durum İletişim Adresleri", + "incident-contacts-description": "Bu adresler olası olmayan ciddi bir olay durumunda bilgilendirilecek.", + "no-incident-contacts": "Hiçbir Özel Durum İletişim Adresi bulunamadı.", + "add-contact": "İletişim Adresi Ekle", + "add-dialog": { + "title": "Bir Özel Durum İletişim Adresi Ekleyin", + "description": "Bu kişi, olası olmayan ciddi bir olay durumunda bilgilendirilecektir..", + "add-incident": "Özel Durum İletişim Adresi Ekle" + } +} \ No newline at end of file diff --git a/frontend/public/locales/tr/section-members.json b/frontend/public/locales/tr/section-members.json new file mode 100644 index 000000000..b4a0c0ec7 --- /dev/null +++ b/frontend/public/locales/tr/section-members.json @@ -0,0 +1,14 @@ +{ + "add-member": "Üye Ekle", + "org-members": "Kuruluş Üyeleri", + "org-members-description": "Kuruluşunuzun üyelerini yönetin. Bu kullanıcılar daha sonra projelere yönlendirilebilir..", + "search-members": "Üyeleri arayın...", + "add-dialog": { + "add-member-to-project": "Projenize bir üye ekleyin", + "already-all-invited": "Kuruluşunuzdaki tüm kullanıcılar zaten davet edildi.", + "add-user-org-first": "Önce kuruluşa daha fazla kullanıcı ekleyin.", + "user-will-email": "Kullanıcı, talimatları içeren bir e-posta alacak.", + "looking-add": "<0>Kuruluşunuza kullanıcı eklemek istiyorsanız,<1>buraya tıklayın", + "add-user-to-org": "Kuruluşa Kullanıcı Ekleyin" + } +} \ No newline at end of file diff --git a/frontend/public/locales/tr/section-password.json b/frontend/public/locales/tr/section-password.json new file mode 100644 index 000000000..07e26ba58 --- /dev/null +++ b/frontend/public/locales/tr/section-password.json @@ -0,0 +1,11 @@ +{ + "password": "Şifre", + "change": "Şifreyi değiştir", + "current": "Mevcut şifre", + "current-wrong": "Mevcut şifre yanlış olabilir", + "new": "Yeni şifre", + "validate-base": "Şifre en az şunları içermelidir:", + "validate-length": "14 karakter", + "validate-case": "1 küçük harf", + "validate-number": "1 rakam" +} \ No newline at end of file diff --git a/frontend/public/locales/tr/section-token.json b/frontend/public/locales/tr/section-token.json new file mode 100644 index 000000000..aceaba6dd --- /dev/null +++ b/frontend/public/locales/tr/section-token.json @@ -0,0 +1,13 @@ +{ + "service-tokens": "Servis Belirteçleri", + "service-tokens-description": "Her servis belirteci size, belirli bir projeye ve o proje içindeki belirli bir ortama özeldir.", + "add-new": "Yeni Belirteç Ekle", + "add-dialog": { + "title": "{{target}} için bir servis belirteci ekleyin", + "description": "Adı, ortamı ve son kullanma süresini belirtin. Bir belirteç oluşturulduğunda, onu kaybolmadan önce yalnızca bir kez görebileceksiniz. Bir yere kaydettiğinizden emin olun.", + "name": "Servis Belirteci Adı", + "add": "Servis Belirteci Ekle", + "copy-service-token": "Service belirtecinizi kopyalayın", + "copy-service-token-description": "Bu açılır pencereyi kapattığınızda, servis belirtecinizi bir daha asla göremeyeceksiniz" + } +} \ No newline at end of file diff --git a/frontend/public/locales/tr/settings-members.json b/frontend/public/locales/tr/settings-members.json new file mode 100644 index 000000000..c4a7441b7 --- /dev/null +++ b/frontend/public/locales/tr/settings-members.json @@ -0,0 +1,4 @@ +{ + "title": "Proje Üyeleri", + "description": "Bu sayfa seçilen projenin üyelerini gösterir." +} \ No newline at end of file diff --git a/frontend/public/locales/tr/settings-org.json b/frontend/public/locales/tr/settings-org.json new file mode 100644 index 000000000..3cc5c0d82 --- /dev/null +++ b/frontend/public/locales/tr/settings-org.json @@ -0,0 +1,4 @@ +{ + "title": "Kuruluş Ayarları", + "description": "Kuruluşunuzun üyelerini yönetin. Bu kullanıcılar daha sonra projelere yönlendirilebilir.." +} \ No newline at end of file diff --git a/frontend/public/locales/tr/settings-personal.json b/frontend/public/locales/tr/settings-personal.json new file mode 100644 index 000000000..31c858efb --- /dev/null +++ b/frontend/public/locales/tr/settings-personal.json @@ -0,0 +1,16 @@ +{ + "title": "Kişisel Ayarlar", + "description": "Kişisel bilgilerinizi burada görüntüleyin ve yönetin.", + "emergency": { + "name": "Acil Durum Kiti", + "text1": "Acil Durum Kitiniz, Infisical hesabınızda oturum açmak için ihtiyaç duyacağınız bilgileri içerir.", + "text2": "Yalnızca en son yayınlanan Acil Durum Kiti geçerliliğini korur. Yeni bir Acil Durum Kiti almak için parolanızı doğrulayın.", + "download": "Acil Durum Kitini İndir" + }, + "change-language": "Dili Değiştir", + "api-keys": { + "title": "API Anahtarları", + "description": "Infisical API'ye erişmek için kişisel API Anahtarlarınızı yönetin", + "add-new": "Ekle yeni" + } +} \ No newline at end of file diff --git a/frontend/public/locales/tr/settings-project.json b/frontend/public/locales/tr/settings-project.json new file mode 100644 index 000000000..41f9f3001 --- /dev/null +++ b/frontend/public/locales/tr/settings-project.json @@ -0,0 +1,13 @@ +{ + "title": "Proje Ayarları", + "description": "Bu ayarlar yalnızca mevcut seçili projeye uygulanacak.", + "danger-zone": "Tehlikeli Bölge", + "delete-project": "Projeyi Sil", + "project-to-delete": "Silinmek Üzere Olan Proje", + "danger-zone-note": "Bu projeyi sildiğiniz anda geri alamayacaksınız. Bu, tüm anahtarları hemen kaldıracaktır. Bunu hala yapmak istiyorsanız, lütfen aşağıya projenin adını girin.", + "delete-project-note": "Not: Yalnızca birden fazla projeniz olması durumunda, bir projeyi silebilirsiniz.", + "project-id-description": "Infisical'ı kod tabanınıza entegre etmek ve çevresel değişkenlerin otomatik enjeksiyonunu almak için aşağıdaki Proje Kimliğini kullanmalısınız.", + "project-id-description2": "Çeşitli diller ve çerçeveler için kod parçaları da dahil olmak üzere daha fazla rehberlik için bkz.", + "auto-generated": "Bu, projenizin otomatik olarak oluşturulan benzersiz tanımlayıcısıdır. Değiştirilemez..", + "docs": "Infisical Dokümanları" +} \ No newline at end of file diff --git a/frontend/public/locales/tr/signup.json b/frontend/public/locales/tr/signup.json new file mode 100644 index 000000000..4a0778335 --- /dev/null +++ b/frontend/public/locales/tr/signup.json @@ -0,0 +1,28 @@ +{ + "title": "Kayıt olun", + "og-title": "Tek satır kodla .env dosyalarını değiştirin. 3 dakika içerinde Infisical'a kayıt olun.", + "og-description": "Infisical takımların API anahtarlarını ve ortam değişkenlerini yönetmelerini ve senkronize etmelerini sağlayan basit, uçtan uca şifrelenmiş bir platformdur. Node.js, Next.js, Gatsby, Nest.js ve daha fazlası ile çalışır.", + "signup": "Kayıt ol", + "already-have-account": "Hesabın var mı? Giriş yap", + "forgot-password": "Şifreni mi unuttun?", + "verify": "Doğrula", + "step1-start": "Hadi başlayalım", + "step1-privacy": "Hesap oluşturarak, Şartlarımızı ve Gizlilik Politikasını okuyup kabul etmiş olursunuz.", + "step1-submit": "Başla", + "step2-message": "Şu adrese bir doğrulama maili yolladık", + "step2-code-error": "Tüh. Kodun hatalı. Lütfen tekrar dene.", + "step2-resend-alert": "Mail ulaşamadı mı?", + "step2-resend-submit": "Tekrar Yolla", + "step2-resend-progress": "Tekrar yollanıyor...", + "step2-spam-alert": "Spam kutunuzu kontrol ettiğinizden emin olun.", + "step3-message": "Çok az kaldı!", + "step4-message": "Acil Durum Kitinizi kayıt edin", + "step4-description1": "Eğer hesabınıza erişemezseniz, Acil Durum Kitiniz giriş yapmanın tek yoludur.", + "step4-description2": "Bunu indirmenizi ve güvenli bir ortamda saklamanızı öneriyoruz.", + "step4-description3": "Kaybetmeniz durumunda bizim dahi erişemeyeceğimiz veya kurtaramayacağımız Gizli Anahtarınızı barındırır.", + "step4-download": "PDF'yi indir", + "step5-send-invites": "Davetleri yolla", + "step5-invite-team": "Takımını davet et", + "step5-subtitle": "Infisical takım arkadaşlarınız ile kullanılmak üzere yapılmıştır. Birlikte test etmek için onları davet edin.", + "step5-skip": "Atla" +} \ No newline at end of file diff --git a/frontend/src/components/analytics/posthog.ts b/frontend/src/components/analytics/posthog.ts index aa6abf463..29208a795 100644 --- a/frontend/src/components/analytics/posthog.ts +++ b/frontend/src/components/analytics/posthog.ts @@ -5,6 +5,8 @@ import posthog from 'posthog-js'; import { ENV, POSTHOG_API_KEY, POSTHOG_HOST } from '../utilities/config'; export const initPostHog = () => { + // @ts-ignore + console.log("Init Infisical") try { if (typeof window !== 'undefined') { // @ts-ignore diff --git a/frontend/src/components/basic/dialog/AddUpdateEnvironmentDialog.tsx b/frontend/src/components/basic/dialog/AddUpdateEnvironmentDialog.tsx index fc216a35a..70e9b0f47 100644 --- a/frontend/src/components/basic/dialog/AddUpdateEnvironmentDialog.tsx +++ b/frontend/src/components/basic/dialog/AddUpdateEnvironmentDialog.tsx @@ -86,7 +86,7 @@ export const AddUpdateEnvironmentDialog = ({ leaveFrom='opacity-100 scale-100' leaveTo='opacity-0 scale-95' > - + - {currentPlan === STRIPE_PRODUCT_STARTER && ( + {currentPlan === plans.starter && (
+ +
+
+ + + + + + + ); +}; + +export default UpgradePlanModal; diff --git a/frontend/src/components/basic/table/EnvironmentsTable.tsx b/frontend/src/components/basic/table/EnvironmentsTable.tsx index 2a3b3fb0e..8ff7d9f0a 100644 --- a/frontend/src/components/basic/table/EnvironmentsTable.tsx +++ b/frontend/src/components/basic/table/EnvironmentsTable.tsx @@ -1,9 +1,13 @@ +import { useEffect, useState } from 'react'; import { faPencil, faPlus, faX } from '@fortawesome/free-solid-svg-icons'; +import { plans } from 'public/data/frequentConstants'; import { usePopUp } from '../../../hooks/usePopUp'; +import getOrganizationSubscriptions from '../../../pages/api/organization/GetOrgSubscription'; import Button from '../buttons/Button'; import { AddUpdateEnvironmentDialog } from '../dialog/AddUpdateEnvironmentDialog'; import DeleteActionModal from '../dialog/DeleteActionModal'; +import UpgradePlanModal from '../dialog/UpgradePlan'; type Env = { name: string; slug: string }; @@ -17,8 +21,24 @@ type Props = { const EnvironmentTable = ({ data = [], onCreateEnv, onDeleteEnv, onUpdateEnv }: Props) => { const { popUp, handlePopUpOpen, handlePopUpClose } = usePopUp([ 'createUpdateEnv', - 'deleteEnv' + 'deleteEnv', + 'upgradePlan' ] as const); + const [plan, setPlan] = useState(''); + const host = window.location.origin; + + useEffect(() => { + // on initial load - run auth check + (async () => { + const orgId = localStorage.getItem('orgData.id') as string; + const subscriptions = await getOrganizationSubscriptions({ + orgId + }); + setPlan(subscriptions.data[0].plan.product); + })(); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + const onEnvCreateCB = async (env: Env) => { try { @@ -63,7 +83,13 @@ const EnvironmentTable = ({ data = [], onCreateEnv, onDeleteEnv, onUpdateEnv }:
-
+
); diff --git a/frontend/src/components/v2/Button/Button.stories.tsx b/frontend/src/components/v2/Button/Button.stories.tsx index 0e78b9649..51e58d0da 100644 --- a/frontend/src/components/v2/Button/Button.stories.tsx +++ b/frontend/src/components/v2/Button/Button.stories.tsx @@ -1,3 +1,5 @@ +import { faPlus } from '@fortawesome/free-solid-svg-icons'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import type { Meta, StoryObj } from '@storybook/react'; import { Button } from './Button'; @@ -6,7 +8,16 @@ const meta: Meta = { title: 'Components/Button', component: Button, tags: ['v2'], - argTypes: {} + argTypes: { + isRounded: { + defaultValue: true, + type: 'boolean' + }, + isFullWidth: { + defaultValue: false, + type: 'boolean' + } + } }; export default meta; @@ -18,3 +29,61 @@ export const Primary: Story = { children: 'Hello Infisical' } }; + +export const Secondary: Story = { + args: { + children: 'Hello Infisical', + colorSchema: 'secondary', + variant: 'outline' + } +}; + +export const Danger: Story = { + args: { + children: 'Hello Infisical', + colorSchema: 'danger', + variant: 'solid' + } +}; + +export const Plain: Story = { + args: { + children: 'Hello Infisical', + variant: 'plain' + } +}; + +export const Disabled: Story = { + args: { + children: 'Hello Infisical', + disabled: true + } +}; + +export const FullWidth: Story = { + args: { + children: 'Hello Infisical', + isFullWidth: true + } +}; + +export const Loading: Story = { + args: { + children: 'Hello Infisical', + isLoading: true + } +}; + +export const LeftIcon: Story = { + args: { + children: 'Hello Infisical', + leftIcon: + } +}; + +export const RightIcon: Story = { + args: { + children: 'Hello Infisical', + rightIcon: + } +}; diff --git a/frontend/src/components/v2/Button/Button.tsx b/frontend/src/components/v2/Button/Button.tsx index a1edb26bf..21548d0e3 100644 --- a/frontend/src/components/v2/Button/Button.tsx +++ b/frontend/src/components/v2/Button/Button.tsx @@ -1,32 +1,166 @@ import { ButtonHTMLAttributes, forwardRef, ReactNode } from 'react'; +import { cva, VariantProps } from 'cva'; import { twMerge } from 'tailwind-merge'; type Props = { children: ReactNode; isDisabled?: boolean; + leftIcon?: ReactNode; + rightIcon?: ReactNode; // loading state isLoading?: boolean; - // various button sizes - size: 'sm' | 'md' | 'lg'; }; -export type ButtonProps = ButtonHTMLAttributes & Props; +const buttonVariants = cva( + [ + 'button', + 'transition-all', + 'font-inter font-medium', + 'cursor-pointer', + 'inline-flex items-center justify-center', + 'relative' + ], + { + variants: { + colorSchema: { + primary: ['bg-primary', 'text-black', 'border-primary hover:bg-opacity-80'], + secondary: ['bg-mineshaft', 'text-gray-300', 'border-mineshaft hover:bg-opacity-80'], + danger: ['bg-red', 'text-white', 'border-red'] + }, + variant: { + solid: '', + outline: ['bg-transparent', 'border-2', 'border-solid'], + plain: '' + }, + isDisabled: { + true: 'bg-opacity-70 cursor-not-allowed', + false: '' + }, + isFullWidth: { + true: 'w-full', + false: '' + }, + isRounded: { + true: 'rounded-md', + false: '' + }, + size: { + xs: ['text-xs', 'py-1', 'px-2'], + sm: ['text-sm', 'py-2', 'px-4'], + md: ['text-md', 'py-2', 'px-6'], + lg: ['text-lg', 'py-2', 'px-8'] + } + }, + compoundVariants: [ + { + colorSchema: 'primary', + variant: 'outline', + className: 'text-primary hover:bg-primary hover:text-black' + }, + { + colorSchema: 'secondary', + variant: 'outline', + className: 'hover:bg-mineshaft' + }, + { + colorSchema: 'danger', + variant: 'outline', + className: 'text-red hover:bg-red hover:text-black' + }, + { + colorSchema: 'primary', + variant: 'plain', + className: 'text-primary' + }, + { + colorSchema: 'secondary', + variant: 'plain', + className: 'text-mineshaft' + }, + { + colorSchema: 'danger', + variant: 'plain', + className: 'text-red' + }, + { + colorSchema: ['danger', 'primary', 'secondary'], + variant: ['plain'], + className: 'bg-transparent py-1 px-1' + } + ] + } +); + +export type ButtonProps = ButtonHTMLAttributes & + VariantProps & + Props; export const Button = forwardRef( - ({ children, isDisabled = false, className, ...props }, ref): JSX.Element => { + ( + { + children, + isDisabled = false, + className = '', + size = 'md', + variant = 'solid', + isFullWidth, + isRounded = true, + leftIcon, + rightIcon, + isLoading, + colorSchema = 'primary', + ...props + }, + ref + ): JSX.Element => { + const loadingToggleClass = isLoading ? 'opacity-0' : 'opacity-100'; + return ( ); } diff --git a/frontend/src/components/v2/Button/index.tsx b/frontend/src/components/v2/Button/index.tsx index fe9c53c51..9cad84da1 100644 --- a/frontend/src/components/v2/Button/index.tsx +++ b/frontend/src/components/v2/Button/index.tsx @@ -1 +1,2 @@ +export type { ButtonProps } from './Button'; export { Button } from './Button'; diff --git a/frontend/src/components/v2/Card/Card.stories.tsx b/frontend/src/components/v2/Card/Card.stories.tsx new file mode 100644 index 000000000..e21625cb4 --- /dev/null +++ b/frontend/src/components/v2/Card/Card.stories.tsx @@ -0,0 +1,40 @@ +import type { Meta, StoryObj } from '@storybook/react'; + +import { Card, CardBody, CardFooter, CardProps, CardTitle } from './Card'; + +const meta: Meta = { + title: 'Components/Card', + component: Card, + tags: ['v2'], + argTypes: { + isRounded: { + type: 'boolean', + defaultValue: true + } + } +}; + +export default meta; +type Story = StoryObj; + +// More on writing stories with args: https://storybook.js.org/docs/7.0/react/writing-stories/args +const Template = (args: CardProps) => ( +
+ + Title + Content + Footer + +
+); + +export const Basic: Story = { + render: (args) =>