mirror of
https://github.com/Infisical/infisical.git
synced 2025-03-25 14:05:03 +00:00
Compare commits
87 Commits
akhilmhdh-
...
auth0-saml
Author | SHA1 | Date | |
---|---|---|---|
e6103d2d3f | |||
0cefd6f837 | |||
f632847dc6 | |||
faa6d1cf40 | |||
7fb18870e3 | |||
ae841715e5 | |||
baac87c16a | |||
b726187ba3 | |||
d98ff32b07 | |||
1fa510b32f | |||
c57f0d8120 | |||
00490f2cff | |||
ee58f538c0 | |||
0fa20f7839 | |||
40ef75d3bd | |||
26af13453c | |||
ad1f71883d | |||
2659ea7170 | |||
d2e3f504fd | |||
ca4151a34d | |||
d4bc104fd1 | |||
7e3a3fcdb0 | |||
7f67912d2f | |||
a7f4020c08 | |||
d2d89034ba | |||
2fc6c564c0 | |||
240b86c1d5 | |||
30d66cef89 | |||
b7d11444a9 | |||
0a6aef0afa | |||
0ac7ec460b | |||
808a901aee | |||
d5412f916f | |||
d0648ca596 | |||
3291f1f908 | |||
965d30bd03 | |||
68fe7c589a | |||
54377a44d3 | |||
8c902d7699 | |||
c25c84aeb3 | |||
4359eb7313 | |||
322536d738 | |||
6c5db3a187 | |||
a337e6badd | |||
524a97e9a6 | |||
c56f598115 | |||
19d32a1a3b | |||
7e5417a0eb | |||
afd6de27fe | |||
7781a6b7e7 | |||
b3b4e41d92 | |||
5225f5136a | |||
398adfaf76 | |||
d77c26fa38 | |||
ef7b81734a | |||
09b489a348 | |||
6b5c50def0 | |||
1f2d52176c | |||
7002e297c8 | |||
71864a131f | |||
9964d2ecaa | |||
3ebbaefc2a | |||
dd5c494bdb | |||
bace8af5a1 | |||
f56196b820 | |||
7042d73410 | |||
cb22ee315e | |||
701eb7cfc6 | |||
bf8df14b01 | |||
1ba8b6394b | |||
c442c8483a | |||
0435305a68 | |||
febf11f502 | |||
64fd15c32d | |||
a2c9494d52 | |||
18460e0678 | |||
3d03fece74 | |||
234e7eb9be | |||
04af313bf0 | |||
9b038ccc45 | |||
9beb384546 | |||
12ec9b4b4e | |||
96b8e7fda8 | |||
93b9108aa3 | |||
99017ea1ae | |||
1190ca2d77 | |||
2fb60201bc |
.github/workflows
Dockerfile.fips.standalone-infisicalDockerfile.standalone-infisicalbackend
package-lock.jsonpackage.json
src
ee
routes/v1
services
access-approval-request
saml-config
secret-approval-request
lib/config
server
services
company/handbook
docker-compose.dev.ymldocs
documentation/platform
images/sso/auth0-saml
auth0-config-2.pngauth0-config-3.pngauth0-config.pngcreate-application-2.pngcreate-application.pngenable-saml.pnginfisical-config.pnginit-config.png
mint.jsonfrontend
.dockerignore.eslintrc.js.gitignore.prettierrceslint.config.jsindex.htmlnext-env.d.tsnext.config.jspackage-lock.jsonpackage.jsonpostcss.config.jsglobal.d.tsindex.tsuseDebounce.tsxuseLeaveConfirm.tsxusePersistentState.tsuseTimedReset.tsxindex.cssvite-env.d.tstsconfig.app.jsontsconfig.jsontsconfig.node.jsontsconfig.tsbuildinfotsr.config.jsonvite.config.ts
.storybook
DockerfileDockerfile.devREADME.mdcypress.config.jscypress
e2e
fixtures
support
public
data
lotties
circular-check.jsongroups.jsonjigsaw-puzzle.jsonlock-closed.jsonmoving-block.jsonsecret-scan.jsonsliding-carousel.jsonspinning-coin.jsonsystem-outline-103-coin-cash-monetization.jsonsystem-outline-109-slider-toggle-settings.jsonsystem-outline-126-verified.jsonsystem-outline-165-view-carousel.jsonsystem-outline-168-view-headline.jsonsystem-outline-69-document-scan.jsonsystem-outline-82-extension.jsonsystem-outline-90-lock-closed.jsonsystem-outline-96-groups.jsonsystem-regular-126-verified-hover-verified.jsontoggle-settings.jsonverified.json
vercel.svgvite.svgscripts
src
components
AddTagPopoverContent
RouteGuard.tsxanalytics
auth
CodeInputStep.tsxDonwloadBackupPDFStep.tsxEnterEmailStep.tsxInitialSignupStep.tsxMfa.tsxTeamInviteStep.tsxUserInfoStep.tsx
basic
Error.tsxInputField.tsxListbox.tsxToggle.tsx
buttons
dialog
ActivateBotDialog.tsxAddProjectMemberDialog.tsxAddUpdateEnvironmentDialog.tsxAddWorkspaceDialog.tsxDeleteActionModal.tsxDeleteEnvVar.tsxDeleteUserDialog.tsxUpgradePlan.tsx
popups
table
dashboard
AddTagsMenu.tsxCommentField.tsxConfirmEnvOverwriteModal.tsxDashboardInputField.tsxDeleteActionButton.tsxDownloadSecretsMenu.tsxDropZone.tsxGenerateSecretMenu.tsxKeyPair.tsx
features
integrations
license/UpgradePlanModal
mfa
navigation
notifications
organization/CreateOrgModal
permissions
projects
secrets/SecretReferenceDetails
tags/CreateTagModal
utilities
SecurityClient.tsattemptChangePassword.tsattemptCliLogin.tsattemptCliLoginMfa.tsattemptLogin.tsattemptLoginMfa.ts
config
cryptography
intercom
secrets
telemetry
v2
Accordion
Alert
Button
Card
Checkbox
ComboBox
ContentLoader
CreatableSelect
DatePicker
Drawer
Dropdown
EmptyState
FilterableSelect
FormControl
HoverCardv2
IconButton
InfisicalSecretInput
Input
Menu
Modal
NoticeBanner
Pagination
Popover
Popoverv2
SecretInput
SecretPathInput
Select
Skeleton
Switch
Table
Tabs
TextArea
Tooltip
index.tsxconfig
const
context
AuthContext
OrgPermissionContext
OrganizationContext
ProjectPermissionContext
ServerConfigContext
SubscriptionContext
UserContext
WorkspaceContext
index.tsxee
api
memberships
secrets
utilities
helpers
hoc
hooks
api
accessApproval
admin
apiKeys
appConnections
auditLogStreams
auditLogs
auth
bots
ca
certificateTemplates
certificates
cmeks
dashboard
dynamicSecret
dynamicSecretLease
externalGroupOrgRoleMappings
groups
identities
identityProjectAdditionalPrivilege
incidentContacts
index.tsxintegrationAuth
integrations
keys
kms
ldapConfig
migration
oidcConfig
organization
pkiAlerts
pkiCollections
policies
projectTemplates
projectUserAdditionalPrivilege
rateLimit
reactQuery.tsxroles
scim
secretApproval
secretApprovalRequest
secretFolders
secretImports
secretRotation
secretScanning
secretSharing
secretSnapshots
secrets
serviceTokens
sshCa
sshCertificateTemplates
ssoConfig
subscriptions
tags
trustedIps
userEngagement
users
webhooks
workflowIntegrations
workspace
layouts
AdminLayout
AppLayout
OrganizationLayout
PersonalSettingsLayout
ProjectLayout
index.tsxlib/fn
main.tsxpages
_app.tsxlayout.tsxdashboard.tsxindex.tsxlayout.tsxpersonal-settings.tsxroot.tsxlayout.tsxsecret-scanning.tsxlayout.tsx
routeTree.gen.tsroutes.tsadmin
api
auth
secret-scanning
auth
CliRedirectPage
EmailNotVerifiedPage
LoginLdapPage
LoginPage
LoginSsoPage
PasswordResetPage
ProviderErrorPage
ProviderSuccessPage
RequestNewInvitePage
SelectOrgPage
SignUpInvitePage
SignUpPage
SignUpSsoPage
VerifyEmailPage
cert-manager
CertAuthDetailsByIDPage
CertAuthDetailsByIDPage.tsx
components
route.tsxCertificatesPage
CertificatesPage.tsxroute.tsx
components
CaTab
CaTab.tsx
components
index.tsxCertificatesTab
CertificatesTab.tsx
components
CertificateCertModal.tsxCertificateContent.tsxCertificateModal.tsxCertificateRevocationModal.tsxCertificateTemplateEnrollmentModal.tsxCertificateTemplateModal.tsxCertificateTemplatesSection.tsxCertificateTemplatesTable.tsxCertificatesSection.tsxCertificatesTable.tsxCertificatesTable.utils.tsindex.tsx
index.tsxPkiAlertsTab
PkiAlertsTab.tsx
index.tsxcomponents
PkiAlertModal.tsxPkiAlertRow.tsxPkiAlertsSection.tsxPkiAlertsTable.tsxPkiCollectionModal.tsxPkiCollectionSection.tsxPkiCollectionTable.tsxindex.tsx
index.tsxPkiCollectionDetailsByIDPage
PkiCollectionDetailsByIDPage.tsx
components
AddPkiCollectionItemModal.tsxPkiCollectionDetailsSection.tsxPkiCollectionItemsSection.tsxPkiCollectionItemsTable.tsxindex.tsx
routes.tsxSettingsPage
SettingsPage.tsx
components
route.tsx[id]
allowlist
ca/[caId]
certificates
identities/[identityId]
members
pki-collections/[collectionId]
roles/[roleSlug]
settings
integrations
[id].tsx
azure-app-configuration/oauth2
azure-key-vault/oauth2
bitbucket/oauth2
details
gcp-secret-manager/oauth2
github/oauth2
heroku/oauth2
netlify/oauth2
vercel/oauth2
kms
OverviewPage
SettingsPage
SettingsPage.tsx
components
route.tsx[id]
allowlist
identities/[identityId]
kms
members
roles/[roleSlug]
settings
login
middlewares
org
[id]
admin
audit-logs
billing
cert-manager
groups/[groupId]
identities/[identityId]
kms
members
memberships/[membershipId]
overview
roles/[roleId]
secret-sharing
settings
ssh
none
organization
AccessManagementPage
AccessManagementPage.tsxroute.tsx
components
OrgGroupsTab
OrgIdentityTab
OrgIdentityTab.tsxindex.tsx
components
IdentitySection
IdentityAuthMethodModal.tsxIdentityAuthMethodModalContent.tsxIdentityAwsAuthForm.tsxIdentityAzureAuthForm.tsxIdentityGcpAuthForm.tsxIdentityJwtAuthForm.tsxIdentityKubernetesAuthForm.tsxIdentityModal.tsxIdentityOidcAuthForm.tsxIdentitySection.tsxIdentityTable.tsxIdentityTokenAuthForm.tsxIdentityTokenAuthTokenModal.tsxIdentityUniversalAuthClientSecretModal.tsxIdentityUniversalAuthForm.tsxindex.tsx
index.tsxOrgMembersTab
OrgRoleTabSection
index.tsxAdminPage
AppConnections/GithubOauthCallbackPage
AuditLogsPage
BillingPage
BillingPage.tsxroute.tsx
components
BillingCloudTab
BillingCloudTab.tsxCurrentPlanSection.tsxManagePlansModal.tsxManagePlansTable.tsxPreviewSection.tsxindex.tsx
BillingDetailsTab
BillingDetailsTab.tsxCompanyNameSection.tsxInvoiceEmailSection.tsxPmtMethodsSection.tsxPmtMethodsTable.tsxTaxIDModal.tsxTaxIDSection.tsxTaxIDTable.tsxindex.tsx
BillingReceiptsTab
BillingSelfHostedTab
BillingTabGroup
index.tsxCertManagerOverviewPage
GroupDetailsByIDPage
GroupDetailsByIDPage.tsx
components
AddGroupMemberModal.tsxGroupCreateUpdateModal.tsxGroupDetailsSection.tsx
route.tsxGroupMembersSection
index.tsxIdentityDetailsByIDPage
IdentityDetailsByIDPage.tsxroute.tsx
components
IdentityAuthenticationSection
IdentityClientSecretModal.tsxIdentityDetailsSection.tsxIdentityProjectsSection
IdentityAddToProjectModal.tsxIdentityProjectRow.tsxIdentityProjectsSection.tsxIdentityProjectsTable.tsxindex.tsx
IdentityTokenListModal.tsxIdentityTokenModal.tsxindex.tsxKmsOverviewPage
NoOrgPage
RoleByIDPage
RoleByIDPage.tsx
components
OrgRoleModifySection.utils.tsRoleDetailsSection.tsxRoleModal.tsx
route.tsxRolePermissionsSection
OrgPermissionAdminConsoleRow.tsxOrgRoleWorkspaceRow.tsxRolePermissionRow.tsxRolePermissionsSection.tsxindex.tsx
index.tsxSecretManagerOverviewPage
SecretScanningPage
SecretSharingPage
SettingsPage
SettingsPage.tsxroute.tsx
components
AppConnectionsTab
AppConnectionsTab.tsx
components
AddAppConnectionModal.tsx
index.tsxAppConnectionForm
AppConnectionForm.tsxAwsConnectionForm.tsxGenericAppConnectionFields.tsxGitHubConnectionForm.tsxindex.ts
AppConnectionHeader.tsxAppConnectionList.tsxAppConnectionRow.tsxAppConnectionsTable.tsxDeleteAppConnectionModal.tsxEditAppConnectionCredentialsModal.tsxEditAppConnectionDetailsModal.tsxindex.tsxAuditLogStreamTab
ImportTab
OrgAuthTab
ExternalGroupOrgRoleMappings.tsxLDAPGroupMapModal.tsxLDAPModal.tsxOIDCModal.tsxOrgAuthTab.tsxOrgGeneralAuthSection.tsxOrgGenericAuthSection.tsxOrgLDAPSection.tsxOrgOIDCSection.tsxOrgSCIMSection.tsxOrgSSOSection.tsxSSOModal.tsxScimTokenModal.tsxindex.tsx
OrgDeleteSection
OrgEncryptionTab
AddExternalKmsForm.tsxAwsKmsForm.tsxGcpKmsForm.tsxOrgEncryptionTab.tsxUpdateExternalKmsForm.tsxindex.tsx
OrgGeneralTab
OrgIncidentContactsSection
OrgNameChangeSection
OrgTabGroup
OrgWorkflowIntegrationTab
AddWorkflowIntegrationForm.tsxIntegrationFormDetails.tsxOrgWorkflowIntegrationTab.tsxSlackIntegrationForm.tsx
ProjectTemplatesTab
ProjectTemplatesTab.tsx
index.tsxcomponents
DeleteProjectTemplateModal.tsx
index.tsxEditProjectTemplateSection
EditProjectTemplateSection.tsx
ProjectTemplateDetailsModal.tsxProjectTemplatesSection.tsxProjectTemplatesTable.tsxindex.tsxcomponents
EditProjectTemplate.tsxProjectTemplateEditRoleForm.tsxProjectTemplateEnvironmentsForm.tsxProjectTemplateRolesSection.tsxindex.tsx
index.tsxSshOverviewPage
UserDetailsByIDPage
UserDetailsByIDPage.tsx
layout.tsxcomponents
UserDetailsSection.tsxUserOrgMembershipModal.tsx
route.tsxUserProjectsSection
UserAddToProjectModal.tsxUserAuditLogsSection.tsxUserGroupsRow.tsxUserGroupsSection.tsxUserGroupsTable.tsxUserProjectRow.tsxUserProjectsSection.tsxUserProjectsTable.tsxindex.tsx
index.tsxproject
AccessControlPage
AccessControlPage.tsxroute-cert-manager.tsxroute-kms.tsxroute-secret-manager.tsxroute-ssh.tsx
components
GroupsTab
IdentityTab
MembersTab
MembersTab.tsx
components
index.tsxProjectRoleListTab
ServiceTokenTab
index.tsxIdentityDetailsByIDPage
IdentityDetailsByIDPage.tsxroute-cert-manager.tsxroute-kms.tsxroute-secret-manager.tsxroute-ssh.tsx
components
IdentityProjectAdditionalPrivilegeSection
IdentityProjectAdditionalPrivilegeModifySection.tsxIdentityProjectAdditionalPrivilegeSection.tsxindex.tsx
IdentityRoleDetailsSection
MemberDetailsByIDPage
MemberDetailsByIDPage.tsxroute-cert-manager.tsxroute-kms.tsxroute-secret-manager.tsxroute-ssh.tsx
components
MemberProjectAdditionalPrivilegeSection
MemberProjectAdditionalPrivilegeSection.tsxMembershipProjectAdditionalPrivilegeModifySection.tsxindex.tsx
MemberRoleDetailsSection
RoleDetailsBySlugPage
RoleDetailsBySlugPage.tsx
components
GeneralPermissionConditions.tsxGeneralPermissionPolicies.tsxIdentityManagementPermissionConditions.tsxNewPermissionRule.tsxPermissionConditionHelpers.tsxPermissionEmptyState.tsxProjectRoleModifySection.utils.tsxRoleDetailsSection.tsxRoleModal.tsxRolePermissionsSection.tsxSecretPermissionConditions.tsx
route-cert-manager.tsxroute-kms.tsxroute-secret-manager.tsxroute-ssh.tsxpublic
ErrorPage
NotFoundPage
ShareSecretPage
ViewSharedSecretByIDPage
secret-manager
IPAllowlistPage
IntegrationsDetailsByIDPage
IntegrationsDetailsByIDPage.tsxIntegrationsDetailsByIDPage.utils.ts
components
IntegrationAuditLogsSection.tsxIntegrationConnectionSection.tsxIntegrationDetailsSection.tsxIntegrationSettingsSection.tsxOctopusDeployScopeValues.tsx
route.tsxIntegrationsListPage
IntegrationsListPage.tsxIntegrationsListPage.utils.tsxroute.tsx
components
CloudIntegrationSection
FrameworkIntegrationSection
InfrastructureIntegrationSection
IntegrationsSection
json
OverviewPage
OverviewPage.tsxroute.tsx
components
CreateSecretForm
FolderBreadCrumbs
SecretOverviewDynamicSecretRow
SecretOverviewFolderRow
SecretOverviewTableRow
SecretEditRow.tsxSecretNoAccessOverviewTableRow.tsxSecretOverviewTableRow.tsxSecretRenameRow.tsxindex.tsx
SecretSearchInput
SecretSearchInput.tsx
components
QuickSearchDynamicSecretItem.tsxQuickSearchFolderItem.tsxQuickSearchModal.tsxQuickSearchSecretItem.tsxindex.tsx
index.tsxSecretTableResourceCount
SecretV2MigrationSection
SelectionPanel
SecretApprovalsPage
SecretApprovalsPage.tsxroute.tsx
components
AccessApprovalRequest
ApprovalPolicyList
SecretApprovalRequest
SecretDashboardPage
SecretDashboardPage.tsxSecretMainPage.store.tsxSecretMainPage.types.tsroute.tsx
components
ActionBar
ActionBar.tsx
CreateDynamicSecretForm
AwsElastiCacheInputForm.tsxAwsIamInputForm.tsxAzureEntraIdInputForm.tsxCassandraInputForm.tsxCreateDynamicSecretForm.tsxElasticSearchInputForm.tsxLdapInputForm.tsxMongoAtlasInputForm.tsxMongoDBInputForm.tsxRabbitMqInputForm.tsxRedisInputForm.tsxSapAseInputForm.tsxSapHanaInputForm.tsxSnowflakeInputForm.tsxSqlDatabaseInputForm.tsxTotpInputForm.tsxindex.tsx
CreateSecretImportForm.tsxFolderForm.tsxMoveSecretsModal.tsxindex.tsxCreateSecretForm
DynamicSecretListView
CreateDynamicSecretLease.tsxDynamicSecretLease.tsxDynamicSecretListView.tsx
EditDynamicSecretForm
EditDynamicSecretAwsElastiCacheProviderForm.tsxEditDynamicSecretAwsIamForm.tsxEditDynamicSecretAzureEntraIdForm.tsxEditDynamicSecretCassandraForm.tsxEditDynamicSecretElasticSearchForm.tsxEditDynamicSecretForm.tsxEditDynamicSecretLdapForm.tsxEditDynamicSecretMongoAtlasForm.tsxEditDynamicSecretMongoDBForm.tsxEditDynamicSecretRabbitMqForm.tsxEditDynamicSecretRedisProviderForm.tsxEditDynamicSecretSapAseForm.tsxEditDynamicSecretSapHanaForm.tsxEditDynamicSecretSnowflakeForm.tsxEditDynamicSecretSqlProviderForm.tsxEditDynamicSecretTotpForm.tsxindex.tsx
RenewDynamicSecretLease.tsxindex.tsxFolderListView
PitDrawer
SecretDropzone
SecretImportListView
SecretListView
CreateReminderForm.tsxGenRandomNumber.tsxSecretDetailSidebar.tsxSecretItem.tsxSecretListView.tsxSecretListView.utils.tsSecretNoAccessListView.tsxindex.tsx
SnapshotView
SecretRotationPage
SettingsPage
SettingsPage.tsxroute.tsx
components
AuditLogsRetentionSection
AutoCapitalizationSection
BackfillSecretReferenceSection
DeleteProjectSection
EncryptionTab
EnvironmentSection
AddEnvironmentModal.tsxEnvironmentSection.tsxEnvironmentTable.tsxUpdateEnvironmentModal.tsxindex.tsx
PointInTimeVersionLimitSection
ProjectGeneralTab
ProjectOverviewChangeSection
RebuildSecretIndicesSection
SecretTagsSection
WebhooksTab
WorkflowIntegrationSection
index.tsx[id]
allowlist
approval
identities/[identityId]
members
roles/[roleSlug]
secret-rotation
secrets
settings
integrations
AwsParameterStoreAuthorizePage
AwsParameterStoreConfigurePage
AwsSecretManagerAuthorizePage
AwsSecretManagerConfigurePage
AzureAppConfigurationConfigurePage
AzureAppConfigurationOauthCallbackPage
AzureDevopsAuthorizePage
AzureDevopsConfigurePage
AzureKeyVaultAuthorizePage
AzureKeyVaultConfigurePage
AzureKeyVaultOauthCallbackPage
BitbucketConfigurePage
BitbucketOauthCallbackPage
ChecklyAuthorizePage
ChecklyConfigurePage
CircleCIAuthorizePage
CircleCIConfigurePage
Cloud66AuthorizePage
Cloud66ConfigurePage
CloudflarePagesAuthorizePage
CloudflarePagesConfigurePage
CloudflareWorkersAuthorizePage
CloudflareWorkersConfigurePage
CodefreshAuthorizePage
CodefreshConfigurePage
DatabricksAuthorizePage
DatabricksConfigurePage
DigitalOceanAppPlatformAuthorizePage
DigitalOceanAppPlatformConfigurePage
FlyioAuthorizePage
FlyioConfigurePage
GcpSecretManagerAuthorizePage
GcpSecretManagerConfigurePage
GcpSecretManagerOauthCallbackPage
GithubAuthorizePage
GithubConfigurePage
GithubOauthCallbackPage
GitlabAuthorizePage
GitlabConfigurePage
GitlabOauthCallbackPage
HashicorpVaultAuthorizePage
HashicorpVaultConfigurePage
HasuraCloudAuthorizePage
HasuraCloudConfigurePage
HerokuConfigurePage
HerokuOauthCallbackPage
LaravelForgeAuthorizePage
LaravelForgeConfigurePage
NetlifyConfigurePage
NetlifyOauthCallbackPage
NorthflankAuthorizePage
NorthflankConfigurePage
OctopusDeployAuthorizePage
OctopusDeployConfigurePage
QoveryAuthorizePage
QoveryConfigurePage
RailwayAuthorizePage
RailwayConfigurePage
RenderAuthorizePage
RenderConfigurePage
RundeckAuthorizePage
RundeckConfigurePage
SelectIntegrationAuthPage
SupabaseAuthorizePage
SupabaseConfigurePage
TeamcityAuthorizePage
TeamcityConfigurePage
TerraformCloudAuthorizePage
TerraformCloudConfigurePage
TravisCIAuthorizePage
TravisCIConfigurePage
VercelConfigurePage
VercelOauthCallbackPage
WindmillAuthorizePage
WindmillConfigurePage
route-azure-app-configurations-oauth-redirect.tsxroute-azure-key-vault-oauth-redirect.tsxroute-bitbucket-oauth-redirect.tsxroute-gcp-oauth-redirect.tsxroute-github-oauth-redirect.tsxroute-gitlab-oauth-redirect.tsxroute-heroku-oauth-redirect.tsxroute-netlify-oauth-redirect.tsxroute-vercel-oauth-redirect.tsxshare-secret
shared/secret/[id]
signup/sso
ssh
OverviewPage
OverviewPage.tsx
components
SshCaModal.tsxSshCaSection.tsxSshCaTable.tsxSshCertificatesSection.tsxSshCertificatesTable.tsxSshCertificatesTable.utils.tsindex.tsx
route.tsxSettingsPage
SettingsPage.tsx
components
route.tsxSshCaByIDPage
SshCaByIDPage.tsx
components
SshCaDetailsSection.tsxSshCertificateContent.tsxSshCertificateModal.tsxSshCertificateTemplateModal.tsxSshCertificateTemplatesSection.tsxSshCertificateTemplatesTable.tsxindex.tsx
route.tsx[id]
allowlist
ca/[caId]
identities/[identityId]
members
roles/[roleSlug]
settings
ssh
user
PersonalSettingsPage
PersonalSettingsPage.tsxroute.tsx
layout.tsxcomponents
APIKeySection
AuthMethodSection
ChangePasswordSection
DeleteAccountSection
EmergencyKitSection
PersonalAPIKeyTab
PersonalAuthTab
PersonalGeneralTab
PersonalTabGroup
SecuritySection
SessionsSection
UserNameSection
services
translation.tsxtypes
views
IntegrationsPage
Login
Org
AuditLogsPage
GroupPage
IdentityPage
MembersPage
NonePage
RolePage
Types
UserPage
OrgAdminPage
Project
CaPage
CertificatesPage
IPAllowListPage
IdentityDetailsPage
KmsPage
MemberDetailsPage
MembersPage
PkiCollectionPage
RolePage
SshCaPage
SshPage
Types
SecretApprovalPage
SecretMainPage
components
index.tsxSecretOverviewPage
SecretRotationPage
Settings
BillingSettingsPage
OrgSettingsPage
PersonalSettingsPage
ProjectSettingsPage
ShareSecretPage
ShareSecretPublicPage
Signup
ViewSecretPublicPage
admin
nginx
package-lock.jsonpackage.jsonstandalone-entrypoint.sh
8
.github/workflows/check-fe-ts-and-lint.yml
vendored
8
.github/workflows/check-fe-ts-and-lint.yml
vendored
@ -18,18 +18,18 @@ jobs:
|
||||
steps:
|
||||
- name: ☁️ Checkout source
|
||||
uses: actions/checkout@v3
|
||||
- name: 🔧 Setup Node 16
|
||||
- name: 🔧 Setup Node 20
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: "16"
|
||||
node-version: "20"
|
||||
cache: "npm"
|
||||
cache-dependency-path: frontend/package-lock.json
|
||||
- name: 📦 Install dependencies
|
||||
run: npm install
|
||||
working-directory: frontend
|
||||
- name: 🏗️ Run Type check
|
||||
run: npm run type:check
|
||||
run: npm run type:check
|
||||
working-directory: frontend
|
||||
- name: 🏗️ Run Link check
|
||||
run: npm run lint:fix
|
||||
run: npm run lint:fix
|
||||
working-directory: frontend
|
||||
|
@ -8,7 +8,7 @@ FROM node:20-slim AS base
|
||||
FROM base AS frontend-dependencies
|
||||
WORKDIR /app
|
||||
|
||||
COPY frontend/package.json frontend/package-lock.json frontend/next.config.js ./
|
||||
COPY frontend/package.json frontend/package-lock.json ./
|
||||
|
||||
# Install dependencies
|
||||
RUN npm ci --only-production --ignore-scripts
|
||||
@ -23,17 +23,16 @@ COPY --from=frontend-dependencies /app/node_modules ./node_modules
|
||||
COPY /frontend .
|
||||
|
||||
ENV NODE_ENV production
|
||||
ENV NEXT_PUBLIC_ENV production
|
||||
ARG POSTHOG_HOST
|
||||
ENV NEXT_PUBLIC_POSTHOG_HOST $POSTHOG_HOST
|
||||
ENV VITE_POSTHOG_HOST $POSTHOG_HOST
|
||||
ARG POSTHOG_API_KEY
|
||||
ENV NEXT_PUBLIC_POSTHOG_API_KEY $POSTHOG_API_KEY
|
||||
ENV VITE_POSTHOG_API_KEY $POSTHOG_API_KEY
|
||||
ARG INTERCOM_ID
|
||||
ENV NEXT_PUBLIC_INTERCOM_ID $INTERCOM_ID
|
||||
ENV VITE_INTERCOM_ID $INTERCOM_ID
|
||||
ARG INFISICAL_PLATFORM_VERSION
|
||||
ENV NEXT_PUBLIC_INFISICAL_PLATFORM_VERSION $INFISICAL_PLATFORM_VERSION
|
||||
ENV VITE_INFISICAL_PLATFORM_VERSION $INFISICAL_PLATFORM_VERSION
|
||||
ARG CAPTCHA_SITE_KEY
|
||||
ENV NEXT_PUBLIC_CAPTCHA_SITE_KEY $CAPTCHA_SITE_KEY
|
||||
ENV VITE_CAPTCHA_SITE_KEY $CAPTCHA_SITE_KEY
|
||||
|
||||
# Build
|
||||
RUN npm run build
|
||||
@ -44,20 +43,10 @@ WORKDIR /app
|
||||
|
||||
RUN groupadd -r -g 1001 nodejs && useradd -r -u 1001 -g nodejs non-root-user
|
||||
|
||||
RUN mkdir -p /app/.next/cache/images && chown non-root-user:nodejs /app/.next/cache/images
|
||||
VOLUME /app/.next/cache/images
|
||||
|
||||
COPY --chown=non-root-user:nodejs --chmod=555 frontend/scripts ./scripts
|
||||
COPY --from=frontend-builder /app/public ./public
|
||||
RUN chown non-root-user:nodejs ./public/data
|
||||
|
||||
COPY --from=frontend-builder --chown=non-root-user:nodejs /app/.next/standalone ./
|
||||
COPY --from=frontend-builder --chown=non-root-user:nodejs /app/.next/static ./.next/static
|
||||
COPY --from=frontend-builder --chown=non-root-user:nodejs /app/dist ./
|
||||
|
||||
USER non-root-user
|
||||
|
||||
ENV NEXT_TELEMETRY_DISABLED 1
|
||||
|
||||
##
|
||||
## BACKEND
|
||||
##
|
||||
@ -137,7 +126,7 @@ RUN apt-get update && apt-get install -y \
|
||||
freetds-dev \
|
||||
freetds-bin \
|
||||
tdsodbc \
|
||||
openssh \
|
||||
openssh-client \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Configure ODBC in production
|
||||
@ -160,14 +149,11 @@ RUN chmod u+rx /usr/sbin/update-ca-certificates
|
||||
|
||||
## set pre baked keys
|
||||
ARG POSTHOG_API_KEY
|
||||
ENV NEXT_PUBLIC_POSTHOG_API_KEY=$POSTHOG_API_KEY \
|
||||
BAKED_NEXT_PUBLIC_POSTHOG_API_KEY=$POSTHOG_API_KEY
|
||||
ENV POSTHOG_API_KEY=$POSTHOG_API_KEY
|
||||
ARG INTERCOM_ID=intercom-id
|
||||
ENV NEXT_PUBLIC_INTERCOM_ID=$INTERCOM_ID \
|
||||
BAKED_NEXT_PUBLIC_INTERCOM_ID=$INTERCOM_ID
|
||||
ENV INTERCOM_ID=$INTERCOM_ID
|
||||
ARG CAPTCHA_SITE_KEY
|
||||
ENV NEXT_PUBLIC_CAPTCHA_SITE_KEY=$CAPTCHA_SITE_KEY \
|
||||
BAKED_NEXT_PUBLIC_CAPTCHA_SITE_KEY=$CAPTCHA_SITE_KEY
|
||||
ENV CAPTCHA_SITE_KEY=$CAPTCHA_SITE_KEY
|
||||
|
||||
WORKDIR /
|
||||
|
||||
@ -192,4 +178,4 @@ EXPOSE 443
|
||||
|
||||
USER non-root-user
|
||||
|
||||
CMD ["./standalone-entrypoint.sh"]
|
||||
CMD ["./standalone-entrypoint.sh"]
|
||||
|
@ -12,7 +12,7 @@ RUN apk add --no-cache libc6-compat
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
COPY frontend/package.json frontend/package-lock.json frontend/next.config.js ./
|
||||
COPY frontend/package.json frontend/package-lock.json ./
|
||||
|
||||
# Install dependencies
|
||||
RUN npm ci --only-production --ignore-scripts
|
||||
@ -27,17 +27,16 @@ COPY --from=frontend-dependencies /app/node_modules ./node_modules
|
||||
COPY /frontend .
|
||||
|
||||
ENV NODE_ENV production
|
||||
ENV NEXT_PUBLIC_ENV production
|
||||
ARG POSTHOG_HOST
|
||||
ENV NEXT_PUBLIC_POSTHOG_HOST $POSTHOG_HOST
|
||||
ENV VITE_POSTHOG_HOST $POSTHOG_HOST
|
||||
ARG POSTHOG_API_KEY
|
||||
ENV NEXT_PUBLIC_POSTHOG_API_KEY $POSTHOG_API_KEY
|
||||
ENV VITE_POSTHOG_API_KEY $POSTHOG_API_KEY
|
||||
ARG INTERCOM_ID
|
||||
ENV NEXT_PUBLIC_INTERCOM_ID $INTERCOM_ID
|
||||
ENV VITE_INTERCOM_ID $INTERCOM_ID
|
||||
ARG INFISICAL_PLATFORM_VERSION
|
||||
ENV NEXT_PUBLIC_INFISICAL_PLATFORM_VERSION $INFISICAL_PLATFORM_VERSION
|
||||
ENV VITE_INFISICAL_PLATFORM_VERSION $INFISICAL_PLATFORM_VERSION
|
||||
ARG CAPTCHA_SITE_KEY
|
||||
ENV NEXT_PUBLIC_CAPTCHA_SITE_KEY $CAPTCHA_SITE_KEY
|
||||
ENV VITE_CAPTCHA_SITE_KEY $CAPTCHA_SITE_KEY
|
||||
|
||||
# Build
|
||||
RUN npm run build
|
||||
@ -49,20 +48,10 @@ WORKDIR /app
|
||||
RUN addgroup --system --gid 1001 nodejs
|
||||
RUN adduser --system --uid 1001 non-root-user
|
||||
|
||||
RUN mkdir -p /app/.next/cache/images && chown non-root-user:nodejs /app/.next/cache/images
|
||||
VOLUME /app/.next/cache/images
|
||||
|
||||
COPY --chown=non-root-user:nodejs --chmod=555 frontend/scripts ./scripts
|
||||
COPY --from=frontend-builder /app/public ./public
|
||||
RUN chown non-root-user:nodejs ./public/data
|
||||
|
||||
COPY --from=frontend-builder --chown=non-root-user:nodejs /app/.next/standalone ./
|
||||
COPY --from=frontend-builder --chown=non-root-user:nodejs /app/.next/static ./.next/static
|
||||
COPY --from=frontend-builder --chown=non-root-user:nodejs /app/dist ./
|
||||
|
||||
USER non-root-user
|
||||
|
||||
ENV NEXT_TELEMETRY_DISABLED 1
|
||||
|
||||
##
|
||||
## BACKEND
|
||||
##
|
||||
@ -159,14 +148,11 @@ RUN chmod u+rx /usr/sbin/update-ca-certificates
|
||||
|
||||
## set pre baked keys
|
||||
ARG POSTHOG_API_KEY
|
||||
ENV NEXT_PUBLIC_POSTHOG_API_KEY=$POSTHOG_API_KEY \
|
||||
BAKED_NEXT_PUBLIC_POSTHOG_API_KEY=$POSTHOG_API_KEY
|
||||
ENV POSTHOG_API_KEY=$POSTHOG_API_KEY
|
||||
ARG INTERCOM_ID=intercom-id
|
||||
ENV NEXT_PUBLIC_INTERCOM_ID=$INTERCOM_ID \
|
||||
BAKED_NEXT_PUBLIC_INTERCOM_ID=$INTERCOM_ID
|
||||
ENV INTERCOM_ID=$INTERCOM_ID
|
||||
ARG CAPTCHA_SITE_KEY
|
||||
ENV NEXT_PUBLIC_CAPTCHA_SITE_KEY=$CAPTCHA_SITE_KEY \
|
||||
BAKED_NEXT_PUBLIC_CAPTCHA_SITE_KEY=$CAPTCHA_SITE_KEY
|
||||
ENV CAPTCHA_SITE_KEY=$CAPTCHA_SITE_KEY
|
||||
|
||||
|
||||
COPY --from=backend-runner /app /backend
|
||||
@ -189,4 +175,4 @@ EXPOSE 443
|
||||
|
||||
USER non-root-user
|
||||
|
||||
CMD ["./standalone-entrypoint.sh"]
|
||||
CMD ["./standalone-entrypoint.sh"]
|
||||
|
128
backend/package-lock.json
generated
128
backend/package-lock.json
generated
@ -26,6 +26,7 @@
|
||||
"@fastify/rate-limit": "^9.0.0",
|
||||
"@fastify/request-context": "^5.1.0",
|
||||
"@fastify/session": "^10.7.0",
|
||||
"@fastify/static": "^7.0.4",
|
||||
"@fastify/swagger": "^8.14.0",
|
||||
"@fastify/swagger-ui": "^2.1.0",
|
||||
"@google-cloud/kms": "^4.5.0",
|
||||
@ -5406,6 +5407,7 @@
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@fastify/accept-negotiator/-/accept-negotiator-1.1.0.tgz",
|
||||
"integrity": "sha512-OIHZrb2ImZ7XG85HXOONLcJWGosv7sIvM2ifAPQVhg9Lv7qdmMBNVaai4QTdyuaqbKM5eO6sLSQOYI7wEQeCJQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
}
|
||||
@ -5545,6 +5547,7 @@
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@fastify/send/-/send-2.1.0.tgz",
|
||||
"integrity": "sha512-yNYiY6sDkexoJR0D8IDy3aRP3+L4wdqCpvx5WP+VtEU58sn7USmKynBzDQex5X42Zzvw2gNzzYgP90UfWShLFA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@lukeed/ms": "^2.0.1",
|
||||
"escape-html": "~1.0.3",
|
||||
@ -5563,16 +5566,85 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@fastify/static": {
|
||||
"version": "6.12.0",
|
||||
"resolved": "https://registry.npmjs.org/@fastify/static/-/static-6.12.0.tgz",
|
||||
"integrity": "sha512-KK1B84E6QD/FcQWxDI2aiUCwHxMJBI1KeCUzm1BwYpPY1b742+jeKruGHP2uOluuM6OkBPI8CIANrXcCRtC2oQ==",
|
||||
"version": "7.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@fastify/static/-/static-7.0.4.tgz",
|
||||
"integrity": "sha512-p2uKtaf8BMOZWLs6wu+Ihg7bWNBdjNgCwDza4MJtTqg+5ovKmcbgbR9Xs5/smZ1YISfzKOCNYmZV8LaCj+eJ1Q==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@fastify/accept-negotiator": "^1.0.0",
|
||||
"@fastify/send": "^2.0.0",
|
||||
"content-disposition": "^0.5.3",
|
||||
"fastify-plugin": "^4.0.0",
|
||||
"glob": "^8.0.1",
|
||||
"p-limit": "^3.1.0"
|
||||
"fastq": "^1.17.0",
|
||||
"glob": "^10.3.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@fastify/static/node_modules/brace-expansion": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
|
||||
"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"balanced-match": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@fastify/static/node_modules/glob": {
|
||||
"version": "10.4.5",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz",
|
||||
"integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"foreground-child": "^3.1.0",
|
||||
"jackspeak": "^3.1.2",
|
||||
"minimatch": "^9.0.4",
|
||||
"minipass": "^7.1.2",
|
||||
"package-json-from-dist": "^1.0.0",
|
||||
"path-scurry": "^1.11.1"
|
||||
},
|
||||
"bin": {
|
||||
"glob": "dist/esm/bin.mjs"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/@fastify/static/node_modules/jackspeak": {
|
||||
"version": "3.4.3",
|
||||
"resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz",
|
||||
"integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==",
|
||||
"license": "BlueOak-1.0.0",
|
||||
"dependencies": {
|
||||
"@isaacs/cliui": "^8.0.2"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@pkgjs/parseargs": "^0.11.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@fastify/static/node_modules/minimatch": {
|
||||
"version": "9.0.5",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
|
||||
"integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"brace-expansion": "^2.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16 || 14 >=14.17"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/@fastify/static/node_modules/minipass": {
|
||||
"version": "7.1.2",
|
||||
"resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
|
||||
"integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
|
||||
"license": "ISC",
|
||||
"engines": {
|
||||
"node": ">=16 || 14 >=14.17"
|
||||
}
|
||||
},
|
||||
"node_modules/@fastify/swagger": {
|
||||
@ -5599,6 +5671,20 @@
|
||||
"yaml": "^2.2.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@fastify/swagger-ui/node_modules/@fastify/static": {
|
||||
"version": "6.12.0",
|
||||
"resolved": "https://registry.npmjs.org/@fastify/static/-/static-6.12.0.tgz",
|
||||
"integrity": "sha512-KK1B84E6QD/FcQWxDI2aiUCwHxMJBI1KeCUzm1BwYpPY1b742+jeKruGHP2uOluuM6OkBPI8CIANrXcCRtC2oQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@fastify/accept-negotiator": "^1.0.0",
|
||||
"@fastify/send": "^2.0.0",
|
||||
"content-disposition": "^0.5.3",
|
||||
"fastify-plugin": "^4.0.0",
|
||||
"glob": "^8.0.1",
|
||||
"p-limit": "^3.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@google-cloud/kms": {
|
||||
"version": "4.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@google-cloud/kms/-/kms-4.5.0.tgz",
|
||||
@ -6062,9 +6148,10 @@
|
||||
"integrity": "sha512-O89xFDLW2gBoZWNXuXpBSM32/KealKCTb3JGtJdtUQc7RjAk8XzrRgyz02cPAwGKwKPxy0ivuC7UP9bmN87egQ=="
|
||||
},
|
||||
"node_modules/@lukeed/ms": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@lukeed/ms/-/ms-2.0.1.tgz",
|
||||
"integrity": "sha512-Xs/4RZltsAL7pkvaNStUQt7netTkyxrS0K+RILcVr3TRMS/ToOg4I6uNfhB9SlGsnWBym4U+EaXq0f0cEMNkHA==",
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@lukeed/ms/-/ms-2.0.2.tgz",
|
||||
"integrity": "sha512-9I2Zn6+NJLfaGoz9jN3lpwDgAYvfGeNYdbAIjJOqzs4Tpc+VU3Jqq4IofSUBKajiDS8k9fZIg18/z13mpk1bsA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
@ -13879,9 +13966,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/express": {
|
||||
"version": "4.21.1",
|
||||
"resolved": "https://registry.npmjs.org/express/-/express-4.21.1.tgz",
|
||||
"integrity": "sha512-YSFlK1Ee0/GC8QaO91tHcDxJiE/X4FbpAyQWkxAvG6AXCuR65YzK8ua6D9hvi/TzUfZMpc+BwuM1IPw8fmQBiQ==",
|
||||
"version": "4.21.2",
|
||||
"resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz",
|
||||
"integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"accepts": "~1.3.8",
|
||||
@ -13903,7 +13990,7 @@
|
||||
"methods": "~1.1.2",
|
||||
"on-finished": "2.4.1",
|
||||
"parseurl": "~1.3.3",
|
||||
"path-to-regexp": "0.1.10",
|
||||
"path-to-regexp": "0.1.12",
|
||||
"proxy-addr": "~2.0.7",
|
||||
"qs": "6.13.0",
|
||||
"range-parser": "~1.2.1",
|
||||
@ -13918,6 +14005,10 @@
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.10.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/express"
|
||||
}
|
||||
},
|
||||
"node_modules/express-session": {
|
||||
@ -17388,15 +17479,16 @@
|
||||
}
|
||||
},
|
||||
"node_modules/nanoid": {
|
||||
"version": "3.3.7",
|
||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz",
|
||||
"integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==",
|
||||
"version": "3.3.8",
|
||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz",
|
||||
"integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/ai"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"nanoid": "bin/nanoid.cjs"
|
||||
},
|
||||
@ -18383,9 +18475,9 @@
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/path-to-regexp": {
|
||||
"version": "0.1.10",
|
||||
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.10.tgz",
|
||||
"integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==",
|
||||
"version": "0.1.12",
|
||||
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz",
|
||||
"integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/path-type": {
|
||||
|
@ -134,6 +134,7 @@
|
||||
"@fastify/rate-limit": "^9.0.0",
|
||||
"@fastify/request-context": "^5.1.0",
|
||||
"@fastify/session": "^10.7.0",
|
||||
"@fastify/static": "^7.0.4",
|
||||
"@fastify/swagger": "^8.14.0",
|
||||
"@fastify/swagger-ui": "^2.1.0",
|
||||
"@google-cloud/kms": "^4.5.0",
|
||||
|
@ -84,7 +84,10 @@ export const registerSamlRouter = async (server: FastifyZodProvider) => {
|
||||
samlConfig.audience = `spn:${ssoConfig.issuer}`;
|
||||
}
|
||||
}
|
||||
if (ssoConfig.authProvider === SamlProviders.GOOGLE_SAML) {
|
||||
if (
|
||||
ssoConfig.authProvider === SamlProviders.GOOGLE_SAML ||
|
||||
ssoConfig.authProvider === SamlProviders.AUTH0_SAML
|
||||
) {
|
||||
samlConfig.wantAssertionsSigned = false;
|
||||
}
|
||||
|
||||
@ -123,7 +126,10 @@ export const registerSamlRouter = async (server: FastifyZodProvider) => {
|
||||
`email: ${email} firstName: ${profile.firstName as string}`
|
||||
);
|
||||
|
||||
throw new Error("Invalid saml request. Missing email or first name");
|
||||
throw new BadRequestError({
|
||||
message:
|
||||
"Missing email or first name. Please double check your SAML attribute mapping for the selected provider."
|
||||
});
|
||||
}
|
||||
|
||||
const userMetadata = Object.keys(profile.attributes || {})
|
||||
|
@ -213,7 +213,7 @@ export const accessApprovalRequestServiceFactory = ({
|
||||
);
|
||||
|
||||
const requesterFullName = `${requestedByUser.firstName} ${requestedByUser.lastName}`;
|
||||
const approvalUrl = `${cfg.SITE_URL}/project/${project.id}/approval`;
|
||||
const approvalUrl = `${cfg.SITE_URL}/secret-manager/${project.id}/approval`;
|
||||
|
||||
await triggerSlackNotification({
|
||||
projectId: project.id,
|
||||
|
@ -6,7 +6,8 @@ export enum SamlProviders {
|
||||
AZURE_SAML = "azure-saml",
|
||||
JUMPCLOUD_SAML = "jumpcloud-saml",
|
||||
GOOGLE_SAML = "google-saml",
|
||||
KEYCLOAK_SAML = "keycloak-saml"
|
||||
KEYCLOAK_SAML = "keycloak-saml",
|
||||
AUTH0_SAML = "auth0-saml"
|
||||
}
|
||||
|
||||
export type TCreateSamlCfgDTO = {
|
||||
|
@ -36,7 +36,7 @@ export const sendApprovalEmailsFn = async ({
|
||||
firstName: reviewerUser.firstName,
|
||||
projectName: project.name,
|
||||
organizationName: project.organization.name,
|
||||
approvalUrl: `${cfg.SITE_URL}/project/${project.id}/approval?requestId=${secretApprovalRequest.id}`
|
||||
approvalUrl: `${cfg.SITE_URL}/secret-manager/${project.id}/approval?requestId=${secretApprovalRequest.id}`
|
||||
},
|
||||
template: SmtpTemplates.SecretApprovalRequestNeedsReview
|
||||
});
|
||||
|
@ -852,7 +852,7 @@ export const secretApprovalRequestServiceFactory = ({
|
||||
bypassReason,
|
||||
secretPath: policy.secretPath,
|
||||
environment: env.name,
|
||||
approvalUrl: `${cfg.SITE_URL}/project/${project.id}/approval`
|
||||
approvalUrl: `${cfg.SITE_URL}/secret-manager/${project.id}/approval`
|
||||
},
|
||||
template: SmtpTemplates.AccessSecretRequestBypassed
|
||||
});
|
||||
|
@ -157,6 +157,8 @@ const envSchema = z
|
||||
INFISICAL_CLOUD: zodStrBool.default("false"),
|
||||
MAINTENANCE_MODE: zodStrBool.default("false"),
|
||||
CAPTCHA_SECRET: zpStr(z.string().optional()),
|
||||
CAPTCHA_SITE_KEY: zpStr(z.string().optional()),
|
||||
INTERCOM_ID: zpStr(z.string().optional()),
|
||||
|
||||
// TELEMETRY
|
||||
OTEL_TELEMETRY_COLLECTION_ENABLED: zodStrBool.default("false"),
|
||||
|
@ -27,10 +27,10 @@ import { globalRateLimiterCfg } from "./config/rateLimiter";
|
||||
import { addErrorsToResponseSchemas } from "./plugins/add-errors-to-response-schemas";
|
||||
import { apiMetrics } from "./plugins/api-metrics";
|
||||
import { fastifyErrHandler } from "./plugins/error-handler";
|
||||
import { registerExternalNextjs } from "./plugins/external-nextjs";
|
||||
import { serializerCompiler, validatorCompiler, ZodTypeProvider } from "./plugins/fastify-zod";
|
||||
import { fastifyIp } from "./plugins/ip";
|
||||
import { maintenanceMode } from "./plugins/maintenanceMode";
|
||||
import { registerServeUI } from "./plugins/serve-ui";
|
||||
import { fastifySwagger } from "./plugins/swagger";
|
||||
import { registerRoutes } from "./routes";
|
||||
|
||||
@ -120,13 +120,10 @@ export const main = async ({ db, hsmModule, auditLogDb, smtp, logger, queue, key
|
||||
|
||||
await server.register(registerRoutes, { smtp, queue, db, auditLogDb, keyStore, hsmModule });
|
||||
|
||||
if (appCfg.isProductionMode) {
|
||||
await server.register(registerExternalNextjs, {
|
||||
standaloneMode: appCfg.STANDALONE_MODE || IS_PACKAGED,
|
||||
dir: path.join(__dirname, IS_PACKAGED ? "../../../" : "../../"),
|
||||
port: appCfg.PORT
|
||||
});
|
||||
}
|
||||
await server.register(registerServeUI, {
|
||||
standaloneMode: appCfg.STANDALONE_MODE || IS_PACKAGED,
|
||||
dir: path.join(__dirname, IS_PACKAGED ? "../../../" : "../../")
|
||||
});
|
||||
|
||||
await server.ready();
|
||||
server.swagger();
|
||||
|
@ -1,76 +0,0 @@
|
||||
// this plugins allows to run infisical in standalone mode
|
||||
// standalone mode = infisical backend and nextjs frontend in one server
|
||||
// this way users don't need to deploy two things
|
||||
import path from "node:path";
|
||||
|
||||
import { IS_PACKAGED } from "@app/lib/config/env";
|
||||
|
||||
// to enabled this u need to set standalone mode to true
|
||||
export const registerExternalNextjs = async (
|
||||
server: FastifyZodProvider,
|
||||
{
|
||||
standaloneMode,
|
||||
dir,
|
||||
port
|
||||
}: {
|
||||
standaloneMode?: boolean;
|
||||
dir: string;
|
||||
port: number;
|
||||
}
|
||||
) => {
|
||||
if (standaloneMode) {
|
||||
const frontendName = IS_PACKAGED ? "frontend" : "frontend-build";
|
||||
const nextJsBuildPath = path.join(dir, frontendName);
|
||||
|
||||
const { default: conf } = (await import(
|
||||
path.join(dir, `${frontendName}/.next/required-server-files.json`),
|
||||
// @ts-expect-error type
|
||||
{
|
||||
assert: { type: "json" }
|
||||
}
|
||||
)) as { default: { config: string } };
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
let NextServer: any;
|
||||
|
||||
if (!IS_PACKAGED) {
|
||||
/* eslint-disable */
|
||||
const { default: nextServer } = (
|
||||
await import(path.join(dir, `${frontendName}/node_modules/next/dist/server/next-server.js`))
|
||||
).default;
|
||||
|
||||
NextServer = nextServer;
|
||||
} else {
|
||||
/* eslint-disable */
|
||||
const nextServer = await import(path.join(dir, `${frontendName}/node_modules/next/dist/server/next-server.js`));
|
||||
|
||||
NextServer = nextServer.default;
|
||||
}
|
||||
|
||||
const nextApp = new NextServer({
|
||||
dev: false,
|
||||
dir: nextJsBuildPath,
|
||||
port,
|
||||
conf: conf.config,
|
||||
hostname: "local",
|
||||
customServer: false
|
||||
});
|
||||
|
||||
server.route({
|
||||
method: ["GET", "PUT", "PATCH", "POST", "DELETE"],
|
||||
url: "/*",
|
||||
schema: {
|
||||
hide: true
|
||||
},
|
||||
handler: (req, res) =>
|
||||
nextApp
|
||||
.getRequestHandler()(req.raw, res.raw)
|
||||
.then(() => {
|
||||
res.hijack();
|
||||
})
|
||||
});
|
||||
server.addHook("onClose", () => nextApp.close());
|
||||
await nextApp.prepare();
|
||||
/* eslint-enable */
|
||||
}
|
||||
};
|
54
backend/src/server/plugins/serve-ui.ts
Normal file
54
backend/src/server/plugins/serve-ui.ts
Normal file
@ -0,0 +1,54 @@
|
||||
import path from "node:path";
|
||||
|
||||
import staticServe from "@fastify/static";
|
||||
|
||||
import { getConfig, IS_PACKAGED } from "@app/lib/config/env";
|
||||
|
||||
// to enabled this u need to set standalone mode to true
|
||||
export const registerServeUI = async (
|
||||
server: FastifyZodProvider,
|
||||
{
|
||||
standaloneMode,
|
||||
dir
|
||||
}: {
|
||||
standaloneMode?: boolean;
|
||||
dir: string;
|
||||
}
|
||||
) => {
|
||||
// use this only for frontend runtime static non-sensitive configuration in standalone mode
|
||||
// that app needs before loading like posthog dsn key
|
||||
// for most of the other usecase use server config
|
||||
server.route({
|
||||
method: "GET",
|
||||
url: "/runtime-ui-env.js",
|
||||
handler: (_req, res) => {
|
||||
const appCfg = getConfig();
|
||||
void res.type("application/javascript");
|
||||
const config = {
|
||||
CAPTCHA_SITE_KEY: appCfg.CAPTCHA_SITE_KEY,
|
||||
POSTHOG_API_KEY: appCfg.POSTHOG_PROJECT_API_KEY,
|
||||
INTERCOM_ID: appCfg.INTERCOM_ID,
|
||||
TELEMETRY_CAPTURING_ENABLED: appCfg.TELEMETRY_ENABLED
|
||||
};
|
||||
const js = `window.__INFISICAL_RUNTIME_ENV__ = Object.freeze(${JSON.stringify(config)});`;
|
||||
void res.send(js);
|
||||
}
|
||||
});
|
||||
|
||||
if (standaloneMode) {
|
||||
const frontendName = IS_PACKAGED ? "frontend" : "frontend-build";
|
||||
const frontendPath = path.join(dir, frontendName);
|
||||
await server.register(staticServe, {
|
||||
root: frontendPath,
|
||||
wildcard: false
|
||||
});
|
||||
|
||||
server.get("/*", (request, reply) => {
|
||||
if (request.url.startsWith("/api")) {
|
||||
reply.callNotFound();
|
||||
return;
|
||||
}
|
||||
void reply.sendFile("index.html");
|
||||
});
|
||||
}
|
||||
};
|
@ -63,7 +63,8 @@ export const registerAuthRoutes = async (server: FastifyZodProvider) => {
|
||||
schema: {
|
||||
response: {
|
||||
200: z.object({
|
||||
token: z.string()
|
||||
token: z.string(),
|
||||
organizationId: z.string().optional()
|
||||
})
|
||||
}
|
||||
},
|
||||
@ -115,7 +116,7 @@ export const registerAuthRoutes = async (server: FastifyZodProvider) => {
|
||||
{ expiresIn: appCfg.JWT_AUTH_LIFETIME }
|
||||
);
|
||||
|
||||
return { token };
|
||||
return { token, organizationId: decodedToken.organizationId };
|
||||
}
|
||||
});
|
||||
};
|
||||
|
@ -331,12 +331,8 @@ export const registerSlackRouter = async (server: FastifyZodProvider) => {
|
||||
failureAsync: async () => {
|
||||
return res.redirect(appCfg.SITE_URL as string);
|
||||
},
|
||||
successAsync: async (installation) => {
|
||||
const metadata = JSON.parse(installation.metadata || "") as {
|
||||
orgId: string;
|
||||
};
|
||||
|
||||
return res.redirect(`${appCfg.SITE_URL}/org/${metadata.orgId}/settings?selectedTab=workflow-integrations`);
|
||||
successAsync: async () => {
|
||||
return res.redirect(`${appCfg.SITE_URL}/organization/settings?selectedTab=workflow-integrations`);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -1167,7 +1167,8 @@ const syncSecretsAWSSecretManager = async ({
|
||||
} else {
|
||||
await secretsManager.send(
|
||||
new DeleteSecretCommand({
|
||||
SecretId: secretId
|
||||
SecretId: secretId,
|
||||
ForceDeleteWithoutRecovery: true
|
||||
})
|
||||
);
|
||||
}
|
||||
|
@ -51,7 +51,7 @@ const buildSlackPayload = (notification: TSlackNotification) => {
|
||||
*Environment*: ${payload.environment}
|
||||
*Secret path*: ${payload.secretPath || "/"}
|
||||
|
||||
View the complete details <${appCfg.SITE_URL}/project/${payload.projectId}/approval?requestId=${
|
||||
View the complete details <${appCfg.SITE_URL}/secret-manager/${payload.projectId}/approval?requestId=${
|
||||
payload.requestId
|
||||
}|here>.`;
|
||||
|
||||
|
@ -19,7 +19,7 @@ Every new joiner has an onboarding buddy who should ideally be in the the same t
|
||||
1. Join the weekly all-hands meeting. It typically happens on Monday's at 8:30am PT.
|
||||
2. Ship something together on day one – even if tiny! It feels great to hit the ground running, with a development environment all ready to go.
|
||||
3. Check out the [Areas of Responsibility (AoR) Table](https://docs.google.com/spreadsheets/d/1RnXlGFg83Sgu0dh7ycuydsSobmFfI3A0XkGw7vrVxEI/edit?usp=sharing). This is helpful to know who you can ask about particular areas of Infisical. Feel free to add yourself to the areas you'd be most interesting to dive into.
|
||||
4. Read the [Infisical Strategy Doc](https://docs.google.com/document/d/1RaJd3RoS2QpWLFHlgfHaXnHqCCwRt6mCGZkbJ75J_D0/edit?usp=sharing).
|
||||
4. Read the [Infisical Strategy Doc](https://docs.google.com/document/d/1uV9IaahYwbZ5OuzDTFdQMSa1P0mpMOnetGB-xqf4G40).
|
||||
5. Update your LinkedIn profile with one of [Infisical's official banners](https://drive.google.com/drive/u/0/folders/1oSNWjbpRl9oNYwxM_98IqzKs9fAskrb2) (if you want to). You can also coordinate your social posts in the #marketing Slack channel, so that we can boost it from Infisical's official social media accounts.
|
||||
6. Over the first few weeks, feel free to schedule 1:1s with folks on the team to get to know them a bit better.
|
||||
7. Change your Slack username in the users channel to `[NAME] (Infisical)`.
|
||||
|
@ -144,9 +144,6 @@ services:
|
||||
- ./frontend/src:/app/src/ # mounted whole src to avoid missing reload on new files
|
||||
- ./frontend/public:/app/public
|
||||
env_file: .env
|
||||
environment:
|
||||
- NEXT_PUBLIC_ENV=development
|
||||
- INFISICAL_TELEMETRY_ENABLED=false
|
||||
|
||||
pgadmin:
|
||||
image: dpage/pgadmin4
|
||||
|
@ -4,6 +4,13 @@ sidebarTitle: "Overview"
|
||||
description: "Learn how to generate secrets dynamically on-demand."
|
||||
---
|
||||
|
||||
<Info>
|
||||
Note that Dynamic Secrets is a paid feature.
|
||||
|
||||
If you're using Infisical Cloud, then it is available under the **Enterprise Tier**
|
||||
If you're self-hosting Infisical, then you should contact sales@infisical.com to purchase an enterprise license to use it.
|
||||
</Info>
|
||||
|
||||
## Introduction
|
||||
|
||||
Contrary to static key-value secrets, which require manual input of data into the secure Infisical storage, **dynamic secrets are generated on-demand upon access**.
|
||||
|
@ -3,6 +3,13 @@ title: "Approval Workflows"
|
||||
description: "Learn how to enable a set of policies to manage changes to sensitive secrets and environments."
|
||||
---
|
||||
|
||||
<Info>
|
||||
Approval Workflows is a paid feature.
|
||||
|
||||
If you're using Infisical Cloud, then it is available under the **Pro Tier** and **Enterprise Tire**.
|
||||
If you're self-hosting Infisical, then you should contact sales@infisical.com to purchase an enterprise license to use it.
|
||||
</Info>
|
||||
|
||||
## Problem at hand
|
||||
|
||||
Updating secrets in high-stakes environments (e.g., production) can have a number of problematic issues:
|
||||
@ -40,4 +47,4 @@ When a user submits a change to an enviropnment that is under a particular polic
|
||||
|
||||
Approvers are notified by email and/or Slack as soon as the request is initiated. In the Infisical Dashboard, they will be able to `approve` and `merge` (or `deny`) a request for a change in a particular environment. After that, depending on the workflows setup, the change will be automatically propagated to the right applications (e.g., using [Infisical Kubernetes Operator](https://infisical.com/docs/integrations/platforms/kubernetes)).
|
||||
|
||||

|
||||

|
||||
|
@ -15,7 +15,7 @@ Prerequisites:
|
||||
|
||||
<Steps>
|
||||
<Step title="Create a SCIM token in Infisical">
|
||||
In Infisical, head to your Organization Settings > Authentication > SCIM Configuration and
|
||||
In Infisical, head to your Organization Settings > Security > SCIM Configuration and
|
||||
press the **Enable SCIM provisioning** toggle to allow Azure to provision/deprovision users for your organization.
|
||||
|
||||

|
||||
|
@ -15,7 +15,7 @@ Prerequisites:
|
||||
|
||||
<Steps>
|
||||
<Step title="Create a SCIM token in Infisical">
|
||||
In Infisical, head to your Organization Settings > Authentication > SCIM Configuration and
|
||||
In Infisical, head to your Organization Settings > Security > SCIM Configuration and
|
||||
press the **Enable SCIM provisioning** toggle to allow JumpCloud to provision/deprovision users and user groups for your organization.
|
||||
|
||||

|
||||
|
@ -15,7 +15,7 @@ Prerequisites:
|
||||
|
||||
<Steps>
|
||||
<Step title="Create a SCIM token in Infisical">
|
||||
In Infisical, head to your Organization Settings > Authentication > SCIM Configuration and
|
||||
In Infisical, head to your Organization Settings > Security > SCIM Configuration and
|
||||
press the **Enable SCIM provisioning** toggle to allow Okta to provision/deprovision users and user groups for your organization.
|
||||
|
||||

|
||||
|
93
docs/documentation/platform/sso/auth0-saml.mdx
Normal file
93
docs/documentation/platform/sso/auth0-saml.mdx
Normal file
@ -0,0 +1,93 @@
|
||||
---
|
||||
title: "Auth0 SAML"
|
||||
description: "Learn how to configure Auth0 SAML for Infisical SSO."
|
||||
---
|
||||
|
||||
<Info>
|
||||
Auth0 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 sales@infisical.com to purchase an enterprise license
|
||||
to use it.
|
||||
</Info>
|
||||
|
||||
<Steps>
|
||||
<Step title="Prepare the SAML SSO configuration in Infisical">
|
||||
In Infisical, head to Organization Settings > Security and click **Connect** for SAML under the Connect to an Identity Provider section. Select Auth0, then click **Connect** again.
|
||||
|
||||
Next, note the **Application Callback URL** and **Audience** to use when configuring the Auth0 SAML application.
|
||||
|
||||

|
||||
|
||||
</Step>
|
||||
<Step title="Create a SAML application in Auth0">
|
||||
2.1. In your Auth0 account, head to Applications and create an application.
|
||||
|
||||

|
||||
|
||||
Select **Regular Web Application** and press **Create**.
|
||||
|
||||

|
||||
|
||||
2.2. In the Application head to Settings > Application URIs and add the **Application Callback URL** from step 1 into the **Allowed Callback URLs** field.
|
||||
|
||||

|
||||
|
||||
2.3. In the Application head to Addons > SAML2 Web App and copy the **Issuer**, **Identity Provider Login URL**, and **Identity Provider Certificate** from the **Usage** tab.
|
||||
|
||||

|
||||
|
||||
2.4. Back in Infisical, set **Issuer**, **Identity Provider Login URL**, and **Certificate** to the corresponding items from step 2.3.
|
||||
|
||||

|
||||
|
||||
2.5. Back in Auth0, in the **Settings** tab, set the **Application Callback URL** to the **Application Callback URL** from step 1
|
||||
and update the **Settings** field with the JSON under the picture below (replacing `<audience-from-infisical>` with the **Audience** from step 1).
|
||||
|
||||

|
||||
|
||||
```json
|
||||
{
|
||||
"audience": "<audience-from-infisical>",
|
||||
"mappings": {
|
||||
"email": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/email",
|
||||
"given_name": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/firstName",
|
||||
"family_name": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/lastName"
|
||||
},
|
||||
"signatureAlgorithm": "rsa-sha256",
|
||||
"digestAlgorithm": "sha256",
|
||||
"signResponse": true
|
||||
}
|
||||
```
|
||||
|
||||
Click **Save**.
|
||||
</Step>
|
||||
<Step title="Enable SAML SSO in Infisical">
|
||||
Enabling SAML SSO allows members in your organization to log into Infisical via Auth0.
|
||||
|
||||

|
||||
</Step>
|
||||
<Step title="Enforce SAML SSO in Infisical">
|
||||
Enforcing SAML SSO ensures that members in your organization can only access Infisical
|
||||
by logging into the organization via Auth0.
|
||||
|
||||
To enforce SAML SSO, you're required to test out the SAML connection by successfully authenticating at least one Auth0 user with Infisical;
|
||||
Once you've completed this requirement, you can toggle the **Enforce SAML SSO** button to enforce SAML SSO.
|
||||
</Step>
|
||||
|
||||
</Steps>
|
||||
|
||||
<Tip>
|
||||
If you are only using one organization on your Infisical instance, you can configure a default organization in the [Server Admin Console](../admin-panel/server-admin#default-organization) to expedite SAML login.
|
||||
</Tip>
|
||||
|
||||
<Note>
|
||||
If you're configuring SAML SSO on a self-hosted instance of Infisical, make
|
||||
sure to set the `AUTH_SECRET` and `SITE_URL` environment variable for it to
|
||||
work:
|
||||
<div class="height:1px;"/>
|
||||
- `AUTH_SECRET`: A secret key used for signing and verifying JWT. This
|
||||
can be a random 32-byte base64 string generated with `openssl rand -base64
|
||||
32`.
|
||||
<div class="height:1px;"/>
|
||||
- `SITE_URL`: The absolute URL of your self-hosted instance of Infisical including the protocol (e.g. https://app.infisical.com)
|
||||
</Note>
|
@ -12,7 +12,7 @@ description: "Learn how to configure Microsoft Entra ID for Infisical SSO."
|
||||
|
||||
<Steps>
|
||||
<Step title="Prepare the SAML SSO configuration in Infisical">
|
||||
In Infisical, head to your Organization Settings > Authentication > SAML SSO Configuration and select **Set up SAML SSO**.
|
||||
In Infisical, head to Organization Settings > Security and click **Connect** for SAML under the Connect to an Identity Provider section. Select Azure / Entra, then click **Connect** again.
|
||||
|
||||
Next, copy the **Reply URL (Assertion Consumer Service URL)** and **Identifier (Entity ID)** to use when configuring the Azure SAML application.
|
||||
|
||||
|
@ -12,7 +12,7 @@ description: "Learn how to configure Google SAML for Infisical SSO."
|
||||
|
||||
<Steps>
|
||||
<Step title="Prepare the SAML SSO configuration in Infisical">
|
||||
In Infisical, head to your Organization Settings > Authentication > SAML SSO Configuration and select **Set up SAML SSO**.
|
||||
In Infisical, head to Organization Settings > Security and click **Connect** for SAML under the Connect to an Identity Provider section. Select Google, then click **Connect** again.
|
||||
|
||||
Next, note the **ACS URL** and **SP Entity ID** to use when configuring the Google SAML application.
|
||||
|
||||
|
@ -12,7 +12,7 @@ description: "Learn how to configure JumpCloud SAML for Infisical SSO."
|
||||
|
||||
<Steps>
|
||||
<Step title="Prepare the SAML SSO configuration in Infisical">
|
||||
In Infisical, head to your Organization Settings > Authentication > SAML SSO Configuration and select **Set up SAML SSO**.
|
||||
In Infisical, head to Organization Settings > Security and click **Connect** for SAML under the Connect to an Identity Provider section. Select JumpCloud, then click **Connect** again.
|
||||
|
||||
Next, copy the **ACS URL** and **SP Entity ID** to use when configuring the JumpCloud SAML application.
|
||||
|
||||
|
@ -12,7 +12,7 @@ description: "Learn how to configure Keycloak SAML for Infisical SSO."
|
||||
|
||||
<Steps>
|
||||
<Step title="Prepare the SAML SSO configuration in Infisical">
|
||||
In Infisical, head to your Organization Settings > Authentication > SAML SSO Configuration and select **Manage**.
|
||||
In Infisical, head to Organization Settings > Security and click **Connect** for SAML under the Connect to an Identity Provider section. Select Keycloak, then click **Connect** again.
|
||||
|
||||

|
||||
|
||||
|
@ -12,7 +12,7 @@ description: "Learn how to configure Okta SAML 2.0 for Infisical SSO."
|
||||
|
||||
<Steps>
|
||||
<Step title="Prepare the SAML SSO configuration in Infisical">
|
||||
In Infisical, head to your Organization Settings > Authentication > SAML SSO Configuration and select **Set up SAML SSO**.
|
||||
In Infisical, head to Organization Settings > Security and click **Connect** for SAML under the Connect to an Identity Provider section. Select Okta, then click **Connect** again.
|
||||
|
||||
Next, copy the **Single sign-on URL** and **Audience URI (SP Entity ID)** to use when configuring the Okta SAML 2.0 application.
|
||||

|
||||
|
@ -28,6 +28,7 @@ Infisical supports these and many other identity providers:
|
||||
- [JumpCloud SAML](/documentation/platform/sso/jumpcloud)
|
||||
- [Keycloak SAML](/documentation/platform/sso/keycloak-saml)
|
||||
- [Google SAML](/documentation/platform/sso/google-saml)
|
||||
- [Auth0 SAML](/documentation/platform/sso/auth0-saml)
|
||||
- [Keycloak OIDC](/documentation/platform/sso/keycloak-oidc)
|
||||
- [Auth0 OIDC](/documentation/platform/sso/auth0-oidc)
|
||||
- [General OIDC](/documentation/platform/sso/general-oidc)
|
||||
|
BIN
docs/images/sso/auth0-saml/auth0-config-2.png
Normal file
BIN
docs/images/sso/auth0-saml/auth0-config-2.png
Normal file
Binary file not shown.
After ![]() (image error) Size: 612 KiB |
BIN
docs/images/sso/auth0-saml/auth0-config-3.png
Normal file
BIN
docs/images/sso/auth0-saml/auth0-config-3.png
Normal file
Binary file not shown.
After ![]() (image error) Size: 366 KiB |
BIN
docs/images/sso/auth0-saml/auth0-config.png
Normal file
BIN
docs/images/sso/auth0-saml/auth0-config.png
Normal file
Binary file not shown.
After ![]() (image error) Size: 431 KiB |
BIN
docs/images/sso/auth0-saml/create-application-2.png
Normal file
BIN
docs/images/sso/auth0-saml/create-application-2.png
Normal file
Binary file not shown.
After ![]() (image error) Size: 352 KiB |
BIN
docs/images/sso/auth0-saml/create-application.png
Normal file
BIN
docs/images/sso/auth0-saml/create-application.png
Normal file
Binary file not shown.
After ![]() (image error) Size: 253 KiB |
BIN
docs/images/sso/auth0-saml/enable-saml.png
Normal file
BIN
docs/images/sso/auth0-saml/enable-saml.png
Normal file
Binary file not shown.
After ![]() (image error) Size: 605 KiB |
BIN
docs/images/sso/auth0-saml/infisical-config.png
Normal file
BIN
docs/images/sso/auth0-saml/infisical-config.png
Normal file
Binary file not shown.
After ![]() (image error) Size: 605 KiB |
BIN
docs/images/sso/auth0-saml/init-config.png
Normal file
BIN
docs/images/sso/auth0-saml/init-config.png
Normal file
Binary file not shown.
After ![]() (image error) Size: 539 KiB |
@ -248,6 +248,7 @@
|
||||
"documentation/platform/sso/jumpcloud",
|
||||
"documentation/platform/sso/keycloak-saml",
|
||||
"documentation/platform/sso/google-saml",
|
||||
"documentation/platform/sso/auth0-saml",
|
||||
"documentation/platform/sso/keycloak-oidc",
|
||||
"documentation/platform/sso/auth0-oidc",
|
||||
"documentation/platform/sso/general-oidc"
|
||||
|
@ -1,3 +1,2 @@
|
||||
node_modules
|
||||
**/.next
|
||||
.next
|
||||
dist
|
||||
|
@ -1,108 +0,0 @@
|
||||
module.exports = {
|
||||
overrides: [
|
||||
{
|
||||
files: ["next.config.js"]
|
||||
}
|
||||
],
|
||||
root: true,
|
||||
env: {
|
||||
browser: true,
|
||||
es2021: true,
|
||||
es6: true
|
||||
},
|
||||
extends: [
|
||||
"airbnb",
|
||||
"airbnb-typescript",
|
||||
"airbnb/hooks",
|
||||
"plugin:react/recommended",
|
||||
"prettier",
|
||||
"plugin:storybook/recommended"
|
||||
],
|
||||
parserOptions: {
|
||||
ecmaVersion: "latest",
|
||||
sourceType: "module",
|
||||
project: "./tsconfig.json",
|
||||
ecmaFeatures: {
|
||||
jsx: true
|
||||
},
|
||||
tsconfigRootDir: __dirname
|
||||
},
|
||||
plugins: ["react", "prettier", "simple-import-sort", "import"],
|
||||
rules: {
|
||||
"@typescript-eslint/no-empty-function": "off",
|
||||
quotes: ["error", "double", { avoidEscape: true }],
|
||||
"comma-dangle": ["error", "only-multiline"],
|
||||
"react/react-in-jsx-scope": "off",
|
||||
"import/prefer-default-export": "off",
|
||||
"react-hooks/exhaustive-deps": "off",
|
||||
"@typescript-eslint/ban-ts-comment": "warn",
|
||||
"react/jsx-props-no-spreading": "off", // switched off for component building
|
||||
// TODO: This rule will be switched ON after complete revamp of frontend
|
||||
"@typescript-eslint/no-explicit-any": "off",
|
||||
"jsx-a11y/control-has-associated-label": "off",
|
||||
"no-console": "off",
|
||||
"arrow-body-style": "off",
|
||||
"no-underscore-dangle": [
|
||||
"error",
|
||||
{
|
||||
allow: ["_id"]
|
||||
}
|
||||
],
|
||||
"jsx-a11y/anchor-is-valid": "off",
|
||||
// all those <a> tags must be converted to label or a p component
|
||||
//
|
||||
"react/require-default-props": "off",
|
||||
"react/jsx-filename-extension": [
|
||||
1,
|
||||
{
|
||||
extensions: [".tsx", ".ts"]
|
||||
}
|
||||
],
|
||||
// TODO: turn this rule ON after migration. everything should use arrow functions
|
||||
"react/function-component-definition": [
|
||||
0,
|
||||
{
|
||||
namedComponents: "arrow-function"
|
||||
}
|
||||
],
|
||||
"react/no-unknown-property": [
|
||||
"error",
|
||||
{
|
||||
ignore: ["jsx"]
|
||||
}
|
||||
],
|
||||
"@typescript-eslint/no-non-null-assertion": "off",
|
||||
"simple-import-sort/exports": "warn",
|
||||
"simple-import-sort/imports": [
|
||||
"warn",
|
||||
{
|
||||
groups: [
|
||||
// Node.js builtins. You could also generate this regex if you use a `.js` config.
|
||||
// For example: `^(${require("module").builtinModules.join("|")})(/|$)`
|
||||
// Note that if you use the `node:` prefix for Node.js builtins,
|
||||
// you can avoid this complexity: You can simply use "^node:".
|
||||
[
|
||||
"^(assert|buffer|child_process|cluster|console|constants|crypto|dgram|dns|domain|events|fs|http|https|module|net|os|path|punycode|querystring|readline|repl|stream|string_decoder|sys|timers|tls|tty|url|util|vm|zlib|freelist|v8|process|async_hooks|http2|perf_hooks)(/.*|$)"
|
||||
],
|
||||
// Packages `react` related packages
|
||||
["^react", "^next", "^@?\\w"],
|
||||
["^@app"],
|
||||
// Internal packages.
|
||||
["^~(/.*|$)"],
|
||||
// Relative imports
|
||||
["^\\.\\.(?!/?$)", "^\\.\\./?$", "^\\./(?=.*/)(?!/?$)", "^\\.(?!/?$)", "^\\./?$"],
|
||||
// Style imports.
|
||||
["^.+\\.?(css|scss)$"]
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
ignorePatterns: ["next.config.js", "cypress/**/*.js", "cypress.config.js"],
|
||||
settings: {
|
||||
"import/resolver": {
|
||||
typescript: {
|
||||
project: ["./tsconfig.json"]
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
50
frontend/.gitignore
vendored
50
frontend/.gitignore
vendored
@ -1,36 +1,24 @@
|
||||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||
|
||||
# dependencies
|
||||
/node_modules
|
||||
/.pnp
|
||||
.pnp.js
|
||||
|
||||
.env
|
||||
|
||||
# testing
|
||||
/coverage
|
||||
|
||||
# next.js
|
||||
/.next/
|
||||
/out/
|
||||
|
||||
# production
|
||||
/build
|
||||
|
||||
# misc
|
||||
.DS_Store
|
||||
|
||||
# debug
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
lerna-debug.log*
|
||||
|
||||
# local env files
|
||||
.env.local
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
.vercel
|
||||
.env.infisical
|
||||
node_modules
|
||||
dist
|
||||
dist-ssr
|
||||
*.local
|
||||
|
||||
.vscode
|
||||
# Editor directories and files
|
||||
.vscode/*
|
||||
!.vscode/extensions.json
|
||||
.idea
|
||||
.DS_Store
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
||||
|
@ -3,5 +3,8 @@
|
||||
"printWidth": 100,
|
||||
"trailingComma": "none",
|
||||
"tabWidth": 2,
|
||||
"semi": true
|
||||
"semi": true,
|
||||
"plugins": ["prettier-plugin-tailwindcss"],
|
||||
"tailwindStylesheet": "./src/index.css",
|
||||
"tailwindFunctions": ["clsx", "twMerge"]
|
||||
}
|
||||
|
@ -1,28 +0,0 @@
|
||||
const path = require("path");
|
||||
module.exports = {
|
||||
stories: ["../src/**/*.mdx", "../src/**/*.stories.@(js|jsx|ts|tsx)"],
|
||||
addons: [
|
||||
"@storybook/addon-links",
|
||||
"@storybook/addon-essentials",
|
||||
"@storybook/addon-interactions",
|
||||
"storybook-dark-mode",
|
||||
{
|
||||
name: "@storybook/addon-styling",
|
||||
options: {
|
||||
postCss: {
|
||||
implementation: require("postcss")
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
framework: {
|
||||
name: "@storybook/nextjs",
|
||||
options: {}
|
||||
},
|
||||
core: {
|
||||
disableTelemetry: true
|
||||
},
|
||||
docs: {
|
||||
autodocs: "tag"
|
||||
}
|
||||
};
|
@ -1,29 +0,0 @@
|
||||
import { themes } from "@storybook/theming";
|
||||
import "react-day-picker/dist/style.css";
|
||||
import "../src/styles/globals.css";
|
||||
|
||||
export const parameters = {
|
||||
actions: { argTypesRegex: "^on[A-Z].*" },
|
||||
backgrounds: {
|
||||
default: "dark",
|
||||
values: [
|
||||
{
|
||||
name: "dark",
|
||||
value: "rgb(14, 16, 20)"
|
||||
},
|
||||
{
|
||||
name: "paper",
|
||||
value: "rgb(30, 31, 34)"
|
||||
}
|
||||
]
|
||||
},
|
||||
controls: {
|
||||
matchers: {
|
||||
color: /(background|color)$/i,
|
||||
date: /Date$/
|
||||
}
|
||||
},
|
||||
darkMode: {
|
||||
dark: { ...themes.dark, appContentBg: "rgb(14,16,20)", appBg: "rgb(14,16,20)" }
|
||||
}
|
||||
};
|
@ -1,84 +0,0 @@
|
||||
ARG POSTHOG_HOST=https://app.posthog.com
|
||||
ARG POSTHOG_API_KEY=posthog-api-key
|
||||
ARG INTERCOM_ID=intercom-id
|
||||
ARG NEXT_INFISICAL_PLATFORM_VERSION=next-infisical-platform-version
|
||||
ARG CAPTCHA_SITE_KEY=captcha-site-key
|
||||
|
||||
FROM node:16-alpine AS deps
|
||||
# Install dependencies only when needed. Check https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine to understand why libc6-compat might be needed.
|
||||
# RUN apk add --no-cache libc6-compat
|
||||
WORKDIR /app
|
||||
|
||||
# Copy over dependency files
|
||||
COPY package.json package-lock.json next.config.js ./
|
||||
|
||||
# Install dependencies
|
||||
RUN npm ci --only-production --ignore-scripts
|
||||
|
||||
# Rebuild the source code only when needed
|
||||
FROM node:16-alpine AS builder
|
||||
WORKDIR /app
|
||||
|
||||
# Copy dependencies
|
||||
COPY --from=deps /app/node_modules ./node_modules
|
||||
# Copy all files
|
||||
COPY . .
|
||||
|
||||
ENV NODE_ENV production
|
||||
ENV NEXT_PUBLIC_ENV production
|
||||
ARG POSTHOG_HOST
|
||||
ENV NEXT_PUBLIC_POSTHOG_HOST $POSTHOG_HOST
|
||||
ARG POSTHOG_API_KEY
|
||||
ENV NEXT_PUBLIC_POSTHOG_API_KEY $POSTHOG_API_KEY
|
||||
ARG INTERCOM_ID
|
||||
ENV NEXT_PUBLIC_INTERCOM_ID $INTERCOM_ID
|
||||
ARG CAPTCHA_SITE_KEY
|
||||
ENV NEXT_PUBLIC_CAPTCHA_SITE_KEY $CAPTCHA_SITE_KEY
|
||||
|
||||
# Build
|
||||
RUN npm run build
|
||||
|
||||
|
||||
# Production image
|
||||
FROM node:16-alpine AS runner
|
||||
WORKDIR /app
|
||||
|
||||
RUN addgroup --system --gid 1001 nodejs
|
||||
RUN adduser --system --uid 1001 nextjs
|
||||
|
||||
RUN mkdir -p /app/.next/cache/images && chown nextjs:nodejs /app/.next/cache/images
|
||||
VOLUME /app/.next/cache/images
|
||||
|
||||
ARG POSTHOG_API_KEY
|
||||
ENV NEXT_PUBLIC_POSTHOG_API_KEY=$POSTHOG_API_KEY \
|
||||
BAKED_NEXT_PUBLIC_POSTHOG_API_KEY=$POSTHOG_API_KEY
|
||||
ARG INTERCOM_ID
|
||||
ENV NEXT_PUBLIC_INTERCOM_ID=$INTERCOM_ID \
|
||||
BAKED_NEXT_PUBLIC_INTERCOM_ID=$INTERCOM_ID
|
||||
ARG SAML_ORG_SLUG
|
||||
ENV NEXT_PUBLIC_SAML_ORG_SLUG=$SAML_ORG_SLUG \
|
||||
BAKED_NEXT_PUBLIC_SAML_ORG_SLUG=$SAML_ORG_SLUG
|
||||
ARG NEXT_INFISICAL_PLATFORM_VERSION
|
||||
ENV NEXT_PUBLIC_INFISICAL_PLATFORM_VERSION=$NEXT_INFISICAL_PLATFORM_VERSION
|
||||
ARG CAPTCHA_SITE_KEY
|
||||
ENV NEXT_PUBLIC_CAPTCHA_SITE_KEY=$CAPTCHA_SITE_KEY \
|
||||
BAKED_NEXT_PUBLIC_CAPTCHA_SITE_KEY=$CAPTCHA_SITE_KEY
|
||||
COPY --chown=nextjs:nodejs --chmod=555 scripts ./scripts
|
||||
COPY --from=builder /app/public ./public
|
||||
RUN chown nextjs:nodejs ./public/data
|
||||
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
|
||||
COPY --from=builder --chown=nextjs:nodejs --chmod=777 /app/.next/static ./.next/static
|
||||
RUN chmod -R 777 /app/.next/server
|
||||
|
||||
USER nextjs
|
||||
|
||||
EXPOSE 3000
|
||||
|
||||
ENV PORT 3000
|
||||
ENV NEXT_TELEMETRY_DISABLED 1
|
||||
|
||||
HEALTHCHECK --interval=10s --timeout=3s --start-period=10s \
|
||||
CMD node scripts/healthcheck.js
|
||||
|
||||
|
||||
CMD ["/app/scripts/start.sh"]
|
@ -1,5 +1,5 @@
|
||||
# Base layer
|
||||
FROM node:16-alpine
|
||||
FROM node:20-alpine
|
||||
|
||||
# Set the working directory
|
||||
WORKDIR /app
|
||||
@ -11,9 +11,6 @@ COPY package-lock.json ./
|
||||
# Install
|
||||
RUN npm install --ignore-scripts
|
||||
|
||||
# Copy over next.js config
|
||||
COPY next.config.js ./next.config.js
|
||||
|
||||
# Copy all files
|
||||
COPY . .
|
||||
|
||||
|
@ -1,22 +1,50 @@
|
||||
This is the client repository for Infisical.
|
||||
# React + TypeScript + Vite
|
||||
|
||||
## Before you get started with development locally
|
||||
This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
|
||||
|
||||
Please ensure you have Docker and Docker Compose installed for your OS.
|
||||
Currently, two official plugins are available:
|
||||
|
||||
### Steps to start server
|
||||
- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh
|
||||
- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh
|
||||
|
||||
- `CD` into the repo
|
||||
- run command `docker-compose -f docker-compose.dev.yml up --build --force-recreate`
|
||||
- Visit localhost:8080 and the website should be live
|
||||
## Expanding the ESLint configuration
|
||||
|
||||
### Steps to shutdown this Docker compose
|
||||
If you are developing a production application, we recommend updating the configuration to enable type aware lint rules:
|
||||
|
||||
- `CD` into this repo
|
||||
- run command `docker-compose -f docker-compose.dev.yml down`
|
||||
- Configure the top-level `parserOptions` property like this:
|
||||
|
||||
### Notes
|
||||
```js
|
||||
export default tseslint.config({
|
||||
languageOptions: {
|
||||
// other options...
|
||||
parserOptions: {
|
||||
project: ['./tsconfig.node.json', './tsconfig.app.json'],
|
||||
tsconfigRootDir: import.meta.dirname,
|
||||
},
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
Any changes made to local files in the `/components`, `/pages`, `/styles` will be hot reloaded. If would like like to watch for other files or folders live, please add them to the docker volume.
|
||||
- Replace `tseslint.configs.recommended` to `tseslint.configs.recommendedTypeChecked` or `tseslint.configs.strictTypeChecked`
|
||||
- Optionally add `...tseslint.configs.stylisticTypeChecked`
|
||||
- Install [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react) and update the config:
|
||||
|
||||
You will also need to ensure that a .env.local file exists with all required environment variables
|
||||
```js
|
||||
// eslint.config.js
|
||||
import react from 'eslint-plugin-react'
|
||||
|
||||
export default tseslint.config({
|
||||
// Set the react version
|
||||
settings: { react: { version: '18.3' } },
|
||||
plugins: {
|
||||
// Add the react plugin
|
||||
react,
|
||||
},
|
||||
rules: {
|
||||
// other rules...
|
||||
// Enable its recommended rules
|
||||
...react.configs.recommended.rules,
|
||||
...react.configs['jsx-runtime'].rules,
|
||||
},
|
||||
})
|
||||
```
|
||||
|
@ -1,7 +0,0 @@
|
||||
module.exports = {
|
||||
e2e: {
|
||||
baseUrl: 'http://localhost:8080',
|
||||
viewportWidth: 1480,
|
||||
viewportHeight: 920,
|
||||
},
|
||||
};
|
@ -1,47 +0,0 @@
|
||||
/// <reference types="cypress" />
|
||||
|
||||
describe('organization Overview', () => {
|
||||
beforeEach(() => {
|
||||
cy.login(`test@localhost.local`, `testInfisical1`)
|
||||
})
|
||||
|
||||
const projectName = "projectY"
|
||||
|
||||
it('can`t create projects with empty names', () => {
|
||||
cy.get('.button').click()
|
||||
cy.get('input[placeholder="Type your project name"]').type('abc').clear()
|
||||
cy.intercept('*').as('anyRequest');
|
||||
cy.get('@anyRequest').should('not.exist');
|
||||
})
|
||||
|
||||
it('can delete a newly-created project', () => {
|
||||
// Create a project
|
||||
cy.get('.button').click()
|
||||
cy.get('input[placeholder="Type your project name"]').type(`${projectName}`)
|
||||
cy.contains('button', 'Create Project').click()
|
||||
cy.url().should('include', '/project')
|
||||
|
||||
// Delete a project
|
||||
cy.get(`[href^="/project/"][href$="/settings"] > a > .group`).click()
|
||||
cy.contains('button', `Delete ${projectName}`).click()
|
||||
cy.contains('button', 'Delete Project').should('have.attr', 'disabled')
|
||||
cy.get('input[placeholder="Type to delete..."]').type('confirm')
|
||||
cy.contains('button', 'Delete Project').should('not.have.attr', 'disabled')
|
||||
cy.url().then((currentUrl) => {
|
||||
let projectId = currentUrl.split("/")[4]
|
||||
cy.intercept('DELETE', `/api/v1/workspace/${projectId}`).as('deleteProject');
|
||||
cy.contains('button', 'Delete Project').click();
|
||||
cy.get('@deleteProject').should('have.property', 'response').and('have.property', 'statusCode', 200);
|
||||
})
|
||||
})
|
||||
|
||||
it('can display no projects', () => {
|
||||
cy.intercept('/api/v1/workspace', {
|
||||
body: {
|
||||
"workspaces": []
|
||||
},
|
||||
})
|
||||
cy.get('.border-mineshaft-700 > :nth-child(2)').should('have.text', 'You are not part of any projects in this organization yet. When you are, they will appear here.')
|
||||
})
|
||||
|
||||
})
|
@ -1,24 +0,0 @@
|
||||
/// <reference types="cypress" />
|
||||
|
||||
describe('Organization Settings', () => {
|
||||
let orgId;
|
||||
|
||||
beforeEach(() => {
|
||||
cy.login(`test@localhost.local`, `testInfisical1`)
|
||||
cy.url().then((currentUrl) => {
|
||||
orgId = currentUrl.split("/")[4]
|
||||
cy.visit(`org/${orgId}/settings`)
|
||||
})
|
||||
})
|
||||
|
||||
it('can rename org', () => {
|
||||
cy.get('input[placeholder="Acme Corp"]').clear().type('ABC')
|
||||
|
||||
cy.intercept('PATCH', `/api/v1/organization/${orgId}/name`).as('renameOrg');
|
||||
cy.get('form.p-4 > .button').click()
|
||||
cy.get('@renameOrg').should('have.property', 'response').and('have.property', 'statusCode', 200);
|
||||
|
||||
cy.get('.pl-3').should("have.text", "ABC ")
|
||||
})
|
||||
|
||||
})
|
@ -1,84 +0,0 @@
|
||||
/// <reference types="cypress" />
|
||||
|
||||
describe('Project Overview', () => {
|
||||
const projectName = "projectY"
|
||||
let projectId;
|
||||
let isFirstTest = true;
|
||||
|
||||
before(() => {
|
||||
cy.login(`test@localhost.local`, `testInfisical1`)
|
||||
|
||||
// Create a project
|
||||
cy.get('.button').click()
|
||||
cy.get('input[placeholder="Type your project name"]').type(`${projectName}`)
|
||||
cy.contains('button', 'Create Project').click()
|
||||
cy.url().should('include', '/project').then((currentUrl) => {
|
||||
projectId = currentUrl.split("/")[4]
|
||||
})
|
||||
})
|
||||
|
||||
beforeEach(() => {
|
||||
if (isFirstTest) {
|
||||
isFirstTest = false;
|
||||
return; // Skip the rest of the beforeEach for the first test
|
||||
}
|
||||
cy.login(`test@localhost.local`, `testInfisical1`)
|
||||
cy.visit(`/project/${projectId}/secrets/overview`)
|
||||
})
|
||||
|
||||
it('can create secrets', () => {
|
||||
cy.contains('button', 'Go to Development').click()
|
||||
cy.contains('button', 'Add a new secret').click()
|
||||
cy.get('input[placeholder="Type your secret name"]').type('SECRET_A')
|
||||
cy.contains('button', 'Create Secret').click()
|
||||
cy.get('.w-80 > .inline-flex > .input').should('have.value', 'SECRET_A')
|
||||
cy.get(':nth-child(6) > .button > .w-min').should('have.text', '1 Commit')
|
||||
})
|
||||
|
||||
it('can update secrets', () => {
|
||||
cy.get(':nth-child(2) > .flex > .button').click()
|
||||
cy.get('.overflow-auto > .relative > .absolute').type('VALUE_A')
|
||||
cy.get('.button.text-primary > .svg-inline--fa').click()
|
||||
cy.get(':nth-child(6) > .button > .w-min').should('have.text', '2 Commits')
|
||||
})
|
||||
|
||||
it('can`t create duplicate-name secrets', () => {
|
||||
cy.get(':nth-child(2) > .flex > .button').click()
|
||||
cy.contains('button', 'Add Secret').click()
|
||||
cy.get('input[placeholder="Type your secret name"]').type('SECRET_A')
|
||||
cy.intercept('POST', `/api/v3/secrets/SECRET_A`).as('createSecret');
|
||||
cy.contains('button', 'Create Secret').click()
|
||||
cy.get('@createSecret').should('have.property', 'response').and('have.property', 'statusCode', 400);
|
||||
})
|
||||
|
||||
it('can add another secret', () => {
|
||||
cy.get(':nth-child(2) > .flex > .button').click()
|
||||
cy.contains('button', 'Add Secret').click()
|
||||
cy.get('input[placeholder="Type your secret name"]').type('SECRET_B')
|
||||
cy.contains('button', 'Create Secret').click()
|
||||
cy.get(':nth-child(6) > .button > .w-min').should('have.text', '3 Commits')
|
||||
})
|
||||
|
||||
it('can delete a secret', () => {
|
||||
cy.get(':nth-child(2) > .flex > .button').click()
|
||||
// cy.get(':nth-child(3) > .shadow-none').trigger('mouseover')
|
||||
cy.get(':nth-child(3) > .shadow-none > .group > .h-10 > .border-red').click()
|
||||
cy.contains('button', 'Delete Secret').should('have.attr', 'disabled')
|
||||
cy.get('input[placeholder="Type to delete..."]').type('SECRET_B')
|
||||
cy.intercept('DELETE', `/api/v3/secrets/SECRET_B`).as('deleteSecret');
|
||||
cy.contains('button', 'Delete Secret').should('not.have.attr', 'disabled')
|
||||
cy.contains('button', 'Delete Secret').click();
|
||||
cy.get('@deleteSecret').should('have.property', 'response').and('have.property', 'statusCode', 200);
|
||||
})
|
||||
|
||||
it('can add a comment', () => {
|
||||
return;
|
||||
cy.get(':nth-child(2) > .flex > .button').click()
|
||||
// for some reason this hover does not want to work
|
||||
cy.get('.overflow-auto').trigger('mouseover').then(() => {
|
||||
cy.get('.shadow-none > .group > .pl-4 > .h-8 > button[aria-label="add-comment"]').should('be.visible').click()
|
||||
});
|
||||
|
||||
})
|
||||
|
||||
})
|
@ -1,5 +0,0 @@
|
||||
{
|
||||
"name": "Using fixtures to represent data",
|
||||
"email": "hello@cypress.io",
|
||||
"body": "Fixtures are a great way to mock data for responses to routes"
|
||||
}
|
@ -1,19 +0,0 @@
|
||||
|
||||
Cypress.Commands.add('login', (username, password) => {
|
||||
cy.visit('/login')
|
||||
cy.get('input[placeholder="Enter your email..."]').type(username)
|
||||
cy.get('input[placeholder="Enter your password..."]').type(password)
|
||||
cy.contains('Continue with Email').click()
|
||||
cy.url().should('include', '/overview')
|
||||
})
|
||||
|
||||
// Cypress.Commands.add('login', (username, password) => {
|
||||
// cy.session([username, password], () => {
|
||||
// cy.visit('/login')
|
||||
// cy.get('input[placeholder="Enter your email..."]').type(username)
|
||||
// cy.get('input[placeholder="Enter your password..."]').type(password)
|
||||
// cy.contains('Continue with Email').click()
|
||||
// cy.url().should('include', '/overview')
|
||||
// cy.wait(2000);
|
||||
// })
|
||||
// })
|
@ -1,20 +0,0 @@
|
||||
// ***********************************************************
|
||||
// This example support/e2e.js is processed and
|
||||
// loaded automatically before your test files.
|
||||
//
|
||||
// This is a great place to put global configuration and
|
||||
// behavior that modifies Cypress.
|
||||
//
|
||||
// You can change the location of this file or turn off
|
||||
// automatically serving support files with the
|
||||
// 'supportFile' configuration option.
|
||||
//
|
||||
// You can read more here:
|
||||
// https://on.cypress.io/configuration
|
||||
// ***********************************************************
|
||||
|
||||
// Import commands.js using ES2015 syntax:
|
||||
import './commands'
|
||||
|
||||
// Alternatively you can use CommonJS syntax:
|
||||
// require('./commands')
|
137
frontend/eslint.config.js
Normal file
137
frontend/eslint.config.js
Normal file
@ -0,0 +1,137 @@
|
||||
import js from "@eslint/js";
|
||||
import globals from "globals";
|
||||
import reactHooks from "eslint-plugin-react-hooks";
|
||||
import reactRefresh from "eslint-plugin-react-refresh";
|
||||
import eslintPluginPrettier from "eslint-plugin-prettier/recommended";
|
||||
import simpleImportSort from "eslint-plugin-simple-import-sort";
|
||||
import tseslint from "typescript-eslint";
|
||||
import { FlatCompat } from "@eslint/eslintrc";
|
||||
import stylisticPlugin from "@stylistic/eslint-plugin";
|
||||
import importPlugin from "eslint-plugin-import";
|
||||
import pluginRouter from "@tanstack/eslint-plugin-router";
|
||||
|
||||
const compat = new FlatCompat({
|
||||
baseDirectory: import.meta.dirname
|
||||
});
|
||||
|
||||
export default tseslint.config(
|
||||
{ ignores: ["dist"] },
|
||||
{
|
||||
extends: [
|
||||
...pluginRouter.configs["flat/recommended"],
|
||||
js.configs.recommended,
|
||||
tseslint.configs.recommended,
|
||||
...compat.extends("airbnb"),
|
||||
...compat.extends("@kesills/airbnb-typescript"),
|
||||
eslintPluginPrettier
|
||||
],
|
||||
files: ["**/*.{ts,tsx}"],
|
||||
languageOptions: {
|
||||
ecmaVersion: 2020,
|
||||
globals: globals.browser,
|
||||
parserOptions: {
|
||||
projectService: true,
|
||||
tsconfigRootDir: import.meta.dirname
|
||||
}
|
||||
},
|
||||
plugins: {
|
||||
"react-hooks": reactHooks,
|
||||
"react-refresh": reactRefresh,
|
||||
"simple-import-sort": simpleImportSort,
|
||||
import: importPlugin
|
||||
},
|
||||
settings: {
|
||||
"import/resolver": {
|
||||
typescript: {
|
||||
project: ["./tsconfig.json"]
|
||||
}
|
||||
}
|
||||
},
|
||||
rules: {
|
||||
...reactHooks.configs.recommended.rules,
|
||||
"react-refresh/only-export-components": "off",
|
||||
"@typescript-eslint/only-throw-error": "off",
|
||||
"@typescript-eslint/no-empty-function": "off",
|
||||
quotes: ["error", "double", { avoidEscape: true }],
|
||||
"comma-dangle": ["error", "only-multiline"],
|
||||
"react/react-in-jsx-scope": "off",
|
||||
"import/prefer-default-export": "off",
|
||||
"react-hooks/exhaustive-deps": "off",
|
||||
"@typescript-eslint/ban-ts-comment": "warn",
|
||||
"react/jsx-props-no-spreading": "off", // switched off for component building
|
||||
// TODO: This rule will be switched ON after complete revamp of frontend
|
||||
"@typescript-eslint/no-explicit-any": "off",
|
||||
"jsx-a11y/control-has-associated-label": "off",
|
||||
"import/no-extraneous-dependencies": [
|
||||
"error",
|
||||
{
|
||||
devDependencies: true
|
||||
}
|
||||
],
|
||||
"no-console": "off",
|
||||
"arrow-body-style": "off",
|
||||
"no-underscore-dangle": [
|
||||
"error",
|
||||
{
|
||||
allow: ["_id"]
|
||||
}
|
||||
],
|
||||
"jsx-a11y/anchor-is-valid": "off",
|
||||
// all those <a> tags must be converted to label or a p component
|
||||
//
|
||||
"react/require-default-props": "off",
|
||||
"react/jsx-filename-extension": [
|
||||
1,
|
||||
{
|
||||
extensions: [".tsx", ".ts"]
|
||||
}
|
||||
],
|
||||
// TODO: turn this rule ON after migration. everything should use arrow functions
|
||||
"react/function-component-definition": [
|
||||
0,
|
||||
{
|
||||
namedComponents: "arrow-function"
|
||||
}
|
||||
],
|
||||
"react/no-unknown-property": [
|
||||
"error",
|
||||
{
|
||||
ignore: ["jsx"]
|
||||
}
|
||||
],
|
||||
"@typescript-eslint/no-non-null-assertion": "off",
|
||||
"simple-import-sort/exports": "warn",
|
||||
"simple-import-sort/imports": [
|
||||
"warn",
|
||||
{
|
||||
groups: [
|
||||
// Node.js builtins. You could also generate this regex if you use a `.js` config.
|
||||
// For example: `^(${require("module").builtinModules.join("|")})(/|$)`
|
||||
// Note that if you use the `node:` prefix for Node.js builtins,
|
||||
// you can avoid this complexity: You can simply use "^node:".
|
||||
[
|
||||
"^(assert|buffer|child_process|cluster|console|constants|crypto|dgram|dns|domain|events|fs|http|https|module|net|os|path|punycode|querystring|readline|repl|stream|string_decoder|sys|timers|tls|tty|url|util|vm|zlib|freelist|v8|process|async_hooks|http2|perf_hooks)(/.*|$)"
|
||||
],
|
||||
// Packages `react` related packages
|
||||
["^react", "^next", "^@?\\w"],
|
||||
["^@app"],
|
||||
// Internal packages.
|
||||
["^~(/.*|$)"],
|
||||
// Relative imports
|
||||
["^\\.\\.(?!/?$)", "^\\.\\./?$", "^\\./(?=.*/)(?!/?$)", "^\\.(?!/?$)", "^\\./?$"],
|
||||
// Style imports.
|
||||
["^.+\\.?(css|scss)$"]
|
||||
]
|
||||
}
|
||||
],
|
||||
"import/first": "error",
|
||||
"import/newline-after-import": "error",
|
||||
"import/no-duplicates": "error"
|
||||
}
|
||||
},
|
||||
{
|
||||
rules: Object.fromEntries(
|
||||
Object.keys(stylisticPlugin.configs["all-flat"].rules ?? {}).map((key) => [key, "off"])
|
||||
)
|
||||
}
|
||||
);
|
29
frontend/index.html
Normal file
29
frontend/index.html
Normal file
@ -0,0 +1,29 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" href="/infisical.ico" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta
|
||||
http-equiv="Content-Security-Policy"
|
||||
content="
|
||||
default-src 'self';
|
||||
connect-src 'self' https://*.posthog.com http://127.0.0.1:* https://cdn.jsdelivr.net/npm/@lottiefiles/dotlottie-web@0.38.2/dist/dotlottie-player.wasm;
|
||||
script-src 'self' https://*.posthog.com https://js.stripe.com https://api.stripe.com https://widget.intercom.io https://js.intercomcdn.com https://hcaptcha.com https://*.hcaptcha.com 'unsafe-inline' 'unsafe-eval' https://cdn.jsdelivr.net/npm/@lottiefiles/dotlottie-web@0.38.2/dist/dotlottie-player.wasm;
|
||||
style-src 'self' 'unsafe-inline' https://hcaptcha.com https://*.hcaptcha.com;
|
||||
child-src https://api.stripe.com;
|
||||
frame-src https://js.stripe.com/ https://api.stripe.com https://www.youtube.com/ https://hcaptcha.com https://*.hcaptcha.com;
|
||||
connect-src 'self' wss://nexus-websocket-a.intercom.io https://api-iam.intercom.io https://api.heroku.com/ https://id.heroku.com/oauth/authorize https://id.heroku.com/oauth/token https://checkout.stripe.com https://app.posthog.com https://api.stripe.com https://api.pwnedpasswords.com http://127.0.0.1:* https://hcaptcha.com https://*.hcaptcha.com;
|
||||
img-src 'self' https://static.intercomassets.com https://js.intercomcdn.com https://downloads.intercomcdn.com https://*.stripe.com https://i.ytimg.com/ data:;
|
||||
media-src https://js.intercomcdn.com;
|
||||
font-src 'self' https://fonts.intercomcdn.com/ https://fonts.gstatic.com;
|
||||
"
|
||||
/>
|
||||
<title>Infisical</title>
|
||||
<script src="/runtime-ui-env.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<script type="module" src="/src/main.tsx"></script>
|
||||
</body>
|
||||
</html>
|
5
frontend/next-env.d.ts
vendored
5
frontend/next-env.d.ts
vendored
@ -1,5 +0,0 @@
|
||||
/// <reference types="next" />
|
||||
/// <reference types="next/image-types/global" />
|
||||
|
||||
// NOTE: This file should not be edited
|
||||
// see https://nextjs.org/docs/basic-features/typescript for more information.
|
@ -1,98 +0,0 @@
|
||||
const path = require("path");
|
||||
|
||||
const ContentSecurityPolicy = `
|
||||
default-src 'self';
|
||||
connect-src 'self' https://*.posthog.com http://127.0.0.1:*;
|
||||
script-src 'self' https://*.posthog.com https://js.stripe.com https://api.stripe.com https://widget.intercom.io https://js.intercomcdn.com https://hcaptcha.com https://*.hcaptcha.com 'unsafe-inline' 'unsafe-eval';
|
||||
style-src 'self' https://rsms.me 'unsafe-inline' https://hcaptcha.com https://*.hcaptcha.com;
|
||||
child-src https://api.stripe.com;
|
||||
frame-src https://js.stripe.com/ https://api.stripe.com https://www.youtube.com/ https://hcaptcha.com https://*.hcaptcha.com;
|
||||
connect-src 'self' wss://nexus-websocket-a.intercom.io https://api-iam.intercom.io https://api.heroku.com/ https://id.heroku.com/oauth/authorize https://id.heroku.com/oauth/token https://checkout.stripe.com https://app.posthog.com https://api.stripe.com https://api.pwnedpasswords.com http://127.0.0.1:* https://hcaptcha.com https://*.hcaptcha.com;
|
||||
img-src 'self' https://static.intercomassets.com https://js.intercomcdn.com https://downloads.intercomcdn.com https://*.stripe.com https://i.ytimg.com/ data:;
|
||||
media-src https://js.intercomcdn.com;
|
||||
font-src 'self' https://fonts.intercomcdn.com/ https://maxcdn.bootstrapcdn.com https://rsms.me https://fonts.gstatic.com;
|
||||
`;
|
||||
|
||||
// You can choose which headers to add to the list
|
||||
// after learning more below.
|
||||
const securityHeaders = [
|
||||
{
|
||||
key: "X-DNS-Prefetch-Control",
|
||||
value: "on"
|
||||
},
|
||||
{
|
||||
key: "Strict-Transport-Security",
|
||||
value: "max-age=63072000; includeSubDomains; preload"
|
||||
},
|
||||
{
|
||||
key: "X-XSS-Protection",
|
||||
value: "1; mode=block"
|
||||
},
|
||||
{
|
||||
key: "X-Frame-Options",
|
||||
value: "SAMEORIGIN"
|
||||
},
|
||||
{
|
||||
key: "Permissions-Policy",
|
||||
value: "camera=(), microphone=()"
|
||||
},
|
||||
{
|
||||
key: "X-Content-Type-Options",
|
||||
value: "nosniff"
|
||||
},
|
||||
{
|
||||
key: "Referrer-Policy",
|
||||
value: "strict-origin-when-cross-origin"
|
||||
},
|
||||
{
|
||||
key: "Content-Security-Policy",
|
||||
value: ContentSecurityPolicy.replace(/\s{2,}/g, " ").trim()
|
||||
}
|
||||
];
|
||||
/**
|
||||
* @type {import('next').NextConfig}
|
||||
**/
|
||||
module.exports = {
|
||||
output: "standalone",
|
||||
i18n: {
|
||||
locales: ["en", "ko", "fr", "pt-BR", "pt-PT", "es"],
|
||||
defaultLocale: "en"
|
||||
},
|
||||
async headers() {
|
||||
return [
|
||||
{
|
||||
// Apply these headers to all routes in your application.
|
||||
source: "/:path*",
|
||||
headers: securityHeaders
|
||||
}
|
||||
];
|
||||
},
|
||||
webpack: (config, { isServer, webpack }) => {
|
||||
// config
|
||||
config.module.rules.push({
|
||||
test: /\.wasm$/,
|
||||
loader: "base64-loader",
|
||||
type: "javascript/auto"
|
||||
});
|
||||
|
||||
config.module.noParse = /\.wasm$/;
|
||||
|
||||
config.module.rules.forEach((rule) => {
|
||||
(rule.oneOf || []).forEach((oneOf) => {
|
||||
if (oneOf.loader && oneOf.loader.indexOf("file-loader") >= 0) {
|
||||
oneOf.exclude.push(/\.wasm$/);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
if (!isServer) {
|
||||
config.resolve.fallback.fs = false;
|
||||
}
|
||||
|
||||
// Perform customizations to webpack config
|
||||
config.plugins.push(new webpack.IgnorePlugin({ resourceRegExp: /\/__tests__\// }));
|
||||
|
||||
// Important: return the modified config
|
||||
return config;
|
||||
}
|
||||
};
|
23584
frontend/package-lock.json
generated
23584
frontend/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -1,165 +1,134 @@
|
||||
{
|
||||
"name": "frontend-v2",
|
||||
"private": true,
|
||||
"version": "0.0.0",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"prepare": "cd .. && npm install",
|
||||
"dev": "next dev",
|
||||
"build": "next build",
|
||||
"start": "next start",
|
||||
"start:docker": "next build && next start",
|
||||
"lint": "eslint --ext js,ts,tsx ./src",
|
||||
"lint:fix": "eslint --fix --ext js,ts,tsx ./src",
|
||||
"type:check": "tsc --project tsconfig.json --noEmit",
|
||||
"storybook": "storybook dev -p 6006 -s ./public",
|
||||
"build-storybook": "storybook build"
|
||||
},
|
||||
"overrides": {
|
||||
"@storybook/nextjs": {
|
||||
"sharp": "npm:dry-uninstall"
|
||||
}
|
||||
"dev": "vite",
|
||||
"build": "tsc -b && vite build",
|
||||
"preview": "vite preview",
|
||||
"lint": "eslint ./src",
|
||||
"lint:fix": "eslint --fix ./src",
|
||||
"type:check": "tsc --noEmit --project ./tsconfig.app.json"
|
||||
},
|
||||
"dependencies": {
|
||||
"@casl/ability": "^6.5.0",
|
||||
"@casl/react": "^3.1.0",
|
||||
"@dnd-kit/core": "^6.0.8",
|
||||
"@dnd-kit/modifiers": "^6.0.1",
|
||||
"@dnd-kit/sortable": "^7.0.2",
|
||||
"@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",
|
||||
"@fortawesome/free-solid-svg-icons": "^6.1.2",
|
||||
"@fortawesome/react-fontawesome": "^0.2.0",
|
||||
"@hcaptcha/react-hcaptcha": "^1.10.1",
|
||||
"@headlessui/react": "^1.7.7",
|
||||
"@hookform/resolvers": "^2.9.10",
|
||||
"@octokit/rest": "^19.0.7",
|
||||
"@peculiar/x509": "^1.11.0",
|
||||
"@radix-ui/react-accordion": "^1.1.2",
|
||||
"@radix-ui/react-alert-dialog": "^1.0.5",
|
||||
"@radix-ui/react-checkbox": "^1.0.4",
|
||||
"@radix-ui/react-collapsible": "^1.0.3",
|
||||
"@radix-ui/react-dialog": "^1.0.5",
|
||||
"@radix-ui/react-dropdown-menu": "^2.0.6",
|
||||
"@radix-ui/react-hover-card": "^1.0.7",
|
||||
"@radix-ui/react-label": "^2.0.2",
|
||||
"@radix-ui/react-popover": "^1.0.7",
|
||||
"@radix-ui/react-popper": "^1.1.3",
|
||||
"@radix-ui/react-progress": "^1.0.3",
|
||||
"@radix-ui/react-radio-group": "^1.1.3",
|
||||
"@radix-ui/react-select": "^2.0.0",
|
||||
"@radix-ui/react-switch": "^1.0.3",
|
||||
"@radix-ui/react-tabs": "^1.0.4",
|
||||
"@radix-ui/react-toast": "^1.1.5",
|
||||
"@radix-ui/react-tooltip": "^1.0.7",
|
||||
"@reduxjs/toolkit": "^1.8.3",
|
||||
"@sindresorhus/slugify": "1.1.0",
|
||||
"@stripe/react-stripe-js": "^1.16.3",
|
||||
"@stripe/stripe-js": "^1.46.0",
|
||||
"@tanstack/react-query": "^4.23.0",
|
||||
"@types/argon2-browser": "^1.18.1",
|
||||
"@casl/ability": "^6.7.2",
|
||||
"@casl/react": "^4.0.0",
|
||||
"@dnd-kit/core": "^6.3.1",
|
||||
"@dnd-kit/modifiers": "^9.0.0",
|
||||
"@dnd-kit/sortable": "^10.0.0",
|
||||
"@fontsource/inter": "^5.1.0",
|
||||
"@fortawesome/fontawesome-svg-core": "^6.7.1",
|
||||
"@fortawesome/free-brands-svg-icons": "^6.7.1",
|
||||
"@fortawesome/free-regular-svg-icons": "^6.7.1",
|
||||
"@fortawesome/free-solid-svg-icons": "^6.7.1",
|
||||
"@fortawesome/react-fontawesome": "^0.2.2",
|
||||
"@hcaptcha/react-hcaptcha": "^1.11.0",
|
||||
"@headlessui/react": "^1.7.19",
|
||||
"@hookform/resolvers": "^3.9.1",
|
||||
"@lottiefiles/dotlottie-react": "^0.12.0",
|
||||
"@octokit/rest": "^21.0.2",
|
||||
"@peculiar/x509": "^1.12.3",
|
||||
"@radix-ui/react-accordion": "^1.2.2",
|
||||
"@radix-ui/react-alert-dialog": "^1.1.3",
|
||||
"@radix-ui/react-checkbox": "^1.1.3",
|
||||
"@radix-ui/react-collapsible": "^1.1.2",
|
||||
"@radix-ui/react-dialog": "^1.1.3",
|
||||
"@radix-ui/react-dropdown-menu": "^2.1.3",
|
||||
"@radix-ui/react-hover-card": "^1.1.3",
|
||||
"@radix-ui/react-label": "^2.1.1",
|
||||
"@radix-ui/react-popover": "^1.1.3",
|
||||
"@radix-ui/react-popper": "^1.2.1",
|
||||
"@radix-ui/react-progress": "^1.1.1",
|
||||
"@radix-ui/react-radio-group": "^1.2.2",
|
||||
"@radix-ui/react-select": "^2.1.3",
|
||||
"@radix-ui/react-switch": "^1.1.2",
|
||||
"@radix-ui/react-tabs": "^1.1.2",
|
||||
"@radix-ui/react-toast": "^1.2.3",
|
||||
"@radix-ui/react-tooltip": "^1.1.5",
|
||||
"@sindresorhus/slugify": "^2.2.1",
|
||||
"@tanstack/react-query": "^5.62.7",
|
||||
"@tanstack/react-router": "^1.95.1",
|
||||
"@tanstack/virtual-file-routes": "^1.87.6",
|
||||
"@tanstack/zod-adapter": "^1.91.0",
|
||||
"@types/nprogress": "^0.2.3",
|
||||
"@ucast/mongo2js": "^1.3.4",
|
||||
"add": "^2.0.6",
|
||||
"argon2-browser": "^1.18.0",
|
||||
"axios": "^0.28.0",
|
||||
"axios-auth-refresh": "^3.3.6",
|
||||
"base64-loader": "^1.0.0",
|
||||
"classnames": "^2.3.1",
|
||||
"cookies": "^0.9.1",
|
||||
"cva": "npm:class-variance-authority@^0.4.0",
|
||||
"date-fns": "^2.30.0",
|
||||
"axios": "^1.7.9",
|
||||
"classnames": "^2.5.1",
|
||||
"cva": "npm:class-variance-authority@^0.7.1",
|
||||
"date-fns": "^4.1.0",
|
||||
"file-saver": "^2.0.5",
|
||||
"framer-motion": "^6.2.3",
|
||||
"fs": "^0.0.2",
|
||||
"gray-matter": "^4.0.3",
|
||||
"http-proxy": "^1.18.1",
|
||||
"i18next": "^22.4.15",
|
||||
"i18next-browser-languagedetector": "^7.0.1",
|
||||
"i18next-http-backend": "^2.2.0",
|
||||
"infisical-node": "^1.0.37",
|
||||
"framer-motion": "^11.14.1",
|
||||
"i18next": "^24.1.0",
|
||||
"i18next-browser-languagedetector": "^8.0.2",
|
||||
"i18next-http-backend": "^3.0.1",
|
||||
"jspdf": "^2.5.2",
|
||||
"jsrp": "^0.2.4",
|
||||
"jwt-decode": "^3.1.2",
|
||||
"lottie-react": "^2.4.0",
|
||||
"markdown-it": "^13.0.1",
|
||||
"jwt-decode": "^4.0.0",
|
||||
"ms": "^2.1.3",
|
||||
"next": "^12.3.4",
|
||||
"nprogress": "^0.2.0",
|
||||
"picomatch": "^2.3.1",
|
||||
"posthog-js": "^1.105.6",
|
||||
"picomatch": "^4.0.2",
|
||||
"posthog-js": "^1.198.0",
|
||||
"qrcode": "^1.5.4",
|
||||
"query-string": "^7.1.3",
|
||||
"react": "^17.0.2",
|
||||
"react-beautiful-dnd": "^13.1.1",
|
||||
"react": "^18.3.1",
|
||||
"react-code-input": "^3.10.1",
|
||||
"react-day-picker": "^8.8.0",
|
||||
"react-dom": "^17.0.2",
|
||||
"react-grid-layout": "^1.3.4",
|
||||
"react-hook-form": "^7.43.0",
|
||||
"react-i18next": "^12.2.2",
|
||||
"react-icons": "^5.3.0",
|
||||
"react-mailchimp-subscribe": "^2.1.3",
|
||||
"react-markdown": "^8.0.3",
|
||||
"react-redux": "^8.0.2",
|
||||
"react-select": "^5.8.1",
|
||||
"react-table": "^7.8.0",
|
||||
"react-toastify": "^9.1.3",
|
||||
"sanitize-html": "^2.12.1",
|
||||
"set-cookie-parser": "^2.5.1",
|
||||
"sharp": "^0.33.2",
|
||||
"styled-components": "^5.3.7",
|
||||
"tailwind-merge": "^1.8.1",
|
||||
"react-day-picker": "^9.4.3",
|
||||
"react-dom": "^18.3.1",
|
||||
"react-helmet": "^6.1.0",
|
||||
"react-hook-form": "^7.54.0",
|
||||
"react-i18next": "^15.2.0",
|
||||
"react-icons": "^5.4.0",
|
||||
"react-select": "^5.9.0",
|
||||
"react-toastify": "^10.0.6",
|
||||
"redaxios": "^0.5.1",
|
||||
"tailwind-merge": "^2.5.5",
|
||||
"tweetnacl": "^1.0.3",
|
||||
"tweetnacl-util": "^0.15.1",
|
||||
"uuid": "^8.3.2",
|
||||
"uuidv4": "^6.2.13",
|
||||
"yaml": "^2.2.2",
|
||||
"yup": "^0.32.11",
|
||||
"zod": "^3.22.3",
|
||||
"zustand": "^4.5.0"
|
||||
"yaml": "^2.6.1",
|
||||
"zod": "^3.24.1",
|
||||
"zustand": "^5.0.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@storybook/addon-essentials": "^7.5.2",
|
||||
"@storybook/addon-interactions": "^7.0.23",
|
||||
"@storybook/addon-links": "^7.0.23",
|
||||
"@storybook/addon-styling": "^1.3.0",
|
||||
"@storybook/blocks": "^7.0.23",
|
||||
"@storybook/client-api": "^7.2.1",
|
||||
"@storybook/nextjs": "^7.0.23",
|
||||
"@storybook/react": "^7.0.23",
|
||||
"@storybook/testing-library": "^0.2.0",
|
||||
"@tailwindcss/typography": "^0.5.4",
|
||||
"@types/file-saver": "^2.0.5",
|
||||
"@types/jsrp": "^0.2.4",
|
||||
"@types/node": "^18.11.9",
|
||||
"@types/picomatch": "^2.3.0",
|
||||
"@eslint/eslintrc": "^3.2.0",
|
||||
"@eslint/js": "^9.15.0",
|
||||
"@kesills/eslint-config-airbnb-typescript": "^20.0.0",
|
||||
"@stylistic/eslint-plugin": "^2.12.1",
|
||||
"@tailwindcss/typography": "^0.5.15",
|
||||
"@tanstack/eslint-plugin-router": "^1.87.6",
|
||||
"@tanstack/router-devtools": "^1.87.9",
|
||||
"@tanstack/router-plugin": "^1.95.1",
|
||||
"@types/argon2-browser": "^1.18.4",
|
||||
"@types/file-saver": "^2.0.7",
|
||||
"@types/jsrp": "^0.2.6",
|
||||
"@types/ms": "^0.7.34",
|
||||
"@types/picomatch": "^3.0.1",
|
||||
"@types/qrcode": "^1.5.5",
|
||||
"@types/react": "^18.0.26",
|
||||
"@types/sanitize-html": "^2.9.0",
|
||||
"@typescript-eslint/eslint-plugin": "^5.48.1",
|
||||
"@typescript-eslint/parser": "^5.45.0",
|
||||
"autoprefixer": "^10.4.7",
|
||||
"cypress": "^13.3.2",
|
||||
"eslint": "^8.32.0",
|
||||
"@types/react": "^18.3.12",
|
||||
"@types/react-dom": "^18.3.1",
|
||||
"@types/react-helmet": "^6.1.11",
|
||||
"@vitejs/plugin-react-swc": "^3.5.0",
|
||||
"autoprefixer": "^10.4.20",
|
||||
"eslint": "^8.57.1",
|
||||
"eslint-config-airbnb": "^19.0.4",
|
||||
"eslint-config-airbnb-typescript": "^17.0.0",
|
||||
"eslint-config-next": "^13.0.5",
|
||||
"eslint-config-prettier": "^8.6.0",
|
||||
"eslint-import-resolver-typescript": "^3.5.2",
|
||||
"eslint-plugin-import": "^2.27.4",
|
||||
"eslint-plugin-jsx-a11y": "^6.7.1",
|
||||
"eslint-plugin-prettier": "^4.2.1",
|
||||
"eslint-plugin-react": "^7.32.0",
|
||||
"eslint-plugin-react-hooks": "^4.6.0",
|
||||
"eslint-plugin-simple-import-sort": "^8.0.0",
|
||||
"eslint-plugin-storybook": "^0.6.12",
|
||||
"postcss": "^8.4.39",
|
||||
"prettier": "^2.8.3",
|
||||
"prettier-plugin-tailwindcss": "^0.2.2",
|
||||
"storybook": "^7.6.20",
|
||||
"storybook-dark-mode": "^3.0.0",
|
||||
"tailwindcss": "3.2",
|
||||
"typescript": "^4.9.3"
|
||||
"eslint-config-prettier": "^9.1.0",
|
||||
"eslint-import-resolver-typescript": "^3.7.0",
|
||||
"eslint-plugin-import": "^2.31.0",
|
||||
"eslint-plugin-prettier": "^5.2.1",
|
||||
"eslint-plugin-react-hooks": "^4.6.2",
|
||||
"eslint-plugin-react-refresh": "^0.4.14",
|
||||
"eslint-plugin-simple-import-sort": "^12.1.1",
|
||||
"globals": "^15.12.0",
|
||||
"postcss": "^8.4.49",
|
||||
"prettier": "3.4.2",
|
||||
"prettier-plugin-tailwindcss": "^0.6.9",
|
||||
"tailwindcss": "^3.4.16",
|
||||
"typescript": "~5.6.2",
|
||||
"typescript-eslint": "^8.15.0",
|
||||
"vite": "^5.4.11",
|
||||
"vite-plugin-node-polyfills": "^0.22.0",
|
||||
"vite-plugin-top-level-await": "^1.4.4",
|
||||
"vite-plugin-wasm": "^3.3.0",
|
||||
"vite-tsconfig-paths": "^5.1.4"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
module.exports = {
|
||||
export default {
|
||||
plugins: {
|
||||
tailwindcss: {},
|
||||
autoprefixer: {},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
@ -1,94 +0,0 @@
|
||||
interface Mapping {
|
||||
[key: string]: string;
|
||||
}
|
||||
|
||||
const integrationSlugNameMapping: Mapping = {
|
||||
"azure-key-vault": "Azure Key Vault",
|
||||
"aws-parameter-store": "AWS Parameter Store",
|
||||
"aws-secret-manager": "AWS Secrets Manager",
|
||||
heroku: "Heroku",
|
||||
vercel: "Vercel",
|
||||
netlify: "Netlify",
|
||||
github: "GitHub",
|
||||
gitlab: "GitLab",
|
||||
render: "Render",
|
||||
"laravel-forge": "Laravel Forge",
|
||||
railway: "Railway",
|
||||
flyio: "Fly.io",
|
||||
circleci: "CircleCI",
|
||||
databricks: "Databricks",
|
||||
travisci: "TravisCI",
|
||||
supabase: "Supabase",
|
||||
checkly: "Checkly",
|
||||
qovery: "Qovery",
|
||||
"terraform-cloud": "Terraform Cloud",
|
||||
teamcity: "TeamCity",
|
||||
"hashicorp-vault": "Vault",
|
||||
"cloudflare-pages": "Cloudflare Pages",
|
||||
"cloudflare-workers": "Cloudflare Workers",
|
||||
codefresh: "Codefresh",
|
||||
"digital-ocean-app-platform": "Digital Ocean App Platform",
|
||||
bitbucket: "Bitbucket",
|
||||
"cloud-66": "Cloud 66",
|
||||
northflank: "Northflank",
|
||||
windmill: "Windmill",
|
||||
"gcp-secret-manager": "GCP Secret Manager",
|
||||
"hasura-cloud": "Hasura Cloud",
|
||||
rundeck: "Rundeck",
|
||||
"azure-devops": "Azure DevOps",
|
||||
"azure-app-configuration": "Azure App Configuration",
|
||||
"octopus-deploy": "Octopus Deploy"
|
||||
};
|
||||
|
||||
const envMapping: Mapping = {
|
||||
Development: "dev",
|
||||
Staging: "staging",
|
||||
Production: "prod",
|
||||
Testing: "test"
|
||||
};
|
||||
|
||||
const reverseEnvMapping: Mapping = {
|
||||
dev: "Development",
|
||||
staging: "Staging",
|
||||
prod: "Production",
|
||||
test: "Testing"
|
||||
};
|
||||
|
||||
const contextNetlifyMapping: Mapping = {
|
||||
dev: "Local development",
|
||||
"branch-deploy": "Branch deploys",
|
||||
"deploy-preview": "Deploy Previews",
|
||||
production: "Production"
|
||||
};
|
||||
|
||||
const reverseContextNetlifyMapping: Mapping = {
|
||||
"Local development": "dev",
|
||||
"Branch deploys": "branch-deploy",
|
||||
"Deploy Previews": "deploy-preview",
|
||||
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,
|
||||
integrationSlugNameMapping,
|
||||
plans,
|
||||
reverseContextNetlifyMapping,
|
||||
reverseEnvMapping
|
||||
};
|
@ -1,19 +0,0 @@
|
||||
export interface Tag {
|
||||
id: string;
|
||||
name: string;
|
||||
slug: string;
|
||||
user: string;
|
||||
workspace: string;
|
||||
createdAt: string;
|
||||
}
|
||||
|
||||
export interface SecretDataProps {
|
||||
pos: number;
|
||||
key: string;
|
||||
value: string | undefined;
|
||||
valueOverride: string | undefined;
|
||||
id: string;
|
||||
idOverride?: string;
|
||||
comment: string;
|
||||
tags: Tag[];
|
||||
}
|
1
frontend/public/lotties/circular-check.json
Normal file
1
frontend/public/lotties/circular-check.json
Normal file
File diff suppressed because one or more lines are too long
1
frontend/public/lotties/groups.json
Normal file
1
frontend/public/lotties/groups.json
Normal file
File diff suppressed because one or more lines are too long
1
frontend/public/lotties/jigsaw-puzzle.json
Normal file
1
frontend/public/lotties/jigsaw-puzzle.json
Normal file
File diff suppressed because one or more lines are too long
1
frontend/public/lotties/lock-closed.json
Normal file
1
frontend/public/lotties/lock-closed.json
Normal file
File diff suppressed because one or more lines are too long
1
frontend/public/lotties/moving-block.json
Normal file
1
frontend/public/lotties/moving-block.json
Normal file
File diff suppressed because one or more lines are too long
1
frontend/public/lotties/secret-scan.json
Normal file
1
frontend/public/lotties/secret-scan.json
Normal file
File diff suppressed because one or more lines are too long
1
frontend/public/lotties/sliding-carousel.json
Normal file
1
frontend/public/lotties/sliding-carousel.json
Normal file
File diff suppressed because one or more lines are too long
1
frontend/public/lotties/spinning-coin.json
Normal file
1
frontend/public/lotties/spinning-coin.json
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
1
frontend/public/lotties/toggle-settings.json
Normal file
1
frontend/public/lotties/toggle-settings.json
Normal file
File diff suppressed because one or more lines are too long
1
frontend/public/lotties/verified.json
Normal file
1
frontend/public/lotties/verified.json
Normal file
File diff suppressed because one or more lines are too long
@ -1,4 +0,0 @@
|
||||
<svg width="283" height="64" viewBox="0 0 283 64" fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M141.04 16c-11.04 0-19 7.2-19 18s8.96 18 20 18c6.67 0 12.55-2.64 16.19-7.09l-7.65-4.42c-2.02 2.21-5.09 3.5-8.54 3.5-4.79 0-8.86-2.5-10.37-6.5h28.02c.22-1.12.35-2.28.35-3.5 0-10.79-7.96-17.99-19-17.99zm-9.46 14.5c1.25-3.99 4.67-6.5 9.45-6.5 4.79 0 8.21 2.51 9.45 6.5h-18.9zM248.72 16c-11.04 0-19 7.2-19 18s8.96 18 20 18c6.67 0 12.55-2.64 16.19-7.09l-7.65-4.42c-2.02 2.21-5.09 3.5-8.54 3.5-4.79 0-8.86-2.5-10.37-6.5h28.02c.22-1.12.35-2.28.35-3.5 0-10.79-7.96-17.99-19-17.99zm-9.45 14.5c1.25-3.99 4.67-6.5 9.45-6.5 4.79 0 8.21 2.51 9.45 6.5h-18.9zM200.24 34c0 6 3.92 10 10 10 4.12 0 7.21-1.87 8.8-4.92l7.68 4.43c-3.18 5.3-9.14 8.49-16.48 8.49-11.05 0-19-7.2-19-18s7.96-18 19-18c7.34 0 13.29 3.19 16.48 8.49l-7.68 4.43c-1.59-3.05-4.68-4.92-8.8-4.92-6.07 0-10 4-10 10zm82.48-29v46h-9V5h9zM36.95 0L73.9 64H0L36.95 0zm92.38 5l-27.71 48L73.91 5H84.3l17.32 30 17.32-30h10.39zm58.91 12v9.69c-1-.29-2.06-.49-3.2-.49-5.81 0-10 4-10 10V51h-9V17h9v9.2c0-5.08 5.91-9.2 13.2-9.2z" fill="#000"/>
|
||||
</svg>
|
Before (image error) Size: 1.1 KiB |
1
frontend/public/vite.svg
Normal file
1
frontend/public/vite.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>
|
After (image error) Size: 1.5 KiB |
@ -6,6 +6,8 @@ scripts/replace-standalone-build-variable.sh "$BAKED_NEXT_PUBLIC_INTERCOM_ID" "$
|
||||
|
||||
scripts/replace-standalone-build-variable.sh "$BAKED_NEXT_PUBLIC_CAPTCHA_SITE_KEY" "$NEXT_PUBLIC_CAPTCHA_SITE_KEY"
|
||||
|
||||
scripts/set-frontend-config.sh
|
||||
|
||||
if [ "$TELEMETRY_ENABLED" != "false" ]; then
|
||||
echo "Telemetry is enabled"
|
||||
scripts/set-standalone-build-telemetry.sh true
|
||||
|
@ -10,7 +10,7 @@ fi
|
||||
|
||||
echo "Replacing pre-baked value.."
|
||||
|
||||
find public .next -type f -name "*.js" |
|
||||
find assets -type f -name "*.js" |
|
||||
while read file; do
|
||||
sed -i "s|$ORIGINAL|$REPLACEMENT|g" "$file"
|
||||
done
|
||||
|
9
frontend/scripts/set-frontend-config.sh
Executable file
9
frontend/scripts/set-frontend-config.sh
Executable file
@ -0,0 +1,9 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Configuration output file
|
||||
CONFIG_FILE="runtime-config.js"
|
||||
|
||||
# Replace content in the config file with SENTRY_DSN interpolation
|
||||
echo "window.__CONFIG__ = Object.freeze({ CAPTCHA_SITE_KEY: \"${CAPTCHA_SITE_KEY}\", CAPTCHA_SITE_KEY: \"${CAPTCHA_SITE_KEY}\", CAPTCHA_SITE_KEY: \"${CAPTCHA_SITE_KEY}\" })" > $CONFIG_FILE
|
||||
|
||||
echo "Configuration file updated at $CONFIG_FILE"
|
@ -1,92 +0,0 @@
|
||||
import { faPlus } from "@fortawesome/free-solid-svg-icons";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
|
||||
import { Button, Checkbox, PopoverContent } from "@app/components/v2";
|
||||
import { ProjectPermissionActions, ProjectPermissionSub } from "@app/context";
|
||||
|
||||
import { WsTag } from "../../hooks/api/tags/types";
|
||||
import { ProjectPermissionCan } from "../permissions";
|
||||
|
||||
interface Props {
|
||||
wsTags: WsTag[] | undefined;
|
||||
secKey: string;
|
||||
selectedTagIds: Record<string, boolean>;
|
||||
handleSelectTag: (wsTag: WsTag) => void;
|
||||
handleTagOnMouseEnter: (wsTag: WsTag) => void;
|
||||
handleTagOnMouseLeave: () => void;
|
||||
checkIfTagIsVisible: (wsTag: WsTag) => boolean;
|
||||
handleOnCreateTagOpen: () => void;
|
||||
}
|
||||
|
||||
const AddTagPopoverContent = ({
|
||||
wsTags,
|
||||
secKey,
|
||||
selectedTagIds,
|
||||
handleSelectTag,
|
||||
handleTagOnMouseEnter,
|
||||
handleTagOnMouseLeave,
|
||||
checkIfTagIsVisible,
|
||||
handleOnCreateTagOpen
|
||||
}: Props) => {
|
||||
return (
|
||||
<PopoverContent
|
||||
side="left"
|
||||
className="relative max-h-96 w-auto min-w-[200px] overflow-y-auto overflow-x-hidden border border-mineshaft-600 bg-mineshaft-800 p-2 text-bunker-200"
|
||||
hideCloseBtn
|
||||
>
|
||||
<div className=" text-center text-sm font-medium text-bunker-200">
|
||||
Add tags to {secKey || "this secret"}
|
||||
</div>
|
||||
<div className="absolute left-0 mt-2 w-full border-t border-mineshaft-600" />
|
||||
<div className="flex flex-col space-y-1.5">
|
||||
{wsTags?.map((wsTag: WsTag) => (
|
||||
<div
|
||||
key={`tag-${wsTag.id}`}
|
||||
className="relative mt-4 flex h-[32px] items-center justify-start rounded-md bg-none p-2 hover:border hover:border-mineshaft-600 hover:bg-mineshaft-700 hover:text-bunker-200"
|
||||
onClick={() => handleSelectTag(wsTag)}
|
||||
onMouseEnter={() => handleTagOnMouseEnter(wsTag)}
|
||||
onMouseLeave={() => handleTagOnMouseLeave()}
|
||||
tabIndex={0}
|
||||
role="button"
|
||||
onKeyDown={() => {}}
|
||||
>
|
||||
{(checkIfTagIsVisible(wsTag) || selectedTagIds?.[wsTag.slug]) && (
|
||||
<Checkbox
|
||||
id="autoCapitalization"
|
||||
isChecked={selectedTagIds?.[wsTag.slug]}
|
||||
className="absolute top-[50%] left-[10px] translate-y-[-50%] "
|
||||
checkIndicatorBg={`${
|
||||
!selectedTagIds?.[wsTag.slug] ? "text-transparent" : "text-mineshaft-800"
|
||||
}`}
|
||||
/>
|
||||
)}
|
||||
<div className="ml-7 flex items-center gap-3">
|
||||
<div
|
||||
className="h-[10px] w-[10px] rounded-full"
|
||||
style={{ background: wsTag?.color ? wsTag.color : "#bec2c8" }}
|
||||
>
|
||||
{" "}
|
||||
</div>
|
||||
<span>{wsTag.slug}</span>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
<ProjectPermissionCan I={ProjectPermissionActions.Create} a={ProjectPermissionSub.Tags}>
|
||||
{(isAllowed) => (
|
||||
<Button
|
||||
onClick={() => handleOnCreateTagOpen()}
|
||||
isDisabled={!isAllowed}
|
||||
size="xs"
|
||||
className="mt-2"
|
||||
leftIcon={<FontAwesomeIcon icon={faPlus} className="ml-1 mr-2" />}
|
||||
>
|
||||
Add new tag
|
||||
</Button>
|
||||
)}
|
||||
</ProjectPermissionCan>
|
||||
</div>
|
||||
</PopoverContent>
|
||||
);
|
||||
};
|
||||
|
||||
export default AddTagPopoverContent;
|
@ -1,72 +0,0 @@
|
||||
import { ReactNode, useEffect, useState } from "react";
|
||||
import { useRouter } from "next/router";
|
||||
|
||||
import { publicPaths } from "@app/const";
|
||||
import checkAuth from "@app/pages/api/auth/CheckAuth";
|
||||
|
||||
// #TODO: finish spinner only when the data loads fully
|
||||
// #TODO: Redirect somewhere if the page does not exist
|
||||
|
||||
type Prop = {
|
||||
children: ReactNode;
|
||||
};
|
||||
|
||||
export default function RouteGuard({ children }: Prop): JSX.Element {
|
||||
const router = useRouter();
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const [authorized, setAuthorized] = useState(false);
|
||||
|
||||
/**
|
||||
* redirect to login page if accessing a private page and not logged in
|
||||
*/
|
||||
async function authCheck(url: string) {
|
||||
// Make sure that we don't redirect when the user is on the following pages.
|
||||
const path = `/${url.split("?")[0].split("/")[1]}`;
|
||||
|
||||
// Check if the user is authenticated
|
||||
const response = await checkAuth();
|
||||
// #TODO: figure our why sometimes it doesn't output a response
|
||||
// ANS(akhilmhdh): Because inside the security client the await token() doesn't have try/catch
|
||||
if (!publicPaths.includes(path)) {
|
||||
try {
|
||||
if (response.status !== 200) {
|
||||
router.push("/login");
|
||||
console.log("Unauthorized to access.");
|
||||
setAuthorized(false);
|
||||
} else {
|
||||
setAuthorized(true);
|
||||
console.log("Authorized to access.");
|
||||
}
|
||||
} catch (error) {
|
||||
console.log("Error (probably the authCheck route is stuck again...):", error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
// on initial load - run auth check
|
||||
(async () => {
|
||||
await authCheck(router.asPath);
|
||||
})();
|
||||
|
||||
// on route change start - hide page content by setting authorized to false
|
||||
// #TODO: add the loading page when not yet authorized.
|
||||
const hideContent = () => setAuthorized(false);
|
||||
// const onError = () => setAuthorized(true)
|
||||
router.events.on("routeChangeStart", hideContent);
|
||||
// router.events.on("routeChangeError", onError);
|
||||
|
||||
// on route change complete - run auth check
|
||||
router.events.on("routeChangeComplete", authCheck);
|
||||
|
||||
// unsubscribe from events in useEffect return function
|
||||
return () => {
|
||||
router.events.off("routeChangeStart", hideContent);
|
||||
router.events.off("routeChangeComplete", authCheck);
|
||||
// router.events.off("routeChangeError", onError);
|
||||
};
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
|
||||
return children as JSX.Element;
|
||||
}
|
@ -1,18 +1,18 @@
|
||||
/* eslint-disable @typescript-eslint/ban-ts-comment */
|
||||
/* eslint-disable no-undef */
|
||||
import posthog from "posthog-js";
|
||||
|
||||
import { ENV, POSTHOG_API_KEY, POSTHOG_HOST } from "../utilities/config";
|
||||
import { envConfig } from "@app/config/env";
|
||||
|
||||
export const initPostHog = () => {
|
||||
// @ts-ignore
|
||||
console.log("Hi there 👋");
|
||||
try {
|
||||
if (typeof window !== "undefined") {
|
||||
// @ts-ignore
|
||||
if (ENV === "production" && TELEMETRY_CAPTURING_ENABLED === true) {
|
||||
posthog.init(POSTHOG_API_KEY, {
|
||||
api_host: POSTHOG_HOST
|
||||
if (
|
||||
envConfig.ENV === "production" &&
|
||||
envConfig.TELEMETRY_CAPTURING_ENABLED === true &&
|
||||
envConfig.POSTHOG_API_KEY
|
||||
) {
|
||||
posthog.init(envConfig.POSTHOG_API_KEY, {
|
||||
api_host: envConfig.POSTHOG_HOST
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* eslint-disable react/jsx-props-no-spreading */
|
||||
import React, { useState } from "react";
|
||||
import { useState } from "react";
|
||||
import ReactCodeInput from "react-code-input";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
@ -97,7 +97,7 @@ export default function CodeInputStep({
|
||||
fields={6}
|
||||
onChange={setCode}
|
||||
{...props}
|
||||
className="mt-6 mb-2"
|
||||
className="mb-2 mt-6"
|
||||
/>
|
||||
</div>
|
||||
<div className="mx-auto mt-4 block w-max md:hidden">
|
||||
@ -108,7 +108,7 @@ export default function CodeInputStep({
|
||||
fields={6}
|
||||
onChange={setCode}
|
||||
{...propsPhone}
|
||||
className="mt-2 mb-2"
|
||||
className="mb-2 mt-2"
|
||||
/>
|
||||
</div>
|
||||
{codeError && <Error text={t("signup.step2-code-error")} />}
|
@ -32,7 +32,7 @@ export default function DonwloadBackupPDFStep({
|
||||
name
|
||||
}: DownloadBackupPDFStepProps): JSX.Element {
|
||||
const { t } = useTranslation();
|
||||
|
||||
|
||||
const [isLoading, setIsLoading] = useToggle();
|
||||
|
||||
const handleBackupKeyGenerate = async () => {
|
||||
@ -61,17 +61,17 @@ export default function DonwloadBackupPDFStep({
|
||||
<p className="flex flex-col items-center justify-center bg-gradient-to-b from-white to-bunker-200 bg-clip-text text-center text-xl font-medium text-transparent">
|
||||
<FontAwesomeIcon
|
||||
icon={faWarning}
|
||||
className="ml-2 mr-3 mb-6 pt-1 text-6xl text-bunker-200"
|
||||
className="mb-6 ml-2 mr-3 pt-1 text-6xl text-bunker-200"
|
||||
/>
|
||||
{t("signup.step4-message")}
|
||||
</p>
|
||||
<div className="text-md mt-8 flex w-full max-w-md flex-col items-center justify-center rounded-md border border-mineshaft-600 bg-mineshaft-800 pb-2 text-center text-bunker-300 md:min-w-[24rem] lg:w-1/6">
|
||||
<div className="m-2 mx-auto mt-4 flex w-full w-full flex-row items-center rounded-md px-3 text-center text-bunker-300 md:mt-8 md:min-w-[23rem] lg:w-1/6 lg:w-1/6">
|
||||
<div className="m-2 mx-auto mt-4 flex w-full flex-row items-center rounded-md px-3 text-center text-bunker-300 md:mt-8 md:min-w-[23rem] lg:w-1/6">
|
||||
<span className="mb-2">
|
||||
{t("signup.step4-description1")} {t("signup.step4-description3")}
|
||||
</span>
|
||||
</div>
|
||||
<div className="mx-auto mt-0 mb-2 mt-2 flex w-full flex-col items-center justify-center px-3 text-center text-sm md:mt-4 md:mb-4 md:min-w-[20rem] md:max-w-md md:text-left lg:w-1/6">
|
||||
<div className="mx-auto mb-2 mt-2 flex w-full flex-col items-center justify-center px-3 text-center text-sm md:mb-4 md:mt-4 md:min-w-[20rem] md:max-w-md md:text-left lg:w-1/6">
|
||||
<div className="text-l w-full py-1 text-lg">
|
||||
<Button
|
||||
onClick={handleBackupKeyGenerate}
|
15
frontend/src/components/signup/EnterEmailStep.tsx → frontend/src/components/auth/EnterEmailStep.tsx
15
frontend/src/components/signup/EnterEmailStep.tsx → frontend/src/components/auth/EnterEmailStep.tsx
@ -1,6 +1,6 @@
|
||||
import React, { useState } from "react";
|
||||
import { useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import Link from "next/link";
|
||||
import { Link } from "@tanstack/react-router";
|
||||
import axios from "axios";
|
||||
|
||||
import { createNotification } from "@app/components/notifications";
|
||||
@ -27,8 +27,7 @@ export default function EnterEmailStep({
|
||||
setEmail,
|
||||
incrementStep
|
||||
}: DownloadBackupPDFStepProps): JSX.Element {
|
||||
|
||||
const { mutateAsync, isLoading } = useSendVerificationEmail();
|
||||
const { mutateAsync, isPending } = useSendVerificationEmail();
|
||||
const [emailError, setEmailError] = useState(false);
|
||||
const { t } = useTranslation();
|
||||
|
||||
@ -51,7 +50,7 @@ export default function EnterEmailStep({
|
||||
if (!emailCheckBool) {
|
||||
try {
|
||||
await mutateAsync({ email: email.toLowerCase() });
|
||||
setEmail(email.toLowerCase())
|
||||
setEmail(email.toLowerCase());
|
||||
incrementStep();
|
||||
} catch (e) {
|
||||
if (axios.isAxiosError(e)) {
|
||||
@ -96,8 +95,8 @@ export default function EnterEmailStep({
|
||||
className="h-14"
|
||||
colorSchema="primary"
|
||||
variant="outline_bg"
|
||||
isLoading={isLoading}
|
||||
isDisabled={isLoading}
|
||||
isLoading={isPending}
|
||||
isDisabled={isPending}
|
||||
>
|
||||
{" "}
|
||||
{String(t("signup.step1-submit"))}{" "}
|
||||
@ -106,7 +105,7 @@ export default function EnterEmailStep({
|
||||
</div>
|
||||
</div>
|
||||
<div className="mx-auto mb-48 mt-2 flex w-full max-w-md flex-col items-center justify-center pt-2 md:mb-16 md:pb-2">
|
||||
<Link href="/login">
|
||||
<Link to="/login">
|
||||
<button type="button" className="w-max pb-3 duration-200 hover:opacity-90">
|
||||
<span className="cursor-pointer text-sm text-mineshaft-400 duration-200 hover:text-bunker-200 hover:underline hover:decoration-primary-700 hover:underline-offset-4">
|
||||
{t("signup.already-have-account")}
|
@ -1,8 +1,8 @@
|
||||
import { useTranslation } from "react-i18next";
|
||||
import Link from "next/link";
|
||||
import { faGithub, faGitlab, faGoogle } from "@fortawesome/free-brands-svg-icons";
|
||||
import { faEnvelope } from "@fortawesome/free-regular-svg-icons";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { Link } from "@tanstack/react-router";
|
||||
|
||||
import { RegionSelect } from "@app/components/navigation/RegionSelect";
|
||||
import { useServerConfig } from "@app/context";
|
||||
@ -94,7 +94,7 @@ export default function InitialSignupStep({
|
||||
{t("signup.create-policy")}
|
||||
</div>
|
||||
<div className="mt-2 flex flex-row text-xs text-bunker-400">
|
||||
<Link href="/login">
|
||||
<Link to="/login">
|
||||
<span className="cursor-pointer duration-200 hover:text-bunker-200 hover:underline hover:decoration-primary-700 hover:underline-offset-4">
|
||||
{t("signup.already-have-account")}
|
||||
</span>
|
@ -1,8 +1,6 @@
|
||||
import React, { useEffect, useState } from "react";
|
||||
import ReactCodeInput from "react-code-input";
|
||||
import Image from "next/image";
|
||||
import Link from "next/link";
|
||||
import { useRouter } from "next/router";
|
||||
import { Link, useNavigate } from "@tanstack/react-router";
|
||||
import { t } from "i18next";
|
||||
|
||||
import Error from "@app/components/basic/Error";
|
||||
@ -43,7 +41,7 @@ type Props = {
|
||||
|
||||
export const Mfa = ({ successCallback, closeMfa, hideLogo, email, method }: Props) => {
|
||||
const [mfaCode, setMfaCode] = useState("");
|
||||
const router = useRouter();
|
||||
const navigate = useNavigate();
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [isLoadingResend, setIsLoadingResend] = useState(false);
|
||||
const [triesLeft, setTriesLeft] = useState<number | undefined>(undefined);
|
||||
@ -80,11 +78,11 @@ export const Mfa = ({ successCallback, closeMfa, hideLogo, email, method }: Prop
|
||||
if (closeMfa) {
|
||||
closeMfa();
|
||||
}
|
||||
} catch (error) {
|
||||
} catch {
|
||||
if (triesLeft) {
|
||||
setTriesLeft((left) => {
|
||||
if (triesLeft === 1) {
|
||||
router.push("/");
|
||||
navigate({ to: "/" });
|
||||
|
||||
SecurityClient.setMfaToken("");
|
||||
SecurityClient.setToken("");
|
||||
@ -132,9 +130,9 @@ export const Mfa = ({ successCallback, closeMfa, hideLogo, email, method }: Prop
|
||||
return (
|
||||
<div className="mx-auto w-max pb-4 pt-4 md:mb-16 md:px-8">
|
||||
{!hideLogo && (
|
||||
<Link href="/">
|
||||
<Link to="/">
|
||||
<div className="mb-4 flex justify-center">
|
||||
<Image src="/images/gradientLogo.svg" height={90} width={120} alt="Infisical logo" />
|
||||
<img src="/images/gradientLogo.svg" height={90} width={120} alt="Infisical logo" />
|
||||
</div>
|
||||
</Link>
|
||||
)}
|
||||
@ -164,12 +162,12 @@ export const Mfa = ({ successCallback, closeMfa, hideLogo, email, method }: Prop
|
||||
type="text"
|
||||
fields={6}
|
||||
onChange={setMfaCode}
|
||||
className="mt-6 mb-2"
|
||||
className="mb-2 mt-6"
|
||||
{...codeInputProps}
|
||||
/>
|
||||
)}
|
||||
{method === MfaMethod.TOTP && (
|
||||
<div className="mt-6 mb-4">
|
||||
<div className="mb-4 mt-6">
|
||||
<Input value={mfaCode} onChange={(e) => setMfaCode(e.target.value)} />
|
||||
</div>
|
||||
)}
|
||||
@ -194,8 +192,8 @@ export const Mfa = ({ successCallback, closeMfa, hideLogo, email, method }: Prop
|
||||
</div>
|
||||
</form>
|
||||
{method === MfaMethod.TOTP && (
|
||||
<div className="mt-2 flex flex-row justify-center text-sm text-bunker-400 ">
|
||||
<Link href="/verify-email">
|
||||
<div className="mt-2 flex flex-row justify-center text-sm text-bunker-400">
|
||||
<Link to="/verify-email">
|
||||
<span className="cursor-pointer duration-200 hover:text-bunker-200 hover:underline hover:decoration-primary-700 hover:underline-offset-4">
|
||||
Lost your recovery codes? Reset your account
|
||||
</span>
|
18
frontend/src/components/signup/TeamInviteStep.tsx → frontend/src/components/auth/TeamInviteStep.tsx
18
frontend/src/components/signup/TeamInviteStep.tsx → frontend/src/components/auth/TeamInviteStep.tsx
@ -1,6 +1,6 @@
|
||||
import React, { useState } from "react";
|
||||
import { useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useRouter } from "next/router";
|
||||
import { useNavigate } from "@tanstack/react-router";
|
||||
|
||||
import { useAddUsersToOrg } from "@app/hooks/api";
|
||||
import { useFetchServerStatus } from "@app/hooks/api/serverDetails";
|
||||
@ -14,7 +14,7 @@ import { Button, EmailServiceSetupModal } from "../v2";
|
||||
*/
|
||||
export default function TeamInviteStep(): JSX.Element {
|
||||
const { t } = useTranslation();
|
||||
const router = useRouter();
|
||||
const navigate = useNavigate();
|
||||
const [emails, setEmails] = useState("");
|
||||
const { data: serverDetails } = useFetchServerStatus();
|
||||
|
||||
@ -23,7 +23,7 @@ export default function TeamInviteStep(): JSX.Element {
|
||||
|
||||
// Redirect user to the getting started page
|
||||
const redirectToHome = async () => {
|
||||
router.push(`/org/${localStorage.getItem("orgData.id")}/${ProjectType.SecretManager}/overview`);
|
||||
navigate({ to: `/organization/${ProjectType.SecretManager}/overview` as const });
|
||||
};
|
||||
|
||||
const inviteUsers = async ({ emails: inviteEmails }: { emails: string }) => {
|
||||
@ -49,19 +49,19 @@ export default function TeamInviteStep(): JSX.Element {
|
||||
<p className="mb-6 mt-4 flex justify-center text-center text-bunker-400 md:mx-8">
|
||||
{t("signup.step5-subtitle")}
|
||||
</p>
|
||||
<div className="mx-auto mb-6 w-max rounded-xl border border-mineshaft-500 bg-mineshaft-800 px-8 pt-6 pb-4 drop-shadow-xl">
|
||||
<div className="mx-auto mb-6 w-max rounded-xl border border-mineshaft-500 bg-mineshaft-800 px-8 pb-4 pt-6 drop-shadow-xl">
|
||||
<div>
|
||||
<div className="pl-1 pb-1 text-sm font-medium text-bunker-300">
|
||||
<div className="pb-1 pl-1 text-sm font-medium text-bunker-300">
|
||||
<span>Emails</span>
|
||||
</div>
|
||||
<textarea
|
||||
className="h-20 w-full min-w-[30rem] rounded-md border border-mineshaft-500 bg-mineshaft-900/70 py-1 px-2 text-sm text-bunker-300 outline-none ring-primary-800 ring-opacity-70 placeholder:text-bunker-400 focus:ring-2"
|
||||
className="h-20 w-full min-w-[30rem] rounded-md border border-mineshaft-500 bg-mineshaft-900/70 px-2 py-1 text-sm text-bunker-300 outline-none ring-primary-800 ring-opacity-70 placeholder:text-bunker-400 focus:ring-2"
|
||||
value={emails}
|
||||
onChange={(e) => setEmails(e.target.value)}
|
||||
placeholder="email@example.com, email2@example.com..."
|
||||
/>
|
||||
</div>
|
||||
<div className="mx-auto mt-2 flex w-full flex-row items-end justify-end text-sm md:mt-4 md:mb-2 md:min-w-[30rem] md:max-w-md">
|
||||
<div className="mx-auto mt-2 flex w-full flex-row items-end justify-end text-sm md:mb-2 md:mt-4 md:min-w-[30rem] md:max-w-md">
|
||||
<Button
|
||||
onClick={() => {
|
||||
if (serverDetails?.emailConfigured) {
|
||||
@ -85,7 +85,7 @@ export default function TeamInviteStep(): JSX.Element {
|
||||
onOpenChange={(isOpen) => handlePopUpToggle("setUpEmail", isOpen)}
|
||||
/>
|
||||
</div>
|
||||
<div className="min-w-28 mx-auto mt-4 mb-2 flex max-h-24 min-w-[20rem] max-w-max flex-row items-center justify-center px-4 text-lg md:p-2">
|
||||
<div className="mx-auto mb-2 mt-4 flex max-h-24 min-w-[20rem] max-w-max flex-row items-center justify-center px-4 text-lg md:p-2">
|
||||
<Button
|
||||
onClick={redirectToHome}
|
||||
size="sm"
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user