Merge remote-tracking branch 'origin' into service-token-v3
@@ -160,7 +160,7 @@ export const getIntegrationAuthAccessHelper = async ({
|
||||
let accessId;
|
||||
let accessToken;
|
||||
const integrationAuth = await IntegrationAuth.findById(integrationAuthId).select(
|
||||
"workspace integration +accessCiphertext +accessIV +accessTag +accessExpiresAt +refreshCiphertext +refreshIV +refreshTag +accessIdCiphertext +accessIdIV +accessIdTag metadata"
|
||||
"workspace integration +accessCiphertext +accessIV +accessTag +accessExpiresAt +refreshCiphertext +refreshIV +refreshTag +accessIdCiphertext +accessIdIV +accessIdTag metadata teamId"
|
||||
);
|
||||
|
||||
if (!integrationAuth)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Document, Schema, Types, model } from "mongoose";
|
||||
import {
|
||||
import {
|
||||
ALGORITHM_AES_256_GCM,
|
||||
ENCODING_SCHEME_BASE64,
|
||||
ENCODING_SCHEME_UTF8,
|
||||
@@ -53,4 +53,6 @@ const secretBlindIndexDataSchema = new Schema<ISecretBlindIndexData>(
|
||||
}
|
||||
);
|
||||
|
||||
secretBlindIndexDataSchema.index({ workspace: 1 });
|
||||
|
||||
export const SecretBlindIndexData = model<ISecretBlindIndexData>("SecretBlindIndexData", secretBlindIndexDataSchema);
|
||||
@@ -1,10 +1,9 @@
|
||||
---
|
||||
title: "Reference/Import Secrets"
|
||||
title: "Reference and Import Secrets"
|
||||
description: "How to use reference secrets in Infisical"
|
||||
---
|
||||
|
||||
Secret referencing is a powerful feature that allows you to create a secret whose value is linked to one or more other secrets.
|
||||
This is useful when you need to use a single secret's value across multiple other secrets.
|
||||
Secret referencing is a powerful feature that allows you to values of other secrets. This way, you just need to update the secret value once for it to be propagated to all the references.
|
||||
|
||||
Consider a scenario where you have a database password. In order to utilize this password, you may need to incorporate it into a database connection string.
|
||||
With secret referencing, you can easily construct these more intricate secrets by directly referencing the base secret.
|
||||
@@ -34,7 +33,7 @@ For instance, to access a secret 'A' composed of secrets 'B' and 'C' from differ
|
||||
When using [service tokens](./token) to fetch referenced secrets, ensure the service token has read access to all referenced environments and folders.
|
||||
Without proper permissions, the final secret value may be incomplete.
|
||||
|
||||
## Import entire folders
|
||||
## Import entire folders/environments
|
||||
|
||||
While secret referencing effectively minimizes duplication, there might be instances where you need to import or replicate an entire folder's secrets into another. This can be achieved using the 'Import' feature.
|
||||
|
||||
@@ -50,3 +49,5 @@ Additionally, any secrets you define directly in your environment will override
|
||||
You can modify the order of folders to control overrides using the `Change Order` drag handle.
|
||||
|
||||

|
||||
|
||||
<iframe width="560" height="315" src="https://www.youtube.com/embed/o11bMU0pXRs?si=dCprt3xLWPrSOJxy" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
|
||||
|
||||
@@ -3,6 +3,13 @@ title: "Azure SAML"
|
||||
description: "Configure Azure SAML for Infisical SSO"
|
||||
---
|
||||
|
||||
<Info>
|
||||
Azure SAML SSO feature is a paid feature.
|
||||
|
||||
If you're using Infisical Cloud, then it is available under the **Pro Tier**. If you're self-hosting Infisical,
|
||||
then you should contact team@infisical.com to purchase an enterprise license to use it.
|
||||
</Info>
|
||||
|
||||
1. In Infisical, head over to your organization Settings > Authentication > SAML SSO Configuration and select **Set up SAML SSO**.
|
||||
Next, copy the **Reply URL (Assertion Consumer Service URL)** and **Identifier (Entity ID)** to use when configuring the Azure SAML application.
|
||||
|
||||
|
||||
37
docs/documentation/platform/sso/github.mdx
Normal file
@@ -0,0 +1,37 @@
|
||||
---
|
||||
title: "GitHub SSO"
|
||||
description: "Configure GitHub SSO for Infisical"
|
||||
---
|
||||
|
||||
Using GitHub SSO on a self-hosted instance of Infisical requires configuring an OAuth2 application in GitHub and registering your instance with it.
|
||||
|
||||
## Create an OAuth application in GitHub
|
||||
|
||||
Navigate to your user Settings > Developer settings > OAuth Apps to create a new GitHub OAuth application.
|
||||
|
||||

|
||||

|
||||

|
||||
|
||||
Create the OAuth application. As part of the form, set the **Homepage URL** to your self-hosted domain `https://your-domain.com`
|
||||
and the **Authorization callback URL** to `https://your-domain.com/api/v1/sso/github`.
|
||||
|
||||

|
||||
|
||||
<Note>
|
||||
If you have a GitHub organization, you can create an OAuth application under it
|
||||
in your organization Settings > Developer settings > OAuth Apps > New Org OAuth App.
|
||||
</Note>
|
||||
|
||||
## Add your OAuth application credentials to Infisical
|
||||
|
||||
Obtain the **Client ID** and generate a new **Client Secret** for your GitHub OAuth application.
|
||||
|
||||

|
||||
|
||||
Back in your Infisical instance, add two new environment variables for the credentials of your GitHub OAuth application:
|
||||
|
||||
- `CLIENT_ID_GITHUB_LOGIN`: The **Client ID** of your GitHub OAuth application.
|
||||
- `CLIENT_SECRET_GITHUB_LOGIN`: The **Client Secret** of your GitHub OAuth application.
|
||||
|
||||
Once added, restart your Infisical instance and log in with GitHub.
|
||||
30
docs/documentation/platform/sso/google.mdx
Normal file
@@ -0,0 +1,30 @@
|
||||
---
|
||||
title: "Google SSO"
|
||||
description: "Configure Google SSO for Infisical"
|
||||
---
|
||||
|
||||
Using Google SSO on a self-hosted instance of Infisical requires configuring an OAuth2 application in GCP and registering your instance with it.
|
||||
|
||||
## Create an OAuth2 application in GCP
|
||||
|
||||
Navigate to your project API & Services > Credentials to create a new OAuth2 application.
|
||||
|
||||

|
||||

|
||||
|
||||
Create the application. As part of the form, add to **Authorized redirect URIs**: `https://your-domain.com/api/v1/sso/google`.
|
||||
|
||||

|
||||
|
||||
## Add your OAuth2 application credentials to Infisical
|
||||
|
||||
Obtain the **Client ID** and **Client Secret** for your GCP OAuth2 application.
|
||||
|
||||

|
||||
|
||||
Back in your Infisical instance, add two new environment variables for the credentials of your GCP OAuth2 application:
|
||||
|
||||
- `CLIENT_ID_GOOGLE_LOGIN`: The **Client ID** of your GCP OAuth2 application.
|
||||
- `CLIENT_SECRET_GOOGLE_LOGIN`: The **Client Secret** of your GCP OAuth2 application.
|
||||
|
||||
Once added, restart your Infisical instance and log in with Google
|
||||
@@ -3,6 +3,13 @@ title: "JumpCloud SAML"
|
||||
description: "Configure JumpCloud SAML for Infisical SSO"
|
||||
---
|
||||
|
||||
<Info>
|
||||
JumpCloud SAML SSO feature is a paid feature.
|
||||
|
||||
If you're using Infisical Cloud, then it is available under the **Pro Tier**. If you're self-hosting Infisical,
|
||||
then you should contact team@infisical.com to purchase an enterprise license to use it.
|
||||
</Info>
|
||||
|
||||
1. In Infisical, head over to your organization Settings > Authentication > SAML SSO Configuration and select **Set up SAML SSO**.
|
||||
Next, copy the **ACS URL** and **SP Entity ID** to use when configuring the JumpCloud SAML application.
|
||||
|
||||
|
||||
@@ -3,6 +3,13 @@ title: "Okta SAML"
|
||||
description: "Configure Okta SAML 2.0 for Infisical SSO"
|
||||
---
|
||||
|
||||
<Info>
|
||||
Okta SAML SSO feature is a paid feature.
|
||||
|
||||
If you're using Infisical Cloud, then it is available under the **Pro Tier**. If you're self-hosting Infisical,
|
||||
then you should contact team@infisical.com to purchase an enterprise license to use it.
|
||||
</Info>
|
||||
|
||||
1. In Infisical, head over to your organization Settings > Authentication > SAML SSO Configuration and select **Set up SAML SSO**.
|
||||
Next, copy the **Single sign-on URL** and **Audience URI (SP Entity ID)** to use when configuring the Okta SAML 2.0 application.
|
||||
|
||||
|
||||
@@ -4,9 +4,11 @@ description: "Log in to Infisical via SSO protocols"
|
||||
---
|
||||
|
||||
<Warning>
|
||||
Infisical currently has confirmed support for SAML SSO authentication with
|
||||
Okta, Azure AD, and JumpCloud. We're expanding support for other IdPs in the
|
||||
coming months, so stay tuned and feel free to request a IdP at this
|
||||
Infisical offers Google SSO and GitHub SSO for free across both Infisical Cloud and Infisical Self-hosted.
|
||||
|
||||
Infisical also offers SAML SSO authentication but as paid features that can be unlocked on Infisical Cloud's **Pro** tier
|
||||
or via enterprise license on self-hosted instances of Infisical. On this front, we currently support Okta, Azure AD, and JumpCloud and
|
||||
are expanding support for other IdPs in the coming months; stay tuned and feel free to request a IdP at this
|
||||
[issue](https://github.com/Infisical/infisical/issues/442).
|
||||
</Warning>
|
||||
|
||||
@@ -15,6 +17,8 @@ You can configure your organization in Infisical to have members authenticate wi
|
||||
To note, configuring SSO retains the end-to-end encrypted architecture of Infisical because we decouple the **authentication** and **decryption** steps. In all login with SSO implementations,
|
||||
your IdP cannot and will not have access to the decryption key needed to decrypt your secrets.
|
||||
|
||||
- [Google SSO](/documentation/platform/sso/google)
|
||||
- [GitHub SSO](/documentation/platform/sso/github)
|
||||
- [Okta SAML](/documentation/platform/sso/okta)
|
||||
- [Azure SAML](/documentation/platform/sso/azure)
|
||||
- [JumpCloud SAML](/documentation/platform/sso/jumpcloud)
|
||||
- [JumpCloud SAML](/documentation/platform/sso/jumpcloud)
|
||||
BIN
docs/images/sso/github/credentials.png
Normal file
|
After Width: | Height: | Size: 740 KiB |
BIN
docs/images/sso/github/dev-settings.png
Normal file
|
After Width: | Height: | Size: 856 KiB |
BIN
docs/images/sso/github/new-app-form.png
Normal file
|
After Width: | Height: | Size: 772 KiB |
BIN
docs/images/sso/github/new-app.png
Normal file
|
After Width: | Height: | Size: 602 KiB |
BIN
docs/images/sso/github/settings.png
Normal file
|
After Width: | Height: | Size: 1.5 MiB |
BIN
docs/images/sso/google/api-services.png
Normal file
|
After Width: | Height: | Size: 370 KiB |
BIN
docs/images/sso/google/credentials.png
Normal file
|
After Width: | Height: | Size: 1.1 MiB |
BIN
docs/images/sso/google/new-app-form.png
Normal file
|
After Width: | Height: | Size: 1.3 MiB |
BIN
docs/images/sso/google/new-app.png
Normal file
|
After Width: | Height: | Size: 940 KiB |
@@ -126,6 +126,8 @@
|
||||
"group": "SSO",
|
||||
"pages": [
|
||||
"documentation/platform/sso/overview",
|
||||
"documentation/platform/sso/google",
|
||||
"documentation/platform/sso/github",
|
||||
"documentation/platform/sso/okta",
|
||||
"documentation/platform/sso/azure",
|
||||
"documentation/platform/sso/jumpcloud"
|
||||
@@ -150,6 +152,7 @@
|
||||
"self-hosting/configuration/envars",
|
||||
"self-hosting/configuration/email",
|
||||
"self-hosting/configuration/redis",
|
||||
"self-hosting/configuration/sso",
|
||||
"self-hosting/faq"
|
||||
]
|
||||
},
|
||||
|
||||
20
docs/self-hosting/configuration/sso.mdx
Normal file
@@ -0,0 +1,20 @@
|
||||
---
|
||||
title: "Configure SSO"
|
||||
description: "How to configure SSO when self-hosting Infisical."
|
||||
---
|
||||
|
||||
<Warning>
|
||||
Infisical offers Google SSO and GitHub SSO for free.
|
||||
|
||||
Infisical also offers SAML SSO authentication but as paid features that can be unlocked via enterprise license; if this is of interest, please contact team@infisical.com.
|
||||
On this front, we currently support Okta, Azure AD, and JumpCloud and are expanding support for other IdPs in the coming months; stay tuned and feel free to request a IdP at this
|
||||
[issue](https://github.com/Infisical/infisical/issues/442).
|
||||
</Warning>
|
||||
|
||||
You can view specific documentation for how to set up each SSO authentication method below:
|
||||
|
||||
- [Google SSO](/documentation/platform/sso/google)
|
||||
- [GitHub SSO](/documentation/platform/sso/github)
|
||||
- [Okta SAML](/documentation/platform/sso/okta)
|
||||
- [Azure SAML](/documentation/platform/sso/azure)
|
||||
- [JumpCloud SAML](/documentation/platform/sso/jumpcloud)
|
||||
46
frontend/src/components/basic/popups/GlobPatternExamples.tsx
Normal file
@@ -0,0 +1,46 @@
|
||||
import { useState } from "react";
|
||||
import { faInfo } from "@fortawesome/free-solid-svg-icons";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
|
||||
import { Tooltip } from "@app/components/v2/Tooltip";
|
||||
|
||||
const GlobPatternExamples = () => {
|
||||
const [showTip, setShowTip] = useState<boolean>(false);
|
||||
|
||||
return (
|
||||
<Tooltip
|
||||
isOpen={showTip}
|
||||
onOpenChange={setShowTip}
|
||||
content={
|
||||
<div>
|
||||
<h4 className="mb-2">Here are some examples of glob patterns:</h4>
|
||||
<div className="ol-listStyleType">
|
||||
<li>
|
||||
<code className="text-primary">/</code> - Matches all files and directories in the
|
||||
current directory
|
||||
</li>
|
||||
<li>
|
||||
<code className="text-primary">**/*</code> - Matches all files and directories in the
|
||||
current directory and its subdirectories
|
||||
</li>
|
||||
<li>
|
||||
<code className="text-primary">{"/{dir1,dir2}"}</code> - Matches all files and
|
||||
directories in dir1 and dir2
|
||||
</li>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
position="right"
|
||||
className="text-xs"
|
||||
>
|
||||
<div
|
||||
className="flex h-3.5 w-3.5 items-center justify-center rounded-full border border-[1px] border-mineshaft-300"
|
||||
onMouseEnter={() => setShowTip(true)}
|
||||
>
|
||||
<FontAwesomeIcon icon={faInfo} className="h-2 w-2" />
|
||||
</div>
|
||||
</Tooltip>
|
||||
);
|
||||
};
|
||||
|
||||
export default GlobPatternExamples;
|
||||
30
frontend/src/components/v2/Accordion/Accordion.stories.tsx
Normal file
@@ -0,0 +1,30 @@
|
||||
import type { Meta, StoryObj } from "@storybook/react";
|
||||
|
||||
import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from "./Accordion";
|
||||
|
||||
const meta: Meta<typeof Accordion> = {
|
||||
title: "Components/Accordion",
|
||||
component: Accordion,
|
||||
tags: ["v2"],
|
||||
argTypes: {}
|
||||
};
|
||||
|
||||
export default meta;
|
||||
type Story = StoryObj<typeof Accordion>;
|
||||
|
||||
export const Basic: Story = {
|
||||
render: (args) => (
|
||||
<div className="flex justify-center w-full">
|
||||
<Accordion {...args}>
|
||||
<AccordionItem value="section-1">
|
||||
<AccordionTrigger>Section 1</AccordionTrigger>
|
||||
<AccordionContent>Description of Section 1</AccordionContent>
|
||||
</AccordionItem>
|
||||
<AccordionItem value="section-2">
|
||||
<AccordionTrigger>Section 2</AccordionTrigger>
|
||||
<AccordionContent>Description of Section 2</AccordionContent>
|
||||
</AccordionItem>
|
||||
</Accordion>
|
||||
</div>
|
||||
)
|
||||
};
|
||||
@@ -8,7 +8,7 @@ export const AccordionItem = forwardRef<HTMLDivElement, AccordionPrimitive.Accor
|
||||
({ children, className, ...props }, forwardedRef) => (
|
||||
<AccordionPrimitive.Item
|
||||
className={twMerge(
|
||||
"focus-within:shadow-mauve12 mt-px overflow-hidden first:mt-0 first:rounded-t last:rounded-b focus-within:relative focus-within:z-10 focus-within:shadow-[0_0_0_2px]",
|
||||
"mt-px overflow-hidden first:mt-0 data-[state=open]:border-l data-[state=open]:border-primary transition-all border-transparent",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
@@ -27,7 +27,7 @@ export const AccordionTrigger = forwardRef<
|
||||
<AccordionPrimitive.Header className="flex">
|
||||
<AccordionPrimitive.Trigger
|
||||
className={twMerge(
|
||||
"text-violet11 shadow-mauve6 hover:bg-mauve2 group flex h-[45px] flex-1 cursor-default items-center justify-between bg-white px-5 text-[15px] leading-none shadow-[0_1px_0] outline-none",
|
||||
"py-2 px-4 group data-[state=open]:text-primary h-11 hover:text-primary flex flex-1 outline-none items-center justify-between ",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
@@ -36,7 +36,7 @@ export const AccordionTrigger = forwardRef<
|
||||
{children}
|
||||
<FontAwesomeIcon
|
||||
icon={faChevronDown}
|
||||
className="text-violet10 ease-[cubic-bezier(0.87,_0,_0.13,_1)] transition-transform duration-300 group-data-[state=open]:rotate-180"
|
||||
className="ease-[cubic-bezier(0.87,_0,_0.13,_1)] transition-transform duration-300 group-data-[state=open]:rotate-180 text-sm"
|
||||
aria-hidden
|
||||
/>
|
||||
</AccordionPrimitive.Trigger>
|
||||
@@ -51,13 +51,13 @@ export const AccordionContent = forwardRef<
|
||||
>(({ children, className, ...props }, forwardedRef) => (
|
||||
<AccordionPrimitive.Content
|
||||
className={twMerge(
|
||||
"text-mauve11 bg-mauve2 data-[state=open]:animate-slideDown data-[state=closed]:animate-slideUp overflow-hidden text-[15px]",
|
||||
"data-[state=open]:animate-slideDown data-[state=closed]:animate-slideUp overflow-hidden",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
ref={forwardedRef}
|
||||
>
|
||||
<div className="py-[15px] px-5">{children}</div>
|
||||
<div className="text-sm py-2 px-4">{children}</div>
|
||||
</AccordionPrimitive.Content>
|
||||
));
|
||||
|
||||
@@ -68,10 +68,7 @@ export const Accordion = ({
|
||||
children,
|
||||
...props
|
||||
}: AccordionPrimitive.AccordionSingleProps | AccordionPrimitive.AccordionMultipleProps) => (
|
||||
<AccordionPrimitive.Root
|
||||
className="bg-mauve6 w-[300px] rounded-md shadow-[0_2px_10px] shadow-black/5"
|
||||
{...props}
|
||||
>
|
||||
<AccordionPrimitive.Root {...props} className={twMerge("w-80 text-bunker-300", props.className)}>
|
||||
{children}
|
||||
</AccordionPrimitive.Root>
|
||||
);
|
||||
|
||||
@@ -79,7 +79,7 @@ export const Tr = ({
|
||||
}: TrProps): JSX.Element => (
|
||||
<tr
|
||||
className={twMerge(
|
||||
"cursor-default border-b last:border-b-0 border-solid border-mineshaft-600",
|
||||
"cursor-default border-b border-solid border-mineshaft-600 last:border-b-0",
|
||||
isHoverable && "hover:bg-mineshaft-600",
|
||||
isSelectable && "cursor-pointer",
|
||||
className
|
||||
|
||||
@@ -45,8 +45,7 @@ export const withPermission = <T extends {}, J extends TOrgPermission>(
|
||||
<div>
|
||||
<div className="text-4xl font-medium mb-2">Access Restricted</div>
|
||||
<div className="text-sm">
|
||||
Your role has limited permissions, please <br /> You do not have permission to this
|
||||
page.
|
||||
Your role has limited permissions, please <br /> contact your admin to gain access
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -15,6 +15,7 @@ import { yupResolver } from "@hookform/resolvers/yup";
|
||||
import { twMerge } from "tailwind-merge";
|
||||
import * as yup from "yup";
|
||||
|
||||
import GlobPatternExamples from "@app/components/basic/popups/GlobPatternExamples";
|
||||
import { useNotificationContext } from "@app/components/context/Notifications/NotificationProvider";
|
||||
import { ProjectPermissionCan } from "@app/components/permissions";
|
||||
// TODO:(akhilmhdh) convert all the util functions like this into a lib folder grouped by functionality
|
||||
@@ -222,7 +223,7 @@ export const SecretDropzone = ({
|
||||
onDragOver={handleDrag}
|
||||
onDrop={handleDrop}
|
||||
className={twMerge(
|
||||
"relative mx-0.5 mb-4 mt-4 flex cursor-pointer items-center justify-center rounded-md bg-mineshaft-900 py-4 text-sm px-2 text-mineshaft-200 opacity-60 outline-dashed outline-2 outline-chicago-600 duration-200 hover:opacity-100",
|
||||
"relative mx-0.5 mb-4 mt-4 flex cursor-pointer items-center justify-center rounded-md bg-mineshaft-900 py-4 px-2 text-sm text-mineshaft-200 opacity-60 outline-dashed outline-2 outline-chicago-600 duration-200 hover:opacity-100",
|
||||
isDragActive && "opacity-100",
|
||||
!isSmaller && "w-full max-w-3xl flex-col space-y-4 py-20",
|
||||
isLoading && "bg-bunker-800"
|
||||
@@ -234,7 +235,7 @@ export const SecretDropzone = ({
|
||||
</div>
|
||||
) : (
|
||||
<form onSubmit={handleSubmit(handleFormSubmit)}>
|
||||
<div className="flex items-center justify-cente flex-col space-y-2">
|
||||
<div className="justify-cente flex flex-col items-center space-y-2">
|
||||
<div>
|
||||
<FontAwesomeIcon icon={faUpload} size={isSmaller ? "2x" : "5x"} />
|
||||
</div>
|
||||
@@ -324,7 +325,12 @@ export const SecretDropzone = ({
|
||||
</FormControl>
|
||||
)}
|
||||
/>
|
||||
<FormControl label="Secret Path" className="flex-grow" isRequired>
|
||||
<FormControl
|
||||
label="Secret Path"
|
||||
className="flex-grow"
|
||||
isRequired
|
||||
icon={<GlobPatternExamples />}
|
||||
>
|
||||
<Input
|
||||
{...register("secretPath")}
|
||||
placeholder="Provide a path, default is /"
|
||||
@@ -334,7 +340,7 @@ export const SecretDropzone = ({
|
||||
<div className="border-t border-mineshaft-600 pt-4">
|
||||
<div className="mb-4 flex items-center justify-between">
|
||||
<div>Secrets</div>
|
||||
<div className="w-1/2 flex items-center space-x-2">
|
||||
<div className="flex w-1/2 items-center space-x-2">
|
||||
<Input
|
||||
placeholder="Search for secret"
|
||||
value={searchFilter}
|
||||
@@ -367,7 +373,7 @@ export const SecretDropzone = ({
|
||||
{!isSecretsLoading && !secrets?.secrets?.length && (
|
||||
<EmptyState title="No secrets found" icon={faKey} />
|
||||
)}
|
||||
<div className="grid grid-cols-2 gap-4 max-h-64 overflow-auto thin-scrollbar ">
|
||||
<div className="thin-scrollbar grid max-h-64 grid-cols-2 gap-4 overflow-auto ">
|
||||
{isSecretsLoading &&
|
||||
Array.apply(0, Array(2)).map((_x, i) => (
|
||||
<Skeleton
|
||||
|
||||
@@ -5,6 +5,7 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { motion } from "framer-motion";
|
||||
import { twMerge } from "tailwind-merge";
|
||||
|
||||
import GlobPatternExamples from "@app/components/basic/popups/GlobPatternExamples";
|
||||
import {
|
||||
Checkbox,
|
||||
FormControl,
|
||||
@@ -98,7 +99,7 @@ export const MultiEnvProjectPermission = ({
|
||||
return (
|
||||
<div
|
||||
className={twMerge(
|
||||
"px-10 py-6 bg-mineshaft-800 rounded-md",
|
||||
"rounded-md bg-mineshaft-800 px-10 py-6",
|
||||
(selectedPermissionCategory !== Permission.NoAccess || isCustom) &&
|
||||
"border-l-2 border-primary-600"
|
||||
)}
|
||||
@@ -107,8 +108,8 @@ export const MultiEnvProjectPermission = ({
|
||||
<div>
|
||||
<FontAwesomeIcon icon={icon} className="text-4xl" />
|
||||
</div>
|
||||
<div className="flex-grow flex flex-col">
|
||||
<div className="font-medium mb-1 text-lg">{title}</div>
|
||||
<div className="flex flex-grow flex-col">
|
||||
<div className="mb-1 text-lg font-medium">{title}</div>
|
||||
<div className="text-xs font-light">{subtitle}</div>
|
||||
</div>
|
||||
<div>
|
||||
@@ -130,12 +131,19 @@ export const MultiEnvProjectPermission = ({
|
||||
animate={{ height: isCustom ? "auto" : 0 }}
|
||||
className="overflow-hidden"
|
||||
>
|
||||
<TableContainer className="border-mineshaft-500 mt-6">
|
||||
<TableContainer className="mt-6 border-mineshaft-500">
|
||||
<Table>
|
||||
<THead>
|
||||
<Tr>
|
||||
<Th />
|
||||
<Th className="min-w-[8rem]">Secret Path</Th>
|
||||
<Th className="min-w-[8rem]">
|
||||
<div className="flex items-center gap-2">
|
||||
Secret Path
|
||||
<span className="text-xs normal-case">
|
||||
<GlobPatternExamples />
|
||||
</span>
|
||||
</div>
|
||||
</Th>
|
||||
<Th className="text-center">View</Th>
|
||||
<Th className="text-center">Create</Th>
|
||||
<Th className="text-center">Modify</Th>
|
||||
|
||||
@@ -169,7 +169,7 @@ export const ProjectRoleModifySection = ({ role, onGoBack }: Props) => {
|
||||
return (
|
||||
<div>
|
||||
<form onSubmit={handleSubmit(handleFormSubmit)}>
|
||||
<div className="flex justify-between mb-2 items-center">
|
||||
<div className="mb-2 flex items-center justify-between">
|
||||
<h1 className="text-xl font-semibold text-mineshaft-100">
|
||||
{isNewRole ? "New" : "Edit"} Role
|
||||
</h1>
|
||||
@@ -211,7 +211,7 @@ export const ProjectRoleModifySection = ({ role, onGoBack }: Props) => {
|
||||
>
|
||||
<Input {...register("description")} isReadOnly={isNonEditable} />
|
||||
</FormControl>
|
||||
<div className="flex justify-between items-center pt-6 border-t border-t-mineshaft-800">
|
||||
<div className="flex items-center justify-between border-t border-t-mineshaft-800 pt-6">
|
||||
<div>
|
||||
<h2 className="text-xl font-medium">Add Permission</h2>
|
||||
</div>
|
||||
@@ -255,7 +255,7 @@ export const ProjectRoleModifySection = ({ role, onGoBack }: Props) => {
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-center space-x-4 mt-12">
|
||||
<div className="mt-12 flex items-center space-x-4">
|
||||
<Button
|
||||
type="submit"
|
||||
isDisabled={isSubmitting || isNonEditable || !isDirty}
|
||||
|
||||
@@ -23,8 +23,8 @@ enum Permission {
|
||||
}
|
||||
|
||||
const PERMISSIONS = [
|
||||
{ action: "edit", label: "Update workspace details" },
|
||||
{ action: "delete", label: "Delete workspace" }
|
||||
{ action: "edit", label: "Update project details" },
|
||||
{ action: "delete", label: "Delete projects" }
|
||||
] as const;
|
||||
|
||||
export const WsProjectPermission = ({ isNonEditable, setValue, control }: Props) => {
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { useEffect } from "react";
|
||||
import { Controller, useForm } from "react-hook-form";
|
||||
import { faInfo } from "@fortawesome/free-solid-svg-icons";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { yupResolver } from "@hookform/resolvers/yup";
|
||||
import * as yup from "yup";
|
||||
|
||||
import GlobPatternExamples from "@app/components/basic/popups/GlobPatternExamples";
|
||||
import {
|
||||
Button,
|
||||
FormControl,
|
||||
@@ -13,8 +12,7 @@ import {
|
||||
ModalClose,
|
||||
ModalContent,
|
||||
Select,
|
||||
SelectItem,
|
||||
Tooltip
|
||||
SelectItem
|
||||
} from "@app/components/v2";
|
||||
|
||||
const formSchema = yup.object({
|
||||
@@ -48,7 +46,6 @@ export const AddWebhookForm = ({
|
||||
} = useForm<TFormSchema>({
|
||||
resolver: yupResolver(formSchema)
|
||||
});
|
||||
const [showTip, setShowTip] = useState<boolean>(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (!isOpen) {
|
||||
@@ -89,40 +86,7 @@ export const AddWebhookForm = ({
|
||||
/>
|
||||
<FormControl
|
||||
label="Secret Path"
|
||||
icon={
|
||||
<Tooltip
|
||||
isOpen={showTip}
|
||||
onOpenChange={setShowTip}
|
||||
content={
|
||||
<div>
|
||||
<h4 className="mb-2">Here are some examples of glob patterns:</h4>
|
||||
<div className="ol-listStyleType">
|
||||
<li>
|
||||
<code className="text-primary">/</code> - Matches all files and
|
||||
directories in the current directory
|
||||
</li>
|
||||
<li>
|
||||
<code className="text-primary">**/*</code> - Matches all files and
|
||||
directories in the current directory and its subdirectories
|
||||
</li>
|
||||
<li>
|
||||
<code className="text-primary">{"/{dir1,dir2}"}</code> - Matches all files
|
||||
and directories in dir1 and dir2
|
||||
</li>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
position="right"
|
||||
className="text-xs"
|
||||
>
|
||||
<div
|
||||
className="flex h-3.5 w-3.5 items-center justify-center rounded-full border border-[1px] border-mineshaft-300"
|
||||
onMouseEnter={() => setShowTip(true)}
|
||||
>
|
||||
<FontAwesomeIcon icon={faInfo} className="h-2 w-2" />
|
||||
</div>
|
||||
</Tooltip>
|
||||
}
|
||||
icon={<GlobPatternExamples />}
|
||||
isRequired
|
||||
isError={Boolean(errors?.secretPath)}
|
||||
errorText={errors?.secretPath?.message}
|
||||
|
||||
@@ -7,7 +7,7 @@ type: application
|
||||
# This is the chart version. This version number should be incremented each time you make changes
|
||||
# to the chart and its templates, including the app version.
|
||||
# Versions are expected to follow Semantic Versioning (https://semver.org/)
|
||||
version: 0.3.3
|
||||
version: 0.3.4
|
||||
|
||||
# This is the version number of the application being deployed. This version number should be
|
||||
# incremented each time you make changes to the application. Versions are not expected to
|
||||
|
||||
@@ -50,7 +50,7 @@ frontend:
|
||||
limits:
|
||||
memory: 100Mi
|
||||
requests:
|
||||
cpu: 10m
|
||||
cpu: 100m
|
||||
## @param frontend.kubeSecretRef Backend secret resource reference name (containing required [frontend configuration variables](https://infisical.com/docs/self-hosting/configuration/envars))
|
||||
##
|
||||
kubeSecretRef: ""
|
||||
|
||||