From 2f1bd9ca611d63914a53653e6deefd84c3366a6c Mon Sep 17 00:00:00 2001 From: Afrie Irham Date: Wed, 5 Jul 2023 18:32:03 +0800 Subject: [PATCH 01/21] fix: enable user to press Enter in signup flow --- frontend/src/components/signup/CodeInputStep.tsx | 1 + frontend/src/components/signup/EnterEmailStep.tsx | 1 + frontend/src/components/signup/UserInfoStep.tsx | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/frontend/src/components/signup/CodeInputStep.tsx b/frontend/src/components/signup/CodeInputStep.tsx index dd765c1fc..7f6c75871 100644 --- a/frontend/src/components/signup/CodeInputStep.tsx +++ b/frontend/src/components/signup/CodeInputStep.tsx @@ -114,6 +114,7 @@ export default function CodeInputStep({
@@ -301,6 +300,7 @@ export default function UserInfoStep({
-
+ } From 93e0232c21000f7ba912caf99c848e7f1fb66367 Mon Sep 17 00:00:00 2001 From: Afrie Irham Date: Wed, 5 Jul 2023 19:02:48 +0800 Subject: [PATCH 03/21] fix: allow user to press Enter in forgot password page --- frontend/src/pages/verify-email.tsx | 31 ++++++++++++++++------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/frontend/src/pages/verify-email.tsx b/frontend/src/pages/verify-email.tsx index 33640dbc1..605c71da8 100644 --- a/frontend/src/pages/verify-email.tsx +++ b/frontend/src/pages/verify-email.tsx @@ -1,4 +1,4 @@ -import { useState } from "react"; +import { FormEvent, useState } from "react"; import Head from "next/head"; import Image from "next/image"; import Link from "next/link"; @@ -12,6 +12,7 @@ import { useFetchServerStatus } from "@app/hooks/api/serverDetails"; import SendEmailOnPasswordReset from "./api/auth/SendEmailOnPasswordReset"; export default function VerifyEmail() { + const [loading, setLoading] = useState(false); const [email, setEmail] = useState(""); const [step, setStep] = useState(1); const { data: serverDetails } = useFetchServerStatus(); @@ -27,6 +28,18 @@ export default function VerifyEmail() { } }; + const onSubmit = (e: FormEvent) => { + e.preventDefault(); + setLoading(true); + + if (serverDetails?.emailConfigured) { + sendVerificationEmail(); + } else { + handlePopUpOpen("setUpEmail"); + setLoading(false); + } + }; + return (
@@ -45,7 +58,7 @@ export default function VerifyEmail() {
{step === 1 && ( -
+

Forgot your password?

@@ -67,20 +80,10 @@ export default function VerifyEmail() {
-
-
+ )} {step === 2 && (
From 11a19eef0731003cb4d19e8a503ef9f97d8922db Mon Sep 17 00:00:00 2001 From: agoodman1999 Date: Thu, 6 Jul 2023 13:20:48 -0400 Subject: [PATCH 04/21] add --path flag to docs for infisical secrets set --- docs/cli/commands/secrets.mdx | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/docs/cli/commands/secrets.mdx b/docs/cli/commands/secrets.mdx index 3b1ccd3fb..67f09c542 100644 --- a/docs/cli/commands/secrets.mdx +++ b/docs/cli/commands/secrets.mdx @@ -90,6 +90,14 @@ $ infisical secrets set STRIPE_API_KEY=sjdgwkeudyjwe DOMAIN=example.com HASH=jeb Default value: `dev` + + Used to select the project folder in which the secrets will be set. Useful when creating new secrets under a particular path. + + ```bash + # Example + infisical secrets set DOMAIN=example.com --path /backend + ``` + From f9fca42c5bf17d4b03c27b5e8012749414dd0d4e Mon Sep 17 00:00:00 2001 From: agoodman1999 Date: Thu, 6 Jul 2023 13:36:15 -0400 Subject: [PATCH 05/21] fix incorrect leading slash in example --- docs/cli/commands/secrets.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/cli/commands/secrets.mdx b/docs/cli/commands/secrets.mdx index 67f09c542..24a8f596b 100644 --- a/docs/cli/commands/secrets.mdx +++ b/docs/cli/commands/secrets.mdx @@ -95,7 +95,7 @@ $ infisical secrets set STRIPE_API_KEY=sjdgwkeudyjwe DOMAIN=example.com HASH=jeb ```bash # Example - infisical secrets set DOMAIN=example.com --path /backend + infisical secrets set DOMAIN=example.com --path backend ``` From 7020c7aeabf30c1e38dfb441866ab0e50d48d5f8 Mon Sep 17 00:00:00 2001 From: Afrie Irham Date: Sun, 9 Jul 2023 15:08:25 +0800 Subject: [PATCH 06/21] fix: completing allow user to press Enter in forgot password flow --- frontend/src/pages/password-reset.tsx | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/frontend/src/pages/password-reset.tsx b/frontend/src/pages/password-reset.tsx index 4ce6d4004..30efc2c3b 100644 --- a/frontend/src/pages/password-reset.tsx +++ b/frontend/src/pages/password-reset.tsx @@ -1,6 +1,6 @@ import crypto from "crypto"; -import { useState } from "react"; +import { FormEvent, useState } from "react"; import Image from "next/image"; import { useRouter } from "next/router"; import { faCheck, faX } from "@fortawesome/free-solid-svg-icons"; @@ -24,6 +24,7 @@ const client = new jsrp.client(); export default function PasswordReset() { const [verificationToken, setVerificationToken] = useState(""); const [step, setStep] = useState(1); + const [loading, setLoading] = useState(false); const [backupKey, setBackupKey] = useState(""); const [privateKey, setPrivateKey] = useState(""); const [newPassword, setNewPassword] = useState(""); @@ -38,7 +39,8 @@ export default function PasswordReset() { const email = (parsedUrl.to as string)?.replace(" ", "+").trim(); // Unencrypt the private key with a backup key - const getEncryptedKeyHandler = async () => { + const getEncryptedKeyHandler = async (e: FormEvent) => { + e.preventDefault(); try { const result = await getBackupEncryptedPrivateKey({ verificationToken }); @@ -57,7 +59,8 @@ export default function PasswordReset() { }; // If everything is correct, reset the password - const resetPasswordHandler = async () => { + const resetPasswordHandler = async (e: FormEvent) => { + e.preventDefault(); const errorCheck = passwordCheck({ password: newPassword, setPasswordErrorLength, @@ -125,6 +128,7 @@ export default function PasswordReset() { if (response?.status === 200) { router.push("/login"); } + setLoading(false) }); } ); @@ -162,7 +166,7 @@ export default function PasswordReset() { // Input backup key const stepInputBackupKey = ( -
+

Enter your backup key

@@ -186,18 +190,19 @@ export default function PasswordReset() {
-
+ ); // Enter new password const stepEnterNewPassword = ( -
+

Enter new password

@@ -269,13 +274,15 @@ export default function PasswordReset() {
-
+ ); return ( From 93264fd2d07a0521d6bd867a862d8e7b01edfa70 Mon Sep 17 00:00:00 2001 From: Reza Rahemtola Date: Sun, 9 Jul 2023 15:40:59 +0200 Subject: [PATCH 07/21] docs: Fix wrong integration name --- docs/self-hosting/configuration/envars.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/self-hosting/configuration/envars.mdx b/docs/self-hosting/configuration/envars.mdx index ef9fc1fd0..fddf6f82e 100644 --- a/docs/self-hosting/configuration/envars.mdx +++ b/docs/self-hosting/configuration/envars.mdx @@ -105,7 +105,7 @@ Other environment variables are listed below to increase the functionality of yo - OAuth2 slug for Netlify integration + OAuth2 slug for Vercel integration From 5ef2508736a9717c6e7453651f23a01ec2eeb6dc Mon Sep 17 00:00:00 2001 From: Reza Rahemtola Date: Sun, 9 Jul 2023 15:44:25 +0200 Subject: [PATCH 08/21] docs: Add missing pull request contribution link --- docs/contributing/overview.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/contributing/overview.mdx b/docs/contributing/overview.mdx index 76475862d..f73422388 100644 --- a/docs/contributing/overview.mdx +++ b/docs/contributing/overview.mdx @@ -30,7 +30,7 @@ If you're ever in doubt about whether or not a proposed feature aligns with Infi ## Writing and submitting code Anyone can contribute code to Infisical. To get started, check out the [local development guide](/contributing/developing), make your changes, and submit a pull request to the main repository -adhering to the [pull request guide](/). +adhering to the [pull request guide](/contributing/pull-requests). ## Licensing From 63544648596ee1aaa964ac709165202f3e447c4d Mon Sep 17 00:00:00 2001 From: Maidul Islam Date: Sun, 9 Jul 2023 22:40:00 -0400 Subject: [PATCH 09/21] update terraform docs with path and env --- docs/integrations/frameworks/terraform.mdx | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/docs/integrations/frameworks/terraform.mdx b/docs/integrations/frameworks/terraform.mdx index 0826a833e..2643ca5af 100644 --- a/docs/integrations/frameworks/terraform.mdx +++ b/docs/integrations/frameworks/terraform.mdx @@ -44,10 +44,17 @@ provider "infisical" { ### 3. Fetch Infisical Secrets -Use the `infisical_secrets` data source to fetch your secrets. This is defined with an empty block `{}` as the provider automatically fetches all secrets associated with your service token. +Use the `infisical_secrets` data source to fetch your secrets. In this block, you must set the `env_slug` and `folder_path` to scope the secrets you want. + +`env_slug` is the slug of the environment name. This slug name can be found under the project settings page on the Infisical dashboard. + +`folder_path` is the path to the folder in a given environment. The path `/` for root of the environment where as `/folder1` is the folder at the root of the environment. ```hcl main.tf -data "infisical_secrets" "my-secrets" {} +data "infisical_secrets" "my-secrets" { + env_slug = "dev" + folder_path = "/some-folder/another-folder" +} ``` ### 4. Define Outputs From 13a81c9222e2f83acda803332a14d801946f923a Mon Sep 17 00:00:00 2001 From: Maidul Islam Date: Sun, 9 Jul 2023 23:25:35 -0400 Subject: [PATCH 10/21] add 401 error message for get secrets in cli --- cli/packages/api/api.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/cli/packages/api/api.go b/cli/packages/api/api.go index a94be0ab0..5afec6782 100644 --- a/cli/packages/api/api.go +++ b/cli/packages/api/api.go @@ -246,7 +246,11 @@ func CallGetSecretsV3(httpClient *resty.Client, request GetEncryptedSecretsV3Req } if response.IsError() { - return GetEncryptedSecretsV3Response{}, fmt.Errorf("CallGetSecretsV3: Unsuccessful response. Please make sure your secret path, workspace and environment name are all correct [response=%s]", response) + if response.StatusCode() == 401 { + return GetEncryptedSecretsV3Response{}, fmt.Errorf("CallGetSecretsV3: Request to access secrets with [environment=%v] [path=%v] [workspaceId=%v] is denied. Please check if your authentication method has access to requested scope", request.Environment, request.SecretPath, request.WorkspaceId) + } else { + return GetEncryptedSecretsV3Response{}, fmt.Errorf("CallGetSecretsV3: Unsuccessful response. Please make sure your secret path, workspace and environment name are all correct [response=%v]", response.RawResponse) + } } return secretsResponse, nil From 34fef4aaadf05d4b7f409dc55b3ef09192e61dde Mon Sep 17 00:00:00 2001 From: Juned Khan Date: Mon, 10 Jul 2023 12:16:51 +0530 Subject: [PATCH 11/21] Implemented feature to remove the trailing slash from the domain url --- cli/packages/cmd/login.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/cli/packages/cmd/login.go b/cli/packages/cmd/login.go index c629130a4..f8d397233 100644 --- a/cli/packages/cmd/login.go +++ b/cli/packages/cmd/login.go @@ -73,7 +73,6 @@ var loginCmd = &cobra.Command{ return } } - //override domain domainQuery := true if config.INFISICAL_URL_MANUAL_OVERRIDE != "" && config.INFISICAL_URL_MANUAL_OVERRIDE != util.INFISICAL_DEFAULT_API_URL { @@ -322,6 +321,8 @@ func DomainOverridePrompt() (bool, error) { ) options := []string{PRESET, OVERRIDE} + //trim the '/' from the end of the domain url + config.INFISICAL_URL_MANUAL_OVERRIDE = strings.TrimRight(config.INFISICAL_URL_MANUAL_OVERRIDE, "/") optionsPrompt := promptui.Select{ Label: fmt.Sprintf("Current INFISICAL_API_URL Domain Override: %s", config.INFISICAL_URL_MANUAL_OVERRIDE), Items: options, @@ -380,7 +381,8 @@ func askForDomain() error { if err != nil { return err } - + //trimmed the '/' from the end of the self hosting url + domain = strings.TrimRight(domain, "/") //set api and login url config.INFISICAL_URL = fmt.Sprintf("%s/api", domain) config.INFISICAL_LOGIN_URL = fmt.Sprintf("%s/login", domain) From e91e7f96c2753c604de4c90f5074dc42e3cab9db Mon Sep 17 00:00:00 2001 From: Tuan Dang Date: Mon, 10 Jul 2023 13:48:46 +0700 Subject: [PATCH 12/21] Update free plan logic --- .../controllers/v1/organizationsController.ts | 24 +++++++ backend/src/ee/routes/v1/organizations.ts | 15 +++++ backend/src/ee/services/EELicenseService.ts | 12 +++- .../v2/UpgradePlanModal/UpgradePlanModal.tsx | 63 ++++++++++++++----- frontend/src/hooks/api/organization/index.ts | 4 +- .../src/hooks/api/organization/queries.tsx | 24 ++++++- frontend/src/hooks/api/organization/types.ts | 5 ++ frontend/src/hooks/api/subscriptions/types.ts | 1 + .../AppLayout/components/NavBar/NavBar.tsx | 31 ++++++--- .../BillingCloudTab/PreviewSection.tsx | 33 ++++++++-- 10 files changed, 180 insertions(+), 32 deletions(-) diff --git a/backend/src/ee/controllers/v1/organizationsController.ts b/backend/src/ee/controllers/v1/organizationsController.ts index fb13a6575..652fc4b32 100644 --- a/backend/src/ee/controllers/v1/organizationsController.ts +++ b/backend/src/ee/controllers/v1/organizationsController.ts @@ -27,6 +27,30 @@ export const getOrganizationPlan = async (req: Request, res: Response) => { }); } +/** + * Return checkout url for pro trial + * @param req + * @param res + * @returns + */ +export const startOrganizationTrial = async (req: Request, res: Response) => { + const { organizationId } = req.params; + const { success_url } = req.body; + + const { data: { url } } = await licenseServerKeyRequest.post( + `${await getLicenseServerUrl()}/api/license-server/v1/customers/${req.organization.customerId}/session/trial`, + { + success_url + } + ); + + EELicenseService.delPlan(organizationId); + + return res.status(200).send({ + url + }); +} + /** * Return the organization's current plan's billing info * @param req diff --git a/backend/src/ee/routes/v1/organizations.ts b/backend/src/ee/routes/v1/organizations.ts index 37be3a96d..c9104d964 100644 --- a/backend/src/ee/routes/v1/organizations.ts +++ b/backend/src/ee/routes/v1/organizations.ts @@ -41,6 +41,21 @@ router.get( organizationsController.getOrganizationPlan ); +router.post( + "/:organizationId/session/trial", + requireAuth({ + acceptedAuthModes: ["jwt"], + }), + requireOrganizationAuth({ + acceptedRoles: [OWNER, ADMIN, MEMBER], + acceptedStatuses: [ACCEPTED], + }), + param("organizationId").exists().trim(), + body("success_url").exists().trim(), + validateRequest, + organizationsController.startOrganizationTrial +); + router.get( "/:organizationId/plan/billing", requireAuth({ diff --git a/backend/src/ee/services/EELicenseService.ts b/backend/src/ee/services/EELicenseService.ts index b4bb97753..88220933d 100644 --- a/backend/src/ee/services/EELicenseService.ts +++ b/backend/src/ee/services/EELicenseService.ts @@ -32,6 +32,7 @@ interface FeatureSet { auditLogs: boolean; status: 'incomplete' | 'incomplete_expired' | 'trialing' | 'active' | 'past_due' | 'canceled' | 'unpaid' | null; trial_end: number | null; + has_used_trial: boolean; } /** @@ -63,7 +64,8 @@ class EELicenseService { customAlerts: true, auditLogs: false, status: null, - trial_end: null + trial_end: null, + has_used_trial: true } public localFeatureSet: NodeCache; @@ -71,7 +73,7 @@ class EELicenseService { constructor() { this._isLicenseValid = true; this.localFeatureSet = new NodeCache({ - stdTTL: 300, + stdTTL: 60, }); } @@ -112,6 +114,12 @@ class EELicenseService { await this.getPlan(organizationId, workspaceId); } } + + public async delPlan(organizationId: string) { + if (this.instanceType === "cloud") { + this.localFeatureSet.del(`${organizationId}-`); + } + } public async initGlobalFeatureSet() { const licenseServerKey = await getLicenseServerKey(); diff --git a/frontend/src/components/v2/UpgradePlanModal/UpgradePlanModal.tsx b/frontend/src/components/v2/UpgradePlanModal/UpgradePlanModal.tsx index 968f131bc..e09d35920 100644 --- a/frontend/src/components/v2/UpgradePlanModal/UpgradePlanModal.tsx +++ b/frontend/src/components/v2/UpgradePlanModal/UpgradePlanModal.tsx @@ -1,9 +1,11 @@ import Link from "next/link"; - import { useSubscription } from "@app/context"; - -import { Button } from "../Button"; +import { Button } from "@app/components/v2"; import { Modal, ModalClose, ModalContent } from "../Modal"; +import { useOrganization } from "@app/context"; +import { + useGetOrgTrialUrl +} from "@app/hooks/api"; type Props = { isOpen?: boolean; @@ -13,32 +15,61 @@ type Props = { export const UpgradePlanModal = ({ text, isOpen, onOpenChange }: Props): JSX.Element => { const { subscription } = useSubscription(); + const { currentOrg } = useOrganization(); + const { mutateAsync, isLoading } = useGetOrgTrialUrl(); const link = (subscription && subscription.slug !== null) ? `/settings/billing/${localStorage.getItem("projectData.id") as string}` : "https://infisical.com/scheduledemo"; + const handleUpgradeBtnClick = async () => { + try { + if (!subscription || !currentOrg) return; + + if (!subscription.has_used_trial) { + // direct user to start pro trial + + const url = await mutateAsync({ + orgId: currentOrg._id, + success_url: window.location.href + }); + + window.location.href = url; + } else { + // direct user to upgrade their plan + window.location.href = link; + } + + } catch (err) { + console.error(err); + } + } + return ( - - , - - - - ]} >

{text}

Upgrade and get access to this, as well as to other powerful enhancements.

+
+ + +
) diff --git a/frontend/src/hooks/api/organization/index.ts b/frontend/src/hooks/api/organization/index.ts index cffa80d63..d523e1c04 100644 --- a/frontend/src/hooks/api/organization/index.ts +++ b/frontend/src/hooks/api/organization/index.ts @@ -13,4 +13,6 @@ export { useGetOrgPmtMethods, useGetOrgTaxIds, useRenameOrg, - useUpdateOrgBillingDetails} from "./queries"; + useGetOrgTrialUrl, + useUpdateOrgBillingDetails +} from "./queries"; diff --git a/frontend/src/hooks/api/organization/queries.tsx b/frontend/src/hooks/api/organization/queries.tsx index d3f161f64..293ad7022 100644 --- a/frontend/src/hooks/api/organization/queries.tsx +++ b/frontend/src/hooks/api/organization/queries.tsx @@ -10,8 +10,10 @@ import { PlanBillingInfo, PmtMethod, ProductsTable, - RenameOrgDTO, - TaxID} from "./types"; + RenameOrgDTO, + GetOrgTrialUrlDTO, + TaxID +} from "./types"; const organizationKeys = { getUserOrganization: ["organization"] as const, @@ -47,6 +49,24 @@ export const useRenameOrg = () => { }); }; +export const useGetOrgTrialUrl = () => { + return useMutation({ + mutationFn: async ({ + orgId, + success_url + }: { + orgId: string; + success_url: string; + }) => { + const { data: { url } } = await apiRequest.post(`/api/v1/organizations/${orgId}/session/trial`, { + success_url + }) + + return url; + } + }); +}; + export const useGetOrgPlanBillingInfo = (organizationId: string) => { return useQuery({ queryKey: organizationKeys.getOrgPlanBillingInfo(organizationId), diff --git a/frontend/src/hooks/api/organization/types.ts b/frontend/src/hooks/api/organization/types.ts index a33a7f875..b2573400b 100644 --- a/frontend/src/hooks/api/organization/types.ts +++ b/frontend/src/hooks/api/organization/types.ts @@ -10,6 +10,11 @@ export type RenameOrgDTO = { newOrgName: string; }; +export type GetOrgTrialUrlDTO = { + orgId: string; + success_url: string; +} + export type BillingDetails = { name: string; email: string; diff --git a/frontend/src/hooks/api/subscriptions/types.ts b/frontend/src/hooks/api/subscriptions/types.ts index ca50255c8..d3d673764 100644 --- a/frontend/src/hooks/api/subscriptions/types.ts +++ b/frontend/src/hooks/api/subscriptions/types.ts @@ -15,4 +15,5 @@ export type SubscriptionPlan = { environmentLimit: number; status: "incomplete" | "incomplete_expired" | "trialing" | "active" | "past_due" | "canceled" | "unpaid" | null; trial_end: number | null; + has_used_trial: boolean; }; diff --git a/frontend/src/layouts/AppLayout/components/NavBar/NavBar.tsx b/frontend/src/layouts/AppLayout/components/NavBar/NavBar.tsx index b263a25ff..52fa0ba5b 100644 --- a/frontend/src/layouts/AppLayout/components/NavBar/NavBar.tsx +++ b/frontend/src/layouts/AppLayout/components/NavBar/NavBar.tsx @@ -22,7 +22,10 @@ import {TFunction} from "i18next"; import guidGenerator from "@app/components/utilities/randomId"; import { useOrganization, useSubscription,useUser } from "@app/context"; -import { useLogoutUser } from "@app/hooks/api"; +import { + useLogoutUser, + useGetOrgTrialUrl +} from "@app/hooks/api"; const supportOptions = (t: TFunction) => [ [ @@ -67,6 +70,7 @@ export const Navbar = () => { const { subscription } = useSubscription(); const { currentOrg, orgs } = useOrganization(); + const { mutateAsync, isLoading } = useGetOrgTrialUrl(); const { user } = useUser(); const logout = useLogoutUser(); @@ -346,12 +350,25 @@ export const Navbar = () => {
- {subscription && subscription.status === "trialing" && subscription.trial_end && ( -
-

- {`Currently trialing the ${formatPlanSlug(subscription.slug)} plan until ${formatDate(subscription.trial_end).formattedDate} - ${formatDate(subscription.trial_end).remainingDays} day(s) left. `} - Add a card to avoid being downgraded to the Starter plan afterward → -

+ {subscription && subscription.slug === "starter" && !subscription.has_used_trial && ( +
+
)}
diff --git a/frontend/src/views/Settings/BillingSettingsPage/components/BillingCloudTab/PreviewSection.tsx b/frontend/src/views/Settings/BillingSettingsPage/components/BillingCloudTab/PreviewSection.tsx index 23a4be24d..cccbfaf2e 100644 --- a/frontend/src/views/Settings/BillingSettingsPage/components/BillingCloudTab/PreviewSection.tsx +++ b/frontend/src/views/Settings/BillingSettingsPage/components/BillingCloudTab/PreviewSection.tsx @@ -2,7 +2,9 @@ import { Button } from "@app/components/v2"; import { useOrganization,useSubscription } from "@app/context"; import { useCreateCustomerPortalSession, - useGetOrgPlanBillingInfo} from "@app/hooks/api"; + useGetOrgPlanBillingInfo, + useGetOrgTrialUrl +} from "@app/hooks/api"; import { usePopUp } from "@app/hooks/usePopUp"; import { ManagePlansModal } from "./ManagePlansModal"; @@ -11,6 +13,7 @@ export const PreviewSection = () => { const { currentOrg } = useOrganization(); const { subscription, isLoading: isSubscriptionLoading } = useSubscription(); const { data, isLoading } = useGetOrgPlanBillingInfo(currentOrg?._id ?? ""); + const getOrgTrialUrl = useGetOrgTrialUrl(); const createCustomerPortalSession = useCreateCustomerPortalSession(); const { popUp, handlePopUpOpen, handlePopUpToggle } = usePopUp([ @@ -42,19 +45,41 @@ export const PreviewSection = () => { .replace(/-/g, " "); } + const handleUpgradeBtnClick = async () => { + try { + if (!subscription || !currentOrg) return; + + if (!subscription.has_used_trial) { + // direct user to start pro trial + const url = await getOrgTrialUrl.mutateAsync({ + orgId: currentOrg._id, + success_url: window.location.href + }); + + window.location.href = url; + } else { + // open compare plans modal + handlePopUpOpen("managePlan"); + } + } catch (err) { + console.error(err); + } + } + return (
- {!isSubscriptionLoading && subscription?.slug !== "enterprise" && subscription?.slug !== "pro" && subscription?.slug !== "pro-annual" && ( + {subscription && subscription?.slug !== "enterprise" && subscription?.slug !== "pro" && subscription?.slug !== "pro-annual" && (

Become Infisical

Unlimited members, projects, RBAC, smart alerts, and so much more

)} From 9e5b9cbdb5c93b30ee35113e8636848df2b84b90 Mon Sep 17 00:00:00 2001 From: Tuan Dang Date: Mon, 10 Jul 2023 15:06:00 +0700 Subject: [PATCH 13/21] Fix lint errors --- .../v2/UpgradePlanModal/UpgradePlanModal.tsx | 9 ++--- frontend/src/hooks/api/organization/index.ts | 2 +- .../src/hooks/api/organization/queries.tsx | 1 - frontend/src/hooks/api/organization/types.ts | 5 --- .../AppLayout/components/NavBar/NavBar.tsx | 39 ++----------------- .../BillingCloudTab/PreviewSection.tsx | 2 +- 6 files changed, 9 insertions(+), 49 deletions(-) diff --git a/frontend/src/components/v2/UpgradePlanModal/UpgradePlanModal.tsx b/frontend/src/components/v2/UpgradePlanModal/UpgradePlanModal.tsx index e09d35920..bf97b6750 100644 --- a/frontend/src/components/v2/UpgradePlanModal/UpgradePlanModal.tsx +++ b/frontend/src/components/v2/UpgradePlanModal/UpgradePlanModal.tsx @@ -1,12 +1,11 @@ -import Link from "next/link"; -import { useSubscription } from "@app/context"; -import { Button } from "@app/components/v2"; -import { Modal, ModalClose, ModalContent } from "../Modal"; -import { useOrganization } from "@app/context"; +import { useOrganization, useSubscription } from "@app/context"; import { useGetOrgTrialUrl } from "@app/hooks/api"; +import { Button } from "../Button"; +import { Modal, ModalContent } from "../Modal"; + type Props = { isOpen?: boolean; onOpenChange?: (isOpen: boolean) => void; diff --git a/frontend/src/hooks/api/organization/index.ts b/frontend/src/hooks/api/organization/index.ts index d523e1c04..847fb4bb9 100644 --- a/frontend/src/hooks/api/organization/index.ts +++ b/frontend/src/hooks/api/organization/index.ts @@ -12,7 +12,7 @@ export { useGetOrgPlanTable, useGetOrgPmtMethods, useGetOrgTaxIds, - useRenameOrg, useGetOrgTrialUrl, + useRenameOrg, useUpdateOrgBillingDetails } from "./queries"; diff --git a/frontend/src/hooks/api/organization/queries.tsx b/frontend/src/hooks/api/organization/queries.tsx index 293ad7022..3bbb82412 100644 --- a/frontend/src/hooks/api/organization/queries.tsx +++ b/frontend/src/hooks/api/organization/queries.tsx @@ -11,7 +11,6 @@ import { PmtMethod, ProductsTable, RenameOrgDTO, - GetOrgTrialUrlDTO, TaxID } from "./types"; diff --git a/frontend/src/hooks/api/organization/types.ts b/frontend/src/hooks/api/organization/types.ts index b2573400b..a33a7f875 100644 --- a/frontend/src/hooks/api/organization/types.ts +++ b/frontend/src/hooks/api/organization/types.ts @@ -10,11 +10,6 @@ export type RenameOrgDTO = { newOrgName: string; }; -export type GetOrgTrialUrlDTO = { - orgId: string; - success_url: string; -} - export type BillingDetails = { name: string; email: string; diff --git a/frontend/src/layouts/AppLayout/components/NavBar/NavBar.tsx b/frontend/src/layouts/AppLayout/components/NavBar/NavBar.tsx index 52fa0ba5b..7c313b0e9 100644 --- a/frontend/src/layouts/AppLayout/components/NavBar/NavBar.tsx +++ b/frontend/src/layouts/AppLayout/components/NavBar/NavBar.tsx @@ -3,7 +3,6 @@ import { Fragment, useMemo } from "react"; import { useTranslation } from "react-i18next"; import Image from "next/image"; -import Link from "next/link"; import { useRouter } from "next/router"; import { faGithub, faSlack } from "@fortawesome/free-brands-svg-icons"; import { faCircleQuestion } from "@fortawesome/free-regular-svg-icons"; @@ -23,9 +22,8 @@ import {TFunction} from "i18next"; import guidGenerator from "@app/components/utilities/randomId"; import { useOrganization, useSubscription,useUser } from "@app/context"; import { - useLogoutUser, - useGetOrgTrialUrl -} from "@app/hooks/api"; + useGetOrgTrialUrl, + useLogoutUser} from "@app/hooks/api"; const supportOptions = (t: TFunction) => [ [ @@ -70,7 +68,7 @@ export const Navbar = () => { const { subscription } = useSubscription(); const { currentOrg, orgs } = useOrganization(); - const { mutateAsync, isLoading } = useGetOrgTrialUrl(); + const { mutateAsync } = useGetOrgTrialUrl(); const { user } = useUser(); const logout = useLogoutUser(); @@ -100,37 +98,6 @@ export const Navbar = () => { } }; - function formatPlanSlug(slug: string) { - return slug - .replace(/(\b[a-z])/g, match => match.toUpperCase()) - .replace(/-/g, " "); - } - - const calculateRemainingDays = (date: number) => { - const now = new Date(); - const endDate = new Date(date * 1000); - - const differenceInTime = endDate.getTime() - now.getTime(); - const differenceInDays = Math.ceil(differenceInTime / (1000 * 3600 * 24)); - - return differenceInDays; - } - - const formatDate = (date: number) => { - const endDate = new Date(date * 1000); - const day: number = endDate.getDate(); - const month: number = endDate.getMonth() + 1; - const year: number = endDate.getFullYear(); - - const formattedDate: string = `${day}/${month}/${year}`; - const remainingDays: number = calculateRemainingDays(date); - - return { - formattedDate, - remainingDays - }; - } - return (
diff --git a/frontend/src/views/Settings/BillingSettingsPage/components/BillingCloudTab/PreviewSection.tsx b/frontend/src/views/Settings/BillingSettingsPage/components/BillingCloudTab/PreviewSection.tsx index cccbfaf2e..20791e0e6 100644 --- a/frontend/src/views/Settings/BillingSettingsPage/components/BillingCloudTab/PreviewSection.tsx +++ b/frontend/src/views/Settings/BillingSettingsPage/components/BillingCloudTab/PreviewSection.tsx @@ -11,7 +11,7 @@ import { ManagePlansModal } from "./ManagePlansModal"; export const PreviewSection = () => { const { currentOrg } = useOrganization(); - const { subscription, isLoading: isSubscriptionLoading } = useSubscription(); + const { subscription } = useSubscription(); const { data, isLoading } = useGetOrgPlanBillingInfo(currentOrg?._id ?? ""); const getOrgTrialUrl = useGetOrgTrialUrl(); const createCustomerPortalSession = useCreateCustomerPortalSession(); From 9713a1940580aeceb91632ef71a6726e81b8571c Mon Sep 17 00:00:00 2001 From: Maidul Islam Date: Mon, 10 Jul 2023 23:14:10 -0400 Subject: [PATCH 14/21] add semvar to k8 images --- .github/workflows/release_docker_k8_operator.yaml | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/.github/workflows/release_docker_k8_operator.yaml b/.github/workflows/release_docker_k8_operator.yaml index 788d414b6..1d07ada0d 100644 --- a/.github/workflows/release_docker_k8_operator.yaml +++ b/.github/workflows/release_docker_k8_operator.yaml @@ -1,10 +1,16 @@ -name: Release Docker image for K8 operator -on: [workflow_dispatch] +name: Release Docker image for K8 operator +on: + push: + tags: + - "infisical-k8-operator/v*.*.*" jobs: release: runs-on: ubuntu-latest steps: + - name: Extract version from tag + id: extract_version + run: echo "::set-output name=version::${GITHUB_REF_NAME#infisical/}" - uses: actions/checkout@v2 - name: 🔧 Set up QEMU @@ -26,4 +32,6 @@ jobs: context: k8-operator push: true platforms: linux/amd64,linux/arm64 - tags: infisical/kubernetes-operator:latest \ No newline at end of file + tags: | + infisical/kubernetes-operator:latest + infisical/backend:${{ steps.extract_version.outputs.version }} From 264f75ce8e19797f875dff960f6dd93cb6648184 Mon Sep 17 00:00:00 2001 From: Maidul Islam Date: Mon, 10 Jul 2023 23:20:45 -0400 Subject: [PATCH 15/21] correct gha for k8 operator --- .github/workflows/release_docker_k8_operator.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release_docker_k8_operator.yaml b/.github/workflows/release_docker_k8_operator.yaml index 1d07ada0d..694104745 100644 --- a/.github/workflows/release_docker_k8_operator.yaml +++ b/.github/workflows/release_docker_k8_operator.yaml @@ -34,4 +34,4 @@ jobs: platforms: linux/amd64,linux/arm64 tags: | infisical/kubernetes-operator:latest - infisical/backend:${{ steps.extract_version.outputs.version }} + infisical/kubernetes-operator:${{ steps.extract_version.outputs.version }} From 07d25cb6733e51cd93e4f97d76d05a63e4f77d52 Mon Sep 17 00:00:00 2001 From: Maidul Islam Date: Mon, 10 Jul 2023 23:26:14 -0400 Subject: [PATCH 16/21] extract version from tag --- .github/workflows/release_docker_k8_operator.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release_docker_k8_operator.yaml b/.github/workflows/release_docker_k8_operator.yaml index 694104745..517549ea8 100644 --- a/.github/workflows/release_docker_k8_operator.yaml +++ b/.github/workflows/release_docker_k8_operator.yaml @@ -10,7 +10,7 @@ jobs: steps: - name: Extract version from tag id: extract_version - run: echo "::set-output name=version::${GITHUB_REF_NAME#infisical/}" + run: echo "::set-output name=version::${GITHUB_REF_NAME#infisical-k8-operator/}" - uses: actions/checkout@v2 - name: 🔧 Set up QEMU From 3e3bbe298d2eaf91c9fc0b40503bf64f489f2f29 Mon Sep 17 00:00:00 2001 From: Tuan Dang Date: Tue, 11 Jul 2023 14:50:41 +0700 Subject: [PATCH 17/21] Add support for Office365 SMTP --- backend/src/services/smtp.ts | 16 +++++++++++--- backend/src/variables/smtp.ts | 1 + docs/self-hosting/configuration/email.mdx | 27 +++++++++++++++++++---- 3 files changed, 37 insertions(+), 7 deletions(-) diff --git a/backend/src/services/smtp.ts b/backend/src/services/smtp.ts index 4bd58020b..b067d499a 100644 --- a/backend/src/services/smtp.ts +++ b/backend/src/services/smtp.ts @@ -2,9 +2,10 @@ import nodemailer from "nodemailer"; import { SMTP_HOST_GMAIL, SMTP_HOST_MAILGUN, + SMTP_HOST_OFFICE365, SMTP_HOST_SENDGRID, SMTP_HOST_SOCKETLABS, - SMTP_HOST_ZOHOMAIL, + SMTP_HOST_ZOHOMAIL } from "../variables"; import SMTPConnection from "nodemailer/lib/smtp-connection"; import * as Sentry from "@sentry/node"; @@ -15,6 +16,7 @@ import { getSmtpSecure, getSmtpUsername, } from "../config"; +import { getLogger } from "../utils/logger"; export const initSmtp = async () => { const mailOpts: SMTPConnection.Options = { @@ -58,6 +60,12 @@ export const initSmtp = async () => { ciphers: "TLSv1.2", } break; + case SMTP_HOST_OFFICE365: + mailOpts.requireTLS = true; + mailOpts.tls = { + ciphers: "TLSv1.2" + } + break; default: if ((await getSmtpHost()).includes("amazonaws.com")) { mailOpts.tls = { @@ -73,10 +81,12 @@ export const initSmtp = async () => { const transporter = nodemailer.createTransport(mailOpts); transporter .verify() - .then((err) => { + .then(async () => { Sentry.setUser(null); Sentry.captureMessage("SMTP - Successfully connected"); - console.log("SMTP - Successfully connected") + (await getLogger("backend-main")).info( + "SMTP - Successfully connected" + ); }) .catch(async (err) => { Sentry.setUser(null); diff --git a/backend/src/variables/smtp.ts b/backend/src/variables/smtp.ts index 8a0e752eb..4ad68c356 100644 --- a/backend/src/variables/smtp.ts +++ b/backend/src/variables/smtp.ts @@ -3,3 +3,4 @@ export const SMTP_HOST_MAILGUN = "smtp.mailgun.org"; export const SMTP_HOST_SOCKETLABS = "smtp.socketlabs.com"; export const SMTP_HOST_ZOHOMAIL = "smtp.zoho.com"; export const SMTP_HOST_GMAIL = "smtp.gmail.com"; +export const SMTP_HOST_OFFICE365 = "smtp.office365.com"; \ No newline at end of file diff --git a/docs/self-hosting/configuration/email.mdx b/docs/self-hosting/configuration/email.mdx index 4c6e13a49..15797d73b 100644 --- a/docs/self-hosting/configuration/email.mdx +++ b/docs/self-hosting/configuration/email.mdx @@ -3,12 +3,12 @@ title: "Configure email service" description: "How to configure your email when self-hosting Infisical." --- -By default, the core functions of Infisical work without any email service configuration. Without email service, basic sign up/login and secret operations will function without any issue. +By default, the core functions of Infisical work without any email service configuration. Without email service, basic sign up/login and secret operations will function without any issue. However, the following functionality will be disabled. -- Multi-factor authentication +- Multi-factor authentication - Sending invite links via email for projects to teammates -- Sending alerts such as suspicious login attempts +- Sending alerts such as suspicious login attempts ## General configuration @@ -157,11 +157,30 @@ SMTP_FROM_NAME=Infisical As per the [notice](https://support.google.com/accounts/answer/6010255?hl=en) by Google, you should note that using Gmail credentials for SMTP configuration will only work for Google Workspace or Google Cloud Identity customers as of May 30, 2022. - Put differently, the SMTP configuration is only possible with business (not personal) Gmail credentials. +Put differently, the SMTP configuration is only possible with business (not personal) Gmail credentials. + + + +1. Create an account and configure [Office365](https://www.office.com/) to send emails. + +2. With your login credentials, you can now set up your SMTP environment variables: + +``` +SMTP_HOST=smtp.office365.com +SMTP_USERNAME=username@yourdomain.com # your username +SMTP_PASSWORD=password # your password +SMTP_PORT=587 +SMTP_SECURE=true +SMTP_FROM_ADDRESS=username@yourdomain.com +SMTP_FROM_NAME=Infisical +``` + + + 1. Create an account and configure [Zoho Mail](https://www.zoho.com/mail/) to send emails. From 9c1f88bb9c80defb26a9462fab466ffbf68fd2f6 Mon Sep 17 00:00:00 2001 From: vmatsiiako <78047717+vmatsiiako@users.noreply.github.com> Date: Tue, 11 Jul 2023 13:49:55 -0700 Subject: [PATCH 18/21] Update mint.json --- docs/mint.json | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/mint.json b/docs/mint.json index 25db15c63..d1175c9e1 100644 --- a/docs/mint.json +++ b/docs/mint.json @@ -21,6 +21,10 @@ "to": "#F8B7BD" } }, + "feedback": { + "suggestEdit": true, + "raiseIssue": true + }, "api": { "baseUrl": ["https://app.infisical.com", "http://localhost:8080"], "auth": { From d3a47ffcddfa183e6dd4d94a59b5e78b4b87168c Mon Sep 17 00:00:00 2001 From: vmatsiiako <78047717+vmatsiiako@users.noreply.github.com> Date: Tue, 11 Jul 2023 13:56:24 -0700 Subject: [PATCH 19/21] Update mint.json --- docs/mint.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/mint.json b/docs/mint.json index d1175c9e1..aa988d593 100644 --- a/docs/mint.json +++ b/docs/mint.json @@ -22,8 +22,8 @@ } }, "feedback": { - "suggestEdit": true, - "raiseIssue": true + "suggestEdit": "true", + "raiseIssue": "true" }, "api": { "baseUrl": ["https://app.infisical.com", "http://localhost:8080"], From e1764880a2c02c96ba05aa83ee4b046b14e4bdff Mon Sep 17 00:00:00 2001 From: vmatsiiako <78047717+vmatsiiako@users.noreply.github.com> Date: Tue, 11 Jul 2023 14:09:57 -0700 Subject: [PATCH 20/21] Update overview.mdx --- docs/changelog/overview.mdx | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/docs/changelog/overview.mdx b/docs/changelog/overview.mdx index 7acab93c6..3ff0736f4 100644 --- a/docs/changelog/overview.mdx +++ b/docs/changelog/overview.mdx @@ -4,6 +4,21 @@ title: "Changelog" The changelog below reflects new product developments and updates on a monthly basis; it will be updated later this quarter to include issues-addressed on a weekly basis. +## July 2023 + +- Released [secret referencing](https://infisical.com/docs/documentation/platform/secret-reference) across folders and environments. +- Added the [intergation with Laravel Forge](https://infisical.com/docs/integrations/cloud/laravel-forge). +- Redesigned the project/organization experience. + +## June 2023 + +- Released the [Terraform Provider](https://infisical.com/docs/integrations/frameworks/terraform#5-run-terraform). +- Updated the usage and billing page. Added the free trial for the professional tier. +- Added the intergation with [Checkly](https://infisical.com/docs/integrations/cloud/checkly), [Hashicorp Vault](https://infisical.com/docs/integrations/cloud/hashicorp-vault), and [Cloudflare Pages](https://infisical.com/docs/integrations/cloud/cloudflare-pages). +- Comleted a penetration test with a `very good` result. +- Added support for multi-line secrets. + + ## May 2023 - Released secret scanning capability for the CLI. @@ -11,8 +26,7 @@ The changelog below reflects new product developments and updates on a monthly b - Completed penetration test. - Released new landing page. - Started SOC 2 (Type II) compliance certification preparation. - -More coming soon. +- Released new deployment options for Fly.io, Digital Ocean and Render. ## April 2023 @@ -107,4 +121,4 @@ More coming soon. - Added search bar to dashboard to query for keys on client-side. - Added capability to rename a project. - Added user roles for projects. -- Added incident contacts. \ No newline at end of file +- Added incident contacts. From 0b52b3cf5892b880b21255ed2ff2ab93c9b716e4 Mon Sep 17 00:00:00 2001 From: vmatsiiako <78047717+vmatsiiako@users.noreply.github.com> Date: Tue, 11 Jul 2023 14:14:23 -0700 Subject: [PATCH 21/21] Update mint.json --- docs/mint.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/mint.json b/docs/mint.json index aa988d593..d1175c9e1 100644 --- a/docs/mint.json +++ b/docs/mint.json @@ -22,8 +22,8 @@ } }, "feedback": { - "suggestEdit": "true", - "raiseIssue": "true" + "suggestEdit": true, + "raiseIssue": true }, "api": { "baseUrl": ["https://app.infisical.com", "http://localhost:8080"],