├── .env.dev.example ├── .env.example ├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md ├── pull_request_template.md └── workflows │ ├── backend.yml │ ├── frontend.yml │ └── main.yml ├── .gitignore ├── .vscode └── settings.json ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── SECURITY.md ├── backend ├── Dockerfile ├── Dockerfile.dev ├── README.md ├── api │ ├── __init__.py │ ├── admin.py │ ├── apps.py │ ├── auth.py │ ├── authentication │ │ └── adapters │ │ │ ├── github.py │ │ │ ├── gitlab.py │ │ │ └── google.py │ ├── config.py │ ├── content_negotiation.py │ ├── emails.py │ ├── management │ │ └── commands │ │ │ ├── purge_app_logs.py │ │ │ └── rqworker.py │ ├── migrations │ │ ├── 0001_initial.py │ │ ├── 0002_organisation.py │ │ ├── 0003_organisation_owner.py │ │ ├── 0004_rename_created_on_customuser_created_at_and_more.py │ │ ├── 0005_organisation_identity_key_organisation_name.py │ │ ├── 0006_app.py │ │ ├── 0007_alter_organisation_name.py │ │ ├── 0008_app_app_seed_alter_app_app_token_and_more.py │ │ ├── 0009_alter_app_id_alter_organisation_id.py │ │ ├── 0010_alter_customuser_username.py │ │ ├── 0011_alter_app_id_alter_customuser_userid_and_more.py │ │ ├── 0012_alter_app_id_alter_customuser_userid_and_more.py │ │ ├── 0013_app_version.py │ │ ├── 0014_rename_version_app_app_version.py │ │ ├── 0015_app_deleted_at_app_is_deleted.py │ │ ├── 0016_organisation_plan.py │ │ ├── 0017_environment_secret_secrettag_secretevent_and_more.py │ │ ├── 0018_rename_environment_token_environmentsecret_name_and_more.py │ │ ├── 0019_remove_secret_user_remove_secretevent_collection_and_more.py │ │ ├── 0020_remove_organisation_owner_and_more.py │ │ ├── 0021_remove_secretevent_timestamp.py │ │ ├── 0022_secretevent_timestamp.py │ │ ├── 0023_environment_identity_key.py │ │ ├── 0024_alter_environment_wrapped_salt_and_more.py │ │ ├── 0025_rename_environmentsecret_environmenttoken_usertoken.py │ │ ├── 0026_secretfolder_color_remove_secret_tags_secret_tags.py │ │ ├── 0027_remove_secretfolder_color_secrettag_color.py │ │ ├── 0028_remove_secretevent_tags_secretevent_tags.py │ │ ├── 0029_servicetoken.py │ │ ├── 0030_usertoken_expires_at.py │ │ ├── 0031_organisationmemberinvite.py │ │ ├── 0032_organisationmemberinvite_apps.py │ │ ├── 0033_organisationmemberinvite_role.py │ │ ├── 0034_organisationmember_apps.py │ │ ├── 0035_alter_organisationmember_deleted_at.py │ │ ├── 0036_alter_organisationmember_apps.py │ │ ├── 0037_organisationmember_wrapped_recovery.py │ │ ├── 0038_secretevent_ip_address_secretevent_user_agent.py │ │ ├── 0039_personalsecret.py │ │ ├── 0040_personalsecret_isactive_alter_personalsecret_value.py │ │ ├── 0041_rename_isactive_personalsecret_is_active.py │ │ ├── 0042_serverenvironmentkey.py │ │ ├── 0043_environmentsync.py │ │ ├── 0044_environmentsync_last_sync.py │ │ ├── 0045_alter_environmentsync_service_environmentsyncevent.py │ │ ├── 0046_alter_environmentsyncevent_meta.py │ │ ├── 0047_environmentsync_status.py │ │ ├── 0048_delete_existing_syncs.py │ │ ├── 0049_alter_environmentsync_service_and_more.py │ │ ├── 0050_alter_environmentsync_status_and_more.py │ │ ├── 0051_alter_environmentsync_service_and_more.py │ │ ├── 0052_alter_environmentsync_service_and_more.py │ │ ├── 0053_alter_environmentsync_service_and_more.py │ │ ├── 0054_alter_environmentsync_service.py │ │ ├── 0055_alter_providercredentials_provider.py │ │ ├── 0056_alter_environmentsync_service.py │ │ ├── 0057_remove_secretfolder_parent_secret_path_and_more.py │ │ ├── 0058_secretevent_path.py │ │ ├── 0059_secretfolder_folder.py │ │ ├── 0060_alter_secretfolder_unique_together.py │ │ ├── 0061_environmentsync_path.py │ │ ├── 0062_secretevent_service_token.py │ │ ├── 0063_lockbox.py │ │ ├── 0064_alter_providercredentials_provider.py │ │ ├── 0065_alter_providercredentials_provider.py │ │ ├── 0066_alter_environmentsync_service.py │ │ ├── 0067_alter_providercredentials_provider.py │ │ ├── 0068_alter_environmentsync_service.py │ │ ├── 0069_activatedphaselicense.py │ │ ├── 0070_alter_providercredentials_provider.py │ │ ├── 0071_alter_environmentsync_service.py │ │ ├── 0072_alter_environment_env_type.py │ │ ├── 0073_environment_index.py │ │ ├── 0074_correct_set_index_values.py │ │ ├── 0075_organisation_stripe_customer_id_and_more.py │ │ ├── 0076_role_organisationmember_organisation_role.py │ │ ├── 0077_auto_20240910_1255.py │ │ ├── 0078_remove_organisationmember_role.py │ │ ├── 0079_rename_organisation_role_organisationmember_role.py │ │ ├── 0080_remove_organisationmemberinvite_role.py │ │ ├── 0081_alter_role_id.py │ │ ├── 0082_role_color.py │ │ ├── 0083_app_sse_enabled.py │ │ ├── 0084_auto_20241008_0708.py │ │ ├── 0085_alter_providercredentials_provider.py │ │ ├── 0085_serviceaccount_environmentkey_paths_and_more.py │ │ ├── 0086_alter_environmentsync_service.py │ │ ├── 0086_remove_servicetoken_service_account_and_more.py │ │ ├── 0087_alter_serviceaccount_apps.py │ │ ├── 0088_secretevent_service_account.py │ │ ├── 0089_alter_serviceaccounthandler_service_account.py │ │ ├── 0090_alter_serviceaccount_organisation.py │ │ ├── 0091_add_managed_manager_service_roles.py │ │ ├── 0092_secretevent_service_account_token.py │ │ ├── 0093_merge_20241116_0744.py │ │ ├── 0094_alter_app_organisation_alter_environment_app.py │ │ ├── 0095_alter_environmentsync_service.py │ │ ├── 0096_organisationmemberinvite_role.py │ │ ├── 0097_alter_secretfolder_unique_together_and_more.py │ │ ├── 0098_cleanup_duplicate_folders.py │ │ ├── 0099_remove_secretfolder_unique_secret_folder_and_more.py │ │ ├── 0100_networkaccesspolicy_and_more.py │ │ ├── 0101_networkaccesspolicy_updated_at.py │ │ ├── 0102_networkaccesspolicy_created_by_and_more.py │ │ └── __init__.py │ ├── models.py │ ├── serializers.py │ ├── services.py │ ├── tasks.py │ ├── templates │ │ ├── api │ │ │ ├── invite.html │ │ │ ├── login.html │ │ │ ├── user_joined_org.html │ │ │ └── welcome.html │ │ └── base.html │ ├── tests.py │ ├── urls.py │ ├── utils │ │ ├── access │ │ │ ├── middleware.py │ │ │ ├── permissions.py │ │ │ └── roles.py │ │ ├── audit_logging.py │ │ ├── crypto.py │ │ ├── organisations.py │ │ ├── rest.py │ │ ├── secrets.py │ │ └── syncing │ │ │ ├── auth.py │ │ │ ├── aws │ │ │ ├── auth.py │ │ │ └── secrets_manager.py │ │ │ ├── cloudflare │ │ │ ├── auth.py │ │ │ ├── pages.py │ │ │ └── workers.py │ │ │ ├── github │ │ │ └── actions.py │ │ │ ├── gitlab │ │ │ └── main.py │ │ │ ├── nomad │ │ │ └── main.py │ │ │ ├── railway │ │ │ └── main.py │ │ │ ├── secrets.py │ │ │ ├── vault │ │ │ └── main.py │ │ │ └── vercel │ │ │ └── main.py │ └── views │ │ ├── auth.py │ │ ├── graphql.py │ │ ├── kms.py │ │ ├── lockbox.py │ │ └── secrets.py ├── backend │ ├── __init__.py │ ├── api │ │ ├── kv.py │ │ └── notifier.py │ ├── asgi.py │ ├── exceptions.py │ ├── graphene │ │ ├── middleware.py │ │ ├── mutations │ │ │ ├── access.py │ │ │ ├── app.py │ │ │ ├── environment.py │ │ │ ├── lockbox.py │ │ │ ├── organisation.py │ │ │ ├── service_accounts.py │ │ │ └── syncing.py │ │ ├── queries │ │ │ ├── access.py │ │ │ ├── license.py │ │ │ ├── quotas.py │ │ │ ├── service_accounts.py │ │ │ └── syncing.py │ │ └── types.py │ ├── quotas.py │ ├── schema.py │ ├── settings.py │ ├── urls.py │ ├── utils │ │ └── secrets.py │ └── wsgi.py ├── constraints.txt ├── dev-requirements.txt ├── ee │ ├── LICENSE │ ├── access │ │ └── utils │ │ │ └── network.py │ ├── authentication │ │ └── sso │ │ │ ├── oauth │ │ │ └── github_enterprise │ │ │ │ ├── provider.py │ │ │ │ └── views.py │ │ │ └── oidc │ │ │ ├── __init__.py │ │ │ ├── entraid │ │ │ └── views.py │ │ │ └── util │ │ │ ├── __init__.py │ │ │ ├── generic │ │ │ ├── __init__.py │ │ │ ├── provider.py │ │ │ └── views.py │ │ │ ├── google │ │ │ ├── __init__.py │ │ │ ├── urls.py │ │ │ └── views.py │ │ │ └── jumpcloud │ │ │ ├── urls.py │ │ │ └── views.py │ ├── billing │ │ ├── graphene │ │ │ ├── mutations │ │ │ │ └── stripe.py │ │ │ ├── queries │ │ │ │ └── stripe.py │ │ │ └── types.py │ │ ├── stripe.py │ │ └── webhooks │ │ │ └── stripe.py │ └── licensing │ │ ├── jobs.py │ │ ├── utils.py │ │ └── verifier.py ├── logs │ ├── __init__.py │ ├── admin.py │ ├── apps.py │ ├── dynamodb_models.py │ ├── migrations │ │ ├── 0001_initial.py │ │ ├── 0002_alter_kmslog_timestamp.py │ │ ├── 0003_alter_kmslog_id.py │ │ ├── 0004_rename_kmslog_kmsdblog.py │ │ ├── 0005_delete_kmslog.py │ │ ├── 0006_initial.py │ │ ├── 0007_alter_kmsdblog_asn_alter_kmsdblog_city_and_more.py │ │ ├── 0008_alter_kmsdblog_id.py │ │ └── __init__.py │ ├── models.py │ ├── queries.py │ ├── tests.py │ └── views.py ├── manage.py ├── requirements.txt ├── scripts │ └── start.sh ├── tests │ ├── __init__.py │ ├── conftest.py │ └── utils │ │ ├── syncing │ │ └── test_github_actions.py │ │ └── test_secret.py └── version.txt ├── dev-docker-compose.yml ├── docker-compose.yml ├── frontend ├── .eslintrc.json ├── .prettierrc.js ├── .vscode │ └── settings.json ├── @types │ └── gql.d.ts ├── Dockerfile ├── Dockerfile.dev ├── README.md ├── apollo │ ├── client.ts │ ├── fragment-masking.ts │ ├── gql.ts │ ├── graphql.ts │ ├── index.ts │ └── schema.graphql ├── app │ ├── [team] │ │ ├── access │ │ │ ├── authentication │ │ │ │ └── page.tsx │ │ │ ├── layout.tsx │ │ │ ├── members │ │ │ │ ├── [memberId] │ │ │ │ │ └── page.tsx │ │ │ │ ├── _components │ │ │ │ │ ├── AddAppToMemberButton.tsx │ │ │ │ │ ├── DeleteMemberConfirmDialog.tsx │ │ │ │ │ ├── DeleteUserTokenDialog.tsx │ │ │ │ │ ├── InviteDialog.tsx │ │ │ │ │ └── RoleSelector.tsx │ │ │ │ └── page.tsx │ │ │ ├── network │ │ │ │ ├── _components │ │ │ │ │ ├── CreateNetworkPolicyDialog.tsx │ │ │ │ │ ├── DeleteNetworkPolicyDialog.tsx │ │ │ │ │ ├── IPChip.tsx │ │ │ │ │ ├── ManageOrgGlobalPolicies.tsx │ │ │ │ │ └── UpdateNetworkPolicyDialog.tsx │ │ │ │ └── page.tsx │ │ │ ├── roles │ │ │ │ └── page.tsx │ │ │ └── service-accounts │ │ │ │ ├── [account] │ │ │ │ ├── _components │ │ │ │ │ ├── AddAppsToServiceAccountsButton.tsx │ │ │ │ │ ├── CreateServiceAccountTokenDialog.tsx │ │ │ │ │ └── DeleteServiceAccountTokenDialog.tsx │ │ │ │ └── page.tsx │ │ │ │ ├── _components │ │ │ │ ├── CreateServiceAccountDialog.tsx │ │ │ │ ├── DeleteServiceAccountDialog.tsx │ │ │ │ └── RoleSelector.tsx │ │ │ │ └── page.tsx │ │ ├── apps │ │ │ ├── [app] │ │ │ │ ├── _components │ │ │ │ │ ├── AppEnvironments.tsx │ │ │ │ │ ├── AppSecretRow.tsx │ │ │ │ │ ├── AppSecrets.tsx │ │ │ │ │ └── SecretInfoLegend.tsx │ │ │ │ ├── _hooks │ │ │ │ │ └── useAppSecrets.ts │ │ │ │ ├── access │ │ │ │ │ ├── layout.tsx │ │ │ │ │ ├── members │ │ │ │ │ │ └── page.tsx │ │ │ │ │ ├── service-accounts │ │ │ │ │ │ └── page.tsx │ │ │ │ │ └── tokens │ │ │ │ │ │ └── page.tsx │ │ │ │ ├── environments │ │ │ │ │ └── [environment] │ │ │ │ │ │ └── [[...path]] │ │ │ │ │ │ └── page.tsx │ │ │ │ ├── layout.tsx │ │ │ │ ├── logs │ │ │ │ │ └── page.tsx │ │ │ │ ├── page.tsx │ │ │ │ ├── settings │ │ │ │ │ └── page.tsx │ │ │ │ ├── syncing │ │ │ │ │ └── page.tsx │ │ │ │ └── types.ts │ │ │ ├── _components │ │ │ │ └── AppSortMenu.tsx │ │ │ └── page.tsx │ │ ├── integrations │ │ │ ├── credentials │ │ │ │ └── page.tsx │ │ │ ├── layout.tsx │ │ │ └── syncs │ │ │ │ └── page.tsx │ │ ├── layout.tsx │ │ ├── page.tsx │ │ ├── recovery │ │ │ └── page.tsx │ │ └── settings │ │ │ └── page.tsx │ ├── error.tsx │ ├── globals.css │ ├── invite │ │ └── [invite] │ │ │ ├── layout.tsx │ │ │ └── page.tsx │ ├── ip-restricted │ │ └── page.tsx │ ├── layout.tsx │ ├── loading.tsx │ ├── lockbox │ │ └── [boxId] │ │ │ ├── error.tsx │ │ │ ├── layout.tsx │ │ │ └── page.tsx │ ├── login │ │ └── page.tsx │ ├── page.tsx │ ├── providers.tsx │ ├── signup │ │ ├── head.tsx │ │ ├── layout.tsx │ │ └── page.tsx │ └── webauth │ │ └── [requestCode] │ │ └── page.tsx ├── codegen.ts ├── components │ ├── LoginButton.tsx │ ├── ReleaseInfo.tsx │ ├── UserMenu.tsx │ ├── VersionLabel.tsx │ ├── access │ │ ├── AccessTemplateSelector.tsx │ │ ├── CreateRoleDialog.tsx │ │ ├── DeleteRoleDialog.tsx │ │ ├── ManageRoleDialog.tsx │ │ ├── NetworkAccessPolicyForm.tsx │ │ ├── PermissionToggle.tsx │ │ └── UpdateAccountNetworkPolicies.tsx │ ├── apps │ │ ├── AppActivityChart.tsx │ │ ├── AppCard.tsx │ │ ├── AppCardSkeleton.tsx │ │ ├── AppsHomeCard.tsx │ │ ├── AppsView.tsx │ │ ├── DeleteAppDialog.tsx │ │ ├── EnableSSEDialog.tsx │ │ ├── EncryptionModeIndicator.tsx │ │ ├── NewAppDialog.tsx │ │ └── tokens │ │ │ ├── CreateServiceTokenDialog.tsx │ │ │ ├── CreateUserTokenDialog.tsx │ │ │ └── SecretTokens.tsx │ ├── auth │ │ ├── SignInButtons.tsx │ │ └── UnlockKeyringDialog.tsx │ ├── common │ │ ├── Accordion.tsx │ │ ├── Alert.tsx │ │ ├── Avatar.tsx │ │ ├── Button.tsx │ │ ├── Card.tsx │ │ ├── ColorPicker.tsx │ │ ├── CommandPalette.tsx │ │ ├── CopyButton.tsx │ │ ├── EmptyState.tsx │ │ ├── GenericDialog.tsx │ │ ├── GridPattern.tsx │ │ ├── HeroPattern.tsx │ │ ├── Input.tsx │ │ ├── LogoMark.tsx │ │ ├── LogoWordMark.tsx │ │ ├── ModeToggle.tsx │ │ ├── ProgressBar.tsx │ │ ├── Spinner.tsx │ │ ├── SplitButton.tsx │ │ ├── StatusIndicator.tsx │ │ ├── TextArea.tsx │ │ ├── Toast.tsx │ │ ├── ToggleSwitch.tsx │ │ └── logos │ │ │ ├── EntraIDLogo.tsx │ │ │ └── JumpCloudLogo.tsx │ ├── contextSnippets │ │ ├── ProgrammaticAccessMenu.tsx │ │ └── SecretsOneLiner.tsx │ ├── dashboard │ │ ├── CliCommand.tsx │ │ ├── CliInstallCommands.tsx │ │ └── GetStarted.tsx │ ├── environments │ │ ├── CreateEnvironmentDialog.tsx │ │ ├── ManageEnvironmentDialog.tsx │ │ ├── Tag.tsx │ │ ├── folders │ │ │ ├── DeleteDialog.tsx │ │ │ └── SecretFolderRow.tsx │ │ └── secrets │ │ │ ├── CommentDialog.tsx │ │ │ ├── DeleteDialog.tsx │ │ │ ├── DeployPreview.tsx │ │ │ ├── HistoryDialog.tsx │ │ │ ├── OverrideDialog.tsx │ │ │ ├── SecretPropertyDiffs.tsx │ │ │ ├── SecretRow.tsx │ │ │ ├── ShareSecretDialog.tsx │ │ │ ├── SortMenu.tsx │ │ │ ├── TagsDialog.tsx │ │ │ └── import │ │ │ ├── EnvFileDropZone.tsx │ │ │ ├── MultiEnvImportDialog.tsx │ │ │ └── SingleEnvImportDialog.tsx │ ├── forms │ │ └── UpgradeRequestForm.tsx │ ├── icons │ │ ├── BellIcon.jsx │ │ ├── BoltIcon.jsx │ │ ├── BookIcon.jsx │ │ ├── CalendarIcon.jsx │ │ ├── CartIcon.jsx │ │ ├── ChatBubbleIcon.jsx │ │ ├── CheckIcon.jsx │ │ ├── ChevronRightLeftIcon.jsx │ │ ├── ClipboardIcon.jsx │ │ ├── CogIcon.jsx │ │ ├── CopyIcon.jsx │ │ ├── DocumentIcon.jsx │ │ ├── EnvelopeIcon.jsx │ │ ├── FaceSmileIcon.jsx │ │ ├── FolderIcon.jsx │ │ ├── LinkIcon.jsx │ │ ├── ListIcon.jsx │ │ ├── MagnifyingGlassIcon.jsx │ │ ├── MapPinIcon.jsx │ │ ├── PackageIcon.jsx │ │ ├── PaperAirplaneIcon.jsx │ │ ├── PaperClipIcon.jsx │ │ ├── ShapesIcon.jsx │ │ ├── ShirtIcon.jsx │ │ ├── SquaresPlusIcon.jsx │ │ ├── TagIcon.jsx │ │ ├── UserIcon.jsx │ │ └── UsersIcon.jsx │ ├── layout │ │ ├── Navbar.tsx │ │ ├── OnboardingNavbar.tsx │ │ └── Sidebar.tsx │ ├── lockbox │ │ └── LockboxViewer.tsx │ ├── logs │ │ ├── KmsLogs.tsx │ │ └── SecretLogs.tsx │ ├── onboarding │ │ ├── AccountPassword.tsx │ │ ├── AccountRecovery.tsx │ │ ├── AccountSeedChecker.tsx │ │ ├── Stepper.tsx │ │ └── TeamName.tsx │ ├── settings │ │ ├── account │ │ │ ├── TrustedDeviceManager.tsx │ │ │ └── ViewRecoveryDialog.tsx │ │ └── organisation │ │ │ ├── PlanInfo.tsx │ │ │ ├── PlanLabel.tsx │ │ │ └── UpsellDialog.tsx │ ├── syncing │ │ ├── AWS │ │ │ ├── AWSRegionPicker.tsx │ │ │ └── CreateAWSSecretsSync.tsx │ │ ├── Cloudflare │ │ │ ├── CreateCloudflarePagesSync.tsx │ │ │ └── CreateCloudflareWorkersSync.tsx │ │ ├── CreateProviderCredentials.tsx │ │ ├── CreateProviderCredentialsDialog.tsx │ │ ├── CreateSyncDialog.tsx │ │ ├── DeleteProviderCredentialDialog.tsx │ │ ├── DeleteSyncDialog.tsx │ │ ├── EnvSyncStatus.tsx │ │ ├── GitHub │ │ │ ├── CreateGhActionsSync.tsx │ │ │ └── SetupGhAuth.tsx │ │ ├── GitLab │ │ │ └── CreateGitLabCISync.tsx │ │ ├── IntegrationsHomeCard.tsx │ │ ├── ManageSyncDialog.tsx │ │ ├── Nomad │ │ │ └── CreateNomadSync.tsx │ │ ├── ProviderCredentialCard.tsx │ │ ├── ProviderCredentialPicker.tsx │ │ ├── ProviderIcon.tsx │ │ ├── Railway │ │ │ └── CreateRailwaySync.tsx │ │ ├── ServiceInfo.tsx │ │ ├── SyncCard.tsx │ │ ├── SyncHistory.tsx │ │ ├── SyncManagement.tsx │ │ ├── SyncOptions.tsx │ │ ├── SyncStatusIndicator.tsx │ │ ├── UpdateProviderCredentials.tsx │ │ ├── Vault │ │ │ └── CreateVaultSync.tsx │ │ └── Vercel │ │ │ └── CreateVercelSync.tsx │ └── users │ │ ├── MembersHomeCard.tsx │ │ └── RoleLabel.tsx ├── constants │ └── index.ts ├── contexts │ ├── keyringContext.tsx │ ├── organisationContext.tsx │ ├── sidebarContext.tsx │ └── themeContext.tsx ├── ee │ ├── LICENSE │ ├── authentication │ │ └── sso │ │ │ └── oidc │ │ │ └── util │ │ │ ├── entraidProvider.ts │ │ │ ├── genericOIDCProvider.ts │ │ │ └── githubEnterpriseProvider.ts │ └── billing │ │ ├── AddPaymentMethodForm.tsx │ │ ├── License.tsx │ │ ├── ModifySubscriptionDialog.tsx │ │ ├── PostCheckoutScreen.tsx │ │ ├── StripeBillingInfo.tsx │ │ └── UpgradeDialog.tsx ├── graphql │ ├── mutations │ │ ├── access │ │ │ ├── createNetworkAccessPolicy.gql │ │ │ ├── createRole.gql │ │ │ ├── deleteNetworkAccessPolicy.gql │ │ │ ├── deleteRole.gql │ │ │ ├── updateAccountNetworkPolicies.gql │ │ │ ├── updateNetworkAccessPolicy.gql │ │ │ └── updateRole.gql │ │ ├── apps │ │ │ ├── addAppMember.gql │ │ │ ├── removeAppMember.gql │ │ │ ├── updateAppName.gql │ │ │ └── updateEnvScope.gql │ │ ├── billing │ │ │ ├── cancelProSubscription.gql │ │ │ ├── createStripeSetupIntent.gql │ │ │ ├── deletePaymentMethod.gql │ │ │ ├── initUpgradeCheckout.gql │ │ │ ├── modifySubscription.gql │ │ │ ├── resumeProSubscription.gql │ │ │ └── setDefaultPaymentMethod.gql │ │ ├── createApp.gql │ │ ├── createOrganisation.gql │ │ ├── deleteApp.gql │ │ ├── environments │ │ │ ├── bulkProcessSecrets.gql │ │ │ ├── createEnvironment.gql │ │ │ ├── createEnvironmentKey.gql │ │ │ ├── createEnvironmentToken.gql │ │ │ ├── createFolder.gql │ │ │ ├── createPersonalSecret.gql │ │ │ ├── createSecret.gql │ │ │ ├── createSecretTag.gql │ │ │ ├── createServiceToken.gql │ │ │ ├── deleteEnvironment.gql │ │ │ ├── deleteFolder.gql │ │ │ ├── deleteSecret.gql │ │ │ ├── deleteServiceToken.gql │ │ │ ├── editSecret.gql │ │ │ ├── initAppEnvironments.gql │ │ │ ├── readSecret.gql │ │ │ ├── removePersonalSecret.gql │ │ │ ├── renameEnvironment.gql │ │ │ ├── shareSecret.gql │ │ │ └── swapEnvironmentOrder.gql │ │ ├── organisation │ │ │ ├── acceptInvite.gql │ │ │ ├── deleteInvite.gql │ │ │ ├── deleteOrgMember.gql │ │ │ ├── inviteNewMember.gql │ │ │ ├── updateOrgMemberRole.gql │ │ │ └── updateUserWrappedSecrets.gql │ │ ├── rotateAppKeys.gql │ │ ├── service-accounts │ │ │ ├── createServiceAccount.gql │ │ │ ├── createServiceAccountToken.gql │ │ │ ├── deleteServiceAccount.gql │ │ │ ├── deleteServiceAccountToken.gql │ │ │ ├── updateHandlerKeys.gql │ │ │ └── updateServiceAccount.gql │ │ ├── syncing │ │ │ ├── aws │ │ │ │ └── CreateAwsSecretsSync.gql │ │ │ ├── cloudflare │ │ │ │ ├── CreateCfPagesSync.gql │ │ │ │ └── CreateCfWorkersSync.gql │ │ │ ├── deleteProviderCredentials.gql │ │ │ ├── deleteSync.gql │ │ │ ├── github │ │ │ │ └── CreateGhActionsSync.gql │ │ │ ├── gitlab │ │ │ │ └── createGitlabCISync.gql │ │ │ ├── initAppSync.gql │ │ │ ├── nomad │ │ │ │ └── createNomadSync.gql │ │ │ ├── railway │ │ │ │ └── createRailwayEnvironmentSync.gql │ │ │ ├── saveNewProviderCreds.gql │ │ │ ├── toggleSync.gql │ │ │ ├── triggerSync.gql │ │ │ ├── updateProviderCreds.gql │ │ │ ├── updateSyncAuthentication.gql │ │ │ ├── vault │ │ │ │ └── createVaultSync.gql │ │ │ └── vercel │ │ │ │ └── createVercelSync.gql │ │ └── users │ │ │ ├── createUserToken.gql │ │ │ └── deleteUserToken.gql │ └── queries │ │ ├── access │ │ ├── getClientIp.gql │ │ └── getNetworkPolicies.gql │ │ ├── apps │ │ ├── getAppAccounts.gql │ │ ├── getAppMembers.gql │ │ └── getAppServiceAccounts.gql │ │ ├── billing │ │ ├── getCheckoutDetails.gql │ │ └── getSubscriptionDetails.gql │ │ ├── getAppActivityChart.gql │ │ ├── getAppDetail.gql │ │ ├── getAppKmsLogs.gql │ │ ├── getApps.gql │ │ ├── getDashboard.gql │ │ ├── getOrganisations.gql │ │ ├── organisation │ │ ├── checkOrgNameAvailable.gql │ │ ├── getGlobalAccessUsers.gql │ │ ├── getInvites.gql │ │ ├── getLicense.gql │ │ ├── getOrganisationLicense.gql │ │ ├── getOrganisationMembers.gql │ │ ├── getOrganisationPlan.gql │ │ ├── getRoles.gql │ │ └── validateOrganisationInvite.gql │ │ ├── secrets │ │ ├── getAppEnvironments.gql │ │ ├── getAppSecrets.gql │ │ ├── getAppSecretsLogs.gql │ │ ├── getEnvironmentKey.gql │ │ ├── getEnvironmentTokens.gql │ │ ├── getFolders.gql │ │ ├── getSecretHistory.gql │ │ ├── getSecretKVs.gql │ │ ├── getSecretTags.gql │ │ ├── getSecrets.gql │ │ └── getServiceTokens.gql │ │ ├── service-accounts │ │ ├── getServiceAccountDetail.gql │ │ ├── getServiceAccountHandlers.gql │ │ └── getServiceAccounts.gql │ │ ├── syncing │ │ ├── GetOrgSyncs.gql │ │ ├── aws │ │ │ └── getSecrets.gql │ │ ├── cloudflare │ │ │ ├── getPages.gql │ │ │ └── getWorkers.gql │ │ ├── getAppSyncStatus.gql │ │ ├── getProviders.gql │ │ ├── getSavedCredentials.gql │ │ ├── getServerKey.gql │ │ ├── getServices.gql │ │ ├── github │ │ │ └── getRepos.gql │ │ ├── gitlab │ │ │ └── getResources.gql │ │ ├── nomad │ │ │ └── testAuth.gql │ │ ├── railway │ │ │ └── getProjects.gql │ │ ├── vault │ │ │ └── testAuth.gql │ │ └── vercel │ │ │ └── getProject.gql │ │ └── users │ │ └── getUserTokens.gql ├── hooks │ └── warnUnsavedChanges.ts ├── jest.config.js ├── middleware.ts ├── next.config.js ├── package-lock.json ├── package.json ├── pages │ └── api │ │ ├── auth │ │ └── [...nextauth].ts │ │ └── health.ts ├── postcss.config.js ├── public │ ├── android-chrome-192x192.png │ ├── android-chrome-512x512.png │ ├── apple-touch-icon.png │ ├── assets │ │ └── images │ │ │ ├── logo.png │ │ │ └── logo.svg │ ├── favicon-16x16.png │ ├── favicon-32x32.png │ ├── favicon.ico │ └── favicon.svg ├── scripts │ ├── replace-variable.sh │ └── start.sh ├── tailwind.config.js ├── tests │ └── utils │ │ ├── crypto │ │ ├── app.test.ts │ │ ├── environments.test.ts │ │ ├── general.test.ts │ │ ├── secretSharding.test.ts │ │ └── users.test.ts │ │ ├── dataUnits.test.ts │ │ ├── recoveryKit.test.ts │ │ └── secretConfig.test.ts ├── tsconfig.json ├── utils │ ├── access │ │ ├── ip.ts │ │ └── permissions.ts │ ├── app.ts │ ├── appConfig.ts │ ├── auth.ts │ ├── clipboard.ts │ ├── contextSnippets.ts │ ├── copy.ts │ ├── crypto │ │ ├── app.ts │ │ ├── constants.ts │ │ ├── environments.ts │ │ ├── general.ts │ │ ├── index.ts │ │ ├── keyshares.ts │ │ ├── lockbox.ts │ │ ├── service-accounts.ts │ │ ├── types.ts │ │ └── users.ts │ ├── dataUnits.ts │ ├── environment.ts │ ├── localStorage.ts │ ├── lockbox.ts │ ├── logoAnimation.css │ ├── logo_b64.ts │ ├── meta.ts │ ├── posthog.ts │ ├── recovery.ts │ ├── secretConfig.ts │ ├── secrets.ts │ ├── syncing │ │ ├── aws.ts │ │ └── general.ts │ ├── tags.ts │ ├── time.ts │ ├── tokens.ts │ └── typography.js └── yarn.lock ├── img ├── aws.svg ├── azure.svg ├── console-ui.mp4 ├── console-ui.webp ├── do.svg ├── docker.svg ├── gcp.svg ├── kubernetes.svg ├── members.png ├── phase-cli-import-run.webp ├── phase-console-secrets.webp ├── phase-console-wordmark-dark.png ├── phase-lattice-logo.svg ├── secrets-overview.png ├── wordmark-dark.svg └── wordmark-light.svg ├── nginx ├── Dockerfile └── default.conf └── staging-docker-compose.yml /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: "" 5 | labels: bug 6 | assignees: "" 7 | --- 8 | 9 | ### Describe the bug 10 | 11 | A clear and concise description of what the bug is. 12 | 13 | ### To Reproduce 14 | 15 | Steps to reproduce the behavior: 16 | 17 | 1. Go to '...' 18 | 2. Click on '....' 19 | 3. Scroll down to '....' 20 | 4. See error 21 | 22 | ### Expected behavior 23 | 24 | A clear and concise description of what you expected to happen. 25 | 26 | ### Screenshots 27 | 28 | If applicable, add screenshots to help explain your problem. 29 | 30 | ### Platform you are having the issue on: 31 | 32 | ### Additional context 33 | 34 | Add any other context about the problem here. 35 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest a feature for Phase 4 | labels: enhancement, feature 5 | 6 | --- 7 | 8 | ## Is your feature request related to a problem? 9 | 10 | *Please describe.* 11 | 12 | ## Describe the solution you'd like 13 | 14 | 15 | 16 | ## Describe alternatives you've considered 17 | 18 | 19 | 20 | ## Additional context 21 | 22 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Supported versions 4 | 5 | We always recommend using the latest version of the Phase Console to ensure you get all security updates. 6 | 7 | ## Reporting vulnerabilities 8 | 9 | Please do not file GitHub issues or post on our public forum for security vulnerabilities, as they are public! 10 | 11 | Phase takes security issues very seriously. If you have any concerns about Phase or believe you have uncovered a vulnerability, please get in touch via the e-mail address `security@phase.dev`. You can see our [security.txt](https://phase.dev/.well-known/security.txt) for GPG keys and to communicate securely with us. In the message, try to provide a description of the issue and ideally a way of reproducing it. The security team will get back to you as soon as possible. 12 | 13 | Note that this security address should be used only for undisclosed vulnerabilities. Please report any security problems to us before disclosing it publicly. 14 | -------------------------------------------------------------------------------- /backend/Dockerfile.dev: -------------------------------------------------------------------------------- 1 | FROM python:3.12.1-alpine3.19@sha256:28230397c48cf4e2619822beb834ae7e46ebcd255b8f7cef58eff932fd75d2ce 2 | 3 | ENV PYTHONUNBUFFERED 1 4 | 5 | WORKDIR /app 6 | 7 | # Install dependencies 8 | RUN apk update && apk add --no-cache \ 9 | postgresql-dev \ 10 | build-base \ 11 | gcc \ 12 | musl-dev \ 13 | jpeg-dev \ 14 | zlib-dev \ 15 | libffi-dev \ 16 | cairo-dev \ 17 | pango-dev \ 18 | gdk-pixbuf-dev \ 19 | mariadb-dev \ 20 | python3-dev 21 | 22 | COPY requirements.txt /app/requirements.txt 23 | 24 | # Install Python dependencies 25 | RUN pip install --upgrade pip && \ 26 | pip install -r requirements.txt 27 | 28 | COPY . /app 29 | 30 | EXPOSE 8000 31 | 32 | CMD sh -c "python manage.py migrate && python manage.py runserver 0.0.0.0:8000" 33 | -------------------------------------------------------------------------------- /backend/README.md: -------------------------------------------------------------------------------- 1 | # Phase Console - Backend 2 | 3 | Django + Graphene + DRF 4 | 5 | ### Generate graphql schema for frontend 6 | 7 | ```bash 8 | ./manage.py graphql_schema --schema backend.schema.schema --out ../frontend/apollo/schema.graphql 9 | ``` 10 | -------------------------------------------------------------------------------- /backend/api/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phasehq/console/29be2cac75707e7be8c8a7780aa3930367fa2e91/backend/api/__init__.py -------------------------------------------------------------------------------- /backend/api/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | from api.models import Organisation 3 | 4 | admin.site.register(Organisation) 5 | -------------------------------------------------------------------------------- /backend/api/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class ApiConfig(AppConfig): 5 | default_auto_field = 'django.db.models.BigAutoField' 6 | name = 'api' 7 | -------------------------------------------------------------------------------- /backend/api/config.py: -------------------------------------------------------------------------------- 1 | import logging 2 | from django.apps import AppConfig 3 | from django.conf import settings 4 | from django.db.models.signals import post_migrate 5 | 6 | 7 | class APIConfig(AppConfig): 8 | name = "api" 9 | 10 | def ready(self): 11 | # Connect the post_migrate signal to a custom handler 12 | post_migrate.connect(self.validate_licenses_post_migrate, sender=self) 13 | 14 | def validate_licenses_post_migrate(self, **kwargs): 15 | 16 | CLOUD_HOSTED = settings.APP_HOST == "cloud" 17 | 18 | if not CLOUD_HOSTED: 19 | from ee.licensing.utils import activate_license 20 | from ee.licensing.jobs import init_license_checker 21 | 22 | init_license_checker() 23 | 24 | if settings.PHASE_LICENSE: 25 | try: 26 | activate_license(settings.PHASE_LICENSE) 27 | except Exception as e: 28 | logging.exception("Failed to activate license: %s", e) 29 | -------------------------------------------------------------------------------- /backend/api/content_negotiation.py: -------------------------------------------------------------------------------- 1 | from rest_framework.negotiation import DefaultContentNegotiation 2 | 3 | from djangorestframework_camel_case.render import ( 4 | CamelCaseJSONRenderer, 5 | ) 6 | 7 | 8 | class CamelCaseContentNegotiation(DefaultContentNegotiation): 9 | def select_renderer(self, request, renderers, format_suffix=None): 10 | 11 | # If the request has the custom header, prefer CamelCaseJSONRenderer 12 | if request.headers.get("X-Use-Camel-Case") == "true": 13 | for renderer in renderers: 14 | if isinstance(renderer, CamelCaseJSONRenderer): 15 | return renderer, renderer.media_type 16 | 17 | # Otherwise, fall back to default DRF behavior 18 | return super().select_renderer(request, renderers, format_suffix) 19 | -------------------------------------------------------------------------------- /backend/api/migrations/0002_organisation.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.1.7 on 2023-03-08 07:54 2 | 3 | from django.db import migrations, models 4 | import uuid 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('api', '0001_initial'), 11 | ] 12 | 13 | operations = [ 14 | migrations.CreateModel( 15 | name='Organisation', 16 | fields=[ 17 | ('id', models.CharField(default=uuid.uuid4, editable=False, max_length=16, primary_key=True, serialize=False)), 18 | ], 19 | ), 20 | ] 21 | -------------------------------------------------------------------------------- /backend/api/migrations/0003_organisation_owner.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.1.7 on 2023-03-08 07:57 2 | 3 | from django.conf import settings 4 | from django.db import migrations, models 5 | import django.db.models.deletion 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('api', '0002_organisation'), 12 | ] 13 | 14 | operations = [ 15 | migrations.AddField( 16 | model_name='organisation', 17 | name='owner', 18 | field=models.ForeignKey(default=' ', on_delete=django.db.models.deletion.CASCADE, related_name='organisation', to=settings.AUTH_USER_MODEL), 19 | preserve_default=False, 20 | ), 21 | ] 22 | -------------------------------------------------------------------------------- /backend/api/migrations/0004_rename_created_on_customuser_created_at_and_more.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.1.7 on 2023-03-08 08:01 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('api', '0003_organisation_owner'), 10 | ] 11 | 12 | operations = [ 13 | migrations.RenameField( 14 | model_name='customuser', 15 | old_name='created_on', 16 | new_name='created_at', 17 | ), 18 | migrations.AddField( 19 | model_name='organisation', 20 | name='created_at', 21 | field=models.DateTimeField(auto_now_add=True, null=True), 22 | ), 23 | migrations.AddField( 24 | model_name='organisation', 25 | name='updated_at', 26 | field=models.DateTimeField(auto_now=True), 27 | ), 28 | ] 29 | -------------------------------------------------------------------------------- /backend/api/migrations/0005_organisation_identity_key_organisation_name.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.1.7 on 2023-03-08 08:12 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('api', '0004_rename_created_on_customuser_created_at_and_more'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name='organisation', 15 | name='identity_key', 16 | field=models.CharField(default=' ', max_length=256), 17 | preserve_default=False, 18 | ), 19 | migrations.AddField( 20 | model_name='organisation', 21 | name='name', 22 | field=models.CharField(default=' ', max_length=64), 23 | preserve_default=False, 24 | ), 25 | ] 26 | -------------------------------------------------------------------------------- /backend/api/migrations/0006_app.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.1.7 on 2023-03-16 11:26 2 | 3 | from django.db import migrations, models 4 | import django.db.models.deletion 5 | import uuid 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('api', '0005_organisation_identity_key_organisation_name'), 12 | ] 13 | 14 | operations = [ 15 | migrations.CreateModel( 16 | name='App', 17 | fields=[ 18 | ('id', models.CharField(default=uuid.uuid4, editable=False, max_length=16, primary_key=True, serialize=False)), 19 | ('name', models.CharField(max_length=64)), 20 | ('identity_key', models.CharField(max_length=256)), 21 | ('app_token', models.CharField(max_length=256)), 22 | ('wrapped_key_share', models.CharField(max_length=256)), 23 | ('created_at', models.DateTimeField(auto_now_add=True, null=True)), 24 | ('updated_at', models.DateTimeField(auto_now=True)), 25 | ('organisation', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='api.organisation')), 26 | ], 27 | ), 28 | ] 29 | -------------------------------------------------------------------------------- /backend/api/migrations/0007_alter_organisation_name.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.1.7 on 2023-03-20 15:18 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('api', '0006_app'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterField( 14 | model_name='organisation', 15 | name='name', 16 | field=models.CharField(max_length=64, unique=True), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /backend/api/migrations/0008_app_app_seed_alter_app_app_token_and_more.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.1.7 on 2023-03-24 08:52 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('api', '0007_alter_organisation_name'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name='app', 15 | name='app_seed', 16 | field=models.CharField(default='', max_length=208), 17 | preserve_default=False, 18 | ), 19 | migrations.AlterField( 20 | model_name='app', 21 | name='app_token', 22 | field=models.CharField(max_length=64), 23 | ), 24 | migrations.AlterField( 25 | model_name='app', 26 | name='wrapped_key_share', 27 | field=models.CharField(max_length=406), 28 | ), 29 | ] 30 | -------------------------------------------------------------------------------- /backend/api/migrations/0009_alter_app_id_alter_organisation_id.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.1.7 on 2023-03-25 06:51 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('api', '0008_app_app_seed_alter_app_app_token_and_more'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterField( 14 | model_name='app', 15 | name='id', 16 | field=models.CharField(editable=False, max_length=16, primary_key=True, serialize=False), 17 | ), 18 | migrations.AlterField( 19 | model_name='organisation', 20 | name='id', 21 | field=models.CharField(editable=False, max_length=16, primary_key=True, serialize=False), 22 | ), 23 | ] 24 | -------------------------------------------------------------------------------- /backend/api/migrations/0010_alter_customuser_username.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.1.7 on 2023-03-25 08:28 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('api', '0009_alter_app_id_alter_organisation_id'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterField( 14 | model_name='customuser', 15 | name='username', 16 | field=models.CharField(max_length=64, unique=True), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /backend/api/migrations/0011_alter_app_id_alter_customuser_userid_and_more.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.1.7 on 2023-03-25 08:40 2 | 3 | from django.db import migrations, models 4 | import uuid 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('api', '0010_alter_customuser_username'), 11 | ] 12 | 13 | operations = [ 14 | migrations.AlterField( 15 | model_name='app', 16 | name='id', 17 | field=models.CharField(editable=False, max_length=32, primary_key=True, serialize=False), 18 | ), 19 | migrations.AlterField( 20 | model_name='customuser', 21 | name='userId', 22 | field=models.CharField(default=uuid.uuid4, editable=False, max_length=32, primary_key=True, serialize=False), 23 | ), 24 | migrations.AlterField( 25 | model_name='organisation', 26 | name='id', 27 | field=models.CharField(editable=False, max_length=32, primary_key=True, serialize=False), 28 | ), 29 | ] 30 | -------------------------------------------------------------------------------- /backend/api/migrations/0012_alter_app_id_alter_customuser_userid_and_more.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.1.7 on 2023-03-25 08:45 2 | 3 | from django.db import migrations, models 4 | import uuid 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('api', '0011_alter_app_id_alter_customuser_userid_and_more'), 11 | ] 12 | 13 | operations = [ 14 | migrations.AlterField( 15 | model_name='app', 16 | name='id', 17 | field=models.TextField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False), 18 | ), 19 | migrations.AlterField( 20 | model_name='customuser', 21 | name='userId', 22 | field=models.TextField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False), 23 | ), 24 | migrations.AlterField( 25 | model_name='organisation', 26 | name='id', 27 | field=models.TextField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False), 28 | ), 29 | ] 30 | -------------------------------------------------------------------------------- /backend/api/migrations/0013_app_version.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2 on 2023-04-21 10:24 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('api', '0012_alter_app_id_alter_customuser_userid_and_more'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name='app', 15 | name='version', 16 | field=models.IntegerField(default=1), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /backend/api/migrations/0014_rename_version_app_app_version.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2 on 2023-04-21 10:58 2 | 3 | from django.db import migrations 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('api', '0013_app_version'), 10 | ] 11 | 12 | operations = [ 13 | migrations.RenameField( 14 | model_name='app', 15 | old_name='version', 16 | new_name='app_version', 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /backend/api/migrations/0015_app_deleted_at_app_is_deleted.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2 on 2023-04-23 14:26 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('api', '0014_rename_version_app_app_version'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name='app', 15 | name='deleted_at', 16 | field=models.DateTimeField(blank=True, null=True), 17 | ), 18 | migrations.AddField( 19 | model_name='app', 20 | name='is_deleted', 21 | field=models.BooleanField(default=False), 22 | ), 23 | ] 24 | -------------------------------------------------------------------------------- /backend/api/migrations/0016_organisation_plan.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2 on 2023-04-23 15:37 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('api', '0015_app_deleted_at_app_is_deleted'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name='organisation', 15 | name='plan', 16 | field=models.CharField(choices=[('FR', 'Free'), ('PR', 'Pro'), ('EN', 'Enterprise')], default='FR', max_length=2), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /backend/api/migrations/0019_remove_secret_user_remove_secretevent_collection_and_more.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.3 on 2023-08-02 07:03 2 | 3 | from django.db import migrations, models 4 | import django.db.models.deletion 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('api', '0018_rename_environment_token_environmentsecret_name_and_more'), 11 | ] 12 | 13 | operations = [ 14 | migrations.RemoveField( 15 | model_name='secret', 16 | name='user', 17 | ), 18 | migrations.RemoveField( 19 | model_name='secretevent', 20 | name='collection', 21 | ), 22 | migrations.AddField( 23 | model_name='secretevent', 24 | name='folder', 25 | field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='api.secretfolder'), 26 | ), 27 | ] 28 | -------------------------------------------------------------------------------- /backend/api/migrations/0021_remove_secretevent_timestamp.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.3 on 2023-08-04 09:42 2 | 3 | from django.db import migrations 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('api', '0020_remove_organisation_owner_and_more'), 10 | ] 11 | 12 | operations = [ 13 | migrations.RemoveField( 14 | model_name='secretevent', 15 | name='timestamp', 16 | ), 17 | ] 18 | -------------------------------------------------------------------------------- /backend/api/migrations/0022_secretevent_timestamp.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.3 on 2023-08-04 09:54 2 | 3 | from django.db import migrations, models 4 | import django.utils.timezone 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('api', '0021_remove_secretevent_timestamp'), 11 | ] 12 | 13 | operations = [ 14 | migrations.AddField( 15 | model_name='secretevent', 16 | name='timestamp', 17 | field=models.DateTimeField(auto_now_add=True, default=django.utils.timezone.now), 18 | preserve_default=False, 19 | ), 20 | ] 21 | -------------------------------------------------------------------------------- /backend/api/migrations/0023_environment_identity_key.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.3 on 2023-08-09 13:23 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('api', '0022_secretevent_timestamp'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name='environment', 15 | name='identity_key', 16 | field=models.CharField(default='', max_length=256), 17 | preserve_default=False, 18 | ), 19 | ] 20 | -------------------------------------------------------------------------------- /backend/api/migrations/0024_alter_environment_wrapped_salt_and_more.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.3 on 2023-08-12 09:16 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('api', '0023_environment_identity_key'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterField( 14 | model_name='environment', 15 | name='wrapped_salt', 16 | field=models.CharField(max_length=256), 17 | ), 18 | migrations.AlterField( 19 | model_name='environment', 20 | name='wrapped_seed', 21 | field=models.CharField(max_length=256), 22 | ), 23 | migrations.AlterField( 24 | model_name='environmentkey', 25 | name='wrapped_salt', 26 | field=models.CharField(max_length=256), 27 | ), 28 | migrations.AlterField( 29 | model_name='environmentkey', 30 | name='wrapped_seed', 31 | field=models.CharField(max_length=256), 32 | ), 33 | ] 34 | -------------------------------------------------------------------------------- /backend/api/migrations/0026_secretfolder_color_remove_secret_tags_secret_tags.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.3 on 2023-08-29 08:21 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('api', '0025_rename_environmentsecret_environmenttoken_usertoken'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name='secretfolder', 15 | name='color', 16 | field=models.CharField(default='', max_length=64), 17 | preserve_default=False, 18 | ), 19 | migrations.RemoveField( 20 | model_name='secret', 21 | name='tags', 22 | ), 23 | migrations.AddField( 24 | model_name='secret', 25 | name='tags', 26 | field=models.ManyToManyField(to='api.secrettag'), 27 | ), 28 | ] 29 | -------------------------------------------------------------------------------- /backend/api/migrations/0027_remove_secretfolder_color_secrettag_color.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.3 on 2023-08-29 08:35 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('api', '0026_secretfolder_color_remove_secret_tags_secret_tags'), 10 | ] 11 | 12 | operations = [ 13 | migrations.RemoveField( 14 | model_name='secretfolder', 15 | name='color', 16 | ), 17 | migrations.AddField( 18 | model_name='secrettag', 19 | name='color', 20 | field=models.CharField(default='', max_length=64), 21 | preserve_default=False, 22 | ), 23 | ] 24 | -------------------------------------------------------------------------------- /backend/api/migrations/0028_remove_secretevent_tags_secretevent_tags.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.3 on 2023-08-29 08:42 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('api', '0027_remove_secretfolder_color_secrettag_color'), 10 | ] 11 | 12 | operations = [ 13 | migrations.RemoveField( 14 | model_name='secretevent', 15 | name='tags', 16 | ), 17 | migrations.AddField( 18 | model_name='secretevent', 19 | name='tags', 20 | field=models.ManyToManyField(to='api.secrettag'), 21 | ), 22 | ] 23 | -------------------------------------------------------------------------------- /backend/api/migrations/0030_usertoken_expires_at.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.3 on 2023-09-09 09:08 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('api', '0029_servicetoken'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name='usertoken', 15 | name='expires_at', 16 | field=models.DateTimeField(null=True), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /backend/api/migrations/0032_organisationmemberinvite_apps.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.3 on 2023-09-12 13:04 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('api', '0031_organisationmemberinvite'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name='organisationmemberinvite', 15 | name='apps', 16 | field=models.ManyToManyField(to='api.app'), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /backend/api/migrations/0033_organisationmemberinvite_role.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.3 on 2023-09-14 08:29 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('api', '0032_organisationmemberinvite_apps'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name='organisationmemberinvite', 15 | name='role', 16 | field=models.CharField(choices=[('owner', 'Owner'), ('admin', 'Admin'), ('dev', 'Developer')], default='dev', max_length=5), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /backend/api/migrations/0034_organisationmember_apps.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.3 on 2023-09-15 13:19 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | def set_org_member_apps(apps, schema_editor): 7 | OrgMemberModel = apps.get_model('api', 'OrganisationMember') 8 | AppModel = apps.get_model('api', 'App') 9 | 10 | for org_member in OrgMemberModel.objects.all(): 11 | org_apps = AppModel.objects.filter( 12 | organisation=org_member.organisation, is_deleted=False) 13 | org_member.apps.set(org_apps) 14 | 15 | 16 | class Migration(migrations.Migration): 17 | 18 | dependencies = [ 19 | ('api', '0033_organisationmemberinvite_role'), 20 | ] 21 | 22 | operations = [ 23 | migrations.AddField( 24 | model_name='organisationmember', 25 | name='apps', 26 | field=models.ManyToManyField(to='api.app'), 27 | ), 28 | migrations.RunPython(set_org_member_apps) 29 | ] 30 | -------------------------------------------------------------------------------- /backend/api/migrations/0035_alter_organisationmember_deleted_at.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.3 on 2023-09-16 08:50 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | def reset_deleted_field(apps, schema_editor): 7 | OrgMemberModel = apps.get_model('api', 'OrganisationMember') 8 | 9 | for org_member in OrgMemberModel.objects.all(): 10 | org_member.deleted_at = None 11 | org_member.save() 12 | 13 | 14 | class Migration(migrations.Migration): 15 | 16 | dependencies = [ 17 | ('api', '0034_organisationmember_apps'), 18 | ] 19 | 20 | operations = [ 21 | migrations.AlterField( 22 | model_name='organisationmember', 23 | name='deleted_at', 24 | field=models.DateTimeField(blank=True, null=True), 25 | ), 26 | migrations.RunPython(reset_deleted_field) 27 | ] 28 | -------------------------------------------------------------------------------- /backend/api/migrations/0036_alter_organisationmember_apps.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.3 on 2023-09-20 06:43 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('api', '0035_alter_organisationmember_deleted_at'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterField( 14 | model_name='organisationmember', 15 | name='apps', 16 | field=models.ManyToManyField(related_name='members', to='api.app'), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /backend/api/migrations/0037_organisationmember_wrapped_recovery.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.3 on 2023-09-27 08:01 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('api', '0036_alter_organisationmember_apps'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name='organisationmember', 15 | name='wrapped_recovery', 16 | field=models.TextField(blank=True), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /backend/api/migrations/0038_secretevent_ip_address_secretevent_user_agent.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.3 on 2023-10-05 15:31 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('api', '0037_organisationmember_wrapped_recovery'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name='secretevent', 15 | name='ip_address', 16 | field=models.GenericIPAddressField(blank=True, null=True), 17 | ), 18 | migrations.AddField( 19 | model_name='secretevent', 20 | name='user_agent', 21 | field=models.TextField(blank=True, null=True), 22 | ), 23 | ] 24 | -------------------------------------------------------------------------------- /backend/api/migrations/0039_personalsecret.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.3 on 2023-11-14 06:58 2 | 3 | from django.db import migrations, models 4 | import django.db.models.deletion 5 | import uuid 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('api', '0038_secretevent_ip_address_secretevent_user_agent'), 12 | ] 13 | 14 | operations = [ 15 | migrations.CreateModel( 16 | name='PersonalSecret', 17 | fields=[ 18 | ('id', models.TextField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)), 19 | ('value', models.TextField()), 20 | ('created_at', models.DateTimeField(auto_now_add=True, null=True)), 21 | ('updated_at', models.DateTimeField(auto_now=True)), 22 | ('deleted_at', models.DateTimeField(blank=True, null=True)), 23 | ('secret', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='api.secret')), 24 | ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='api.organisationmember')), 25 | ], 26 | ), 27 | ] 28 | -------------------------------------------------------------------------------- /backend/api/migrations/0040_personalsecret_isactive_alter_personalsecret_value.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.3 on 2023-11-16 05:46 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('api', '0039_personalsecret'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name='personalsecret', 15 | name='isActive', 16 | field=models.BooleanField(default=True), 17 | ), 18 | migrations.AlterField( 19 | model_name='personalsecret', 20 | name='value', 21 | field=models.TextField(blank=True, null=True), 22 | ), 23 | ] 24 | -------------------------------------------------------------------------------- /backend/api/migrations/0041_rename_isactive_personalsecret_is_active.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.3 on 2023-11-16 05:53 2 | 3 | from django.db import migrations 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('api', '0040_personalsecret_isactive_alter_personalsecret_value'), 10 | ] 11 | 12 | operations = [ 13 | migrations.RenameField( 14 | model_name='personalsecret', 15 | old_name='isActive', 16 | new_name='is_active', 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /backend/api/migrations/0042_serverenvironmentkey.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.7 on 2023-11-22 08:22 2 | 3 | from django.db import migrations, models 4 | import django.db.models.deletion 5 | import uuid 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('api', '0041_rename_isactive_personalsecret_is_active'), 12 | ] 13 | 14 | operations = [ 15 | migrations.CreateModel( 16 | name='ServerEnvironmentKey', 17 | fields=[ 18 | ('id', models.TextField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)), 19 | ('identity_key', models.CharField(max_length=256)), 20 | ('wrapped_seed', models.CharField(max_length=256)), 21 | ('wrapped_salt', models.CharField(max_length=256)), 22 | ('created_at', models.DateTimeField(auto_now_add=True, null=True)), 23 | ('updated_at', models.DateTimeField(auto_now=True)), 24 | ('deleted_at', models.DateTimeField(blank=True, null=True)), 25 | ('environment', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='api.environment')), 26 | ], 27 | ), 28 | ] 29 | -------------------------------------------------------------------------------- /backend/api/migrations/0044_environmentsync_last_sync.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.7 on 2023-11-29 07:03 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('api', '0043_environmentsync'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name='environmentsync', 15 | name='last_sync', 16 | field=models.DateTimeField(blank=True, null=True), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /backend/api/migrations/0046_alter_environmentsyncevent_meta.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.7 on 2023-11-30 09:14 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('api', '0045_alter_environmentsync_service_environmentsyncevent'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterField( 14 | model_name='environmentsyncevent', 15 | name='meta', 16 | field=models.JSONField(null=True), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /backend/api/migrations/0047_environmentsync_status.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.7 on 2023-12-01 14:19 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('api', '0046_alter_environmentsyncevent_meta'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name='environmentsync', 15 | name='status', 16 | field=models.CharField(choices=[('in_progress', 'In progress'), ('completed', 'Completed'), ('failed', 'Failed')], default='in_progress', max_length=16), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /backend/api/migrations/0048_delete_existing_syncs.py: -------------------------------------------------------------------------------- 1 | from django.db import migrations, models 2 | 3 | 4 | def delete_existing_syncs(apps, schema_editor): 5 | EnvironmentSync = apps.get_model("api", "EnvironmentSync") 6 | # This will delete all rows in EnvironmentSync 7 | EnvironmentSync.objects.all().delete() 8 | 9 | 10 | class Migration(migrations.Migration): 11 | dependencies = [ 12 | ("api", "0047_environmentsync_status"), 13 | ] 14 | 15 | operations = [ 16 | migrations.RunPython(delete_existing_syncs), 17 | ] 18 | -------------------------------------------------------------------------------- /backend/api/migrations/0050_alter_environmentsync_status_and_more.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.7 on 2023-12-27 09:36 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('api', '0049_alter_environmentsync_service_and_more'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterField( 14 | model_name='environmentsync', 15 | name='status', 16 | field=models.CharField(choices=[('in_progress', 'In progress'), ('completed', 'Completed'), ('cancelled', 'cancelled'), ('timed_out', 'Timed out'), ('failed', 'Failed')], default='in_progress', max_length=16), 17 | ), 18 | migrations.AlterField( 19 | model_name='environmentsyncevent', 20 | name='status', 21 | field=models.CharField(choices=[('in_progress', 'In progress'), ('completed', 'Completed'), ('cancelled', 'cancelled'), ('timed_out', 'Timed out'), ('failed', 'Failed')], default='in_progress', max_length=16), 22 | ), 23 | ] 24 | -------------------------------------------------------------------------------- /backend/api/migrations/0051_alter_environmentsync_service_and_more.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.7 on 2024-01-02 14:46 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('api', '0050_alter_environmentsync_status_and_more'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterField( 14 | model_name='environmentsync', 15 | name='service', 16 | field=models.CharField(choices=[('cloudflare_pages', 'Cloudflare Pages'), ('cloudflare_workers', 'Cloudflare Workers')], max_length=50), 17 | ), 18 | migrations.AlterField( 19 | model_name='providercredentials', 20 | name='provider', 21 | field=models.CharField(choices=[('cloudflare', 'Cloudflare')], max_length=50), 22 | ), 23 | ] 24 | -------------------------------------------------------------------------------- /backend/api/migrations/0052_alter_environmentsync_service_and_more.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.7 on 2024-01-05 06:24 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('api', '0051_alter_environmentsync_service_and_more'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterField( 14 | model_name='environmentsync', 15 | name='service', 16 | field=models.CharField(choices=[('cloudflare_pages', 'Cloudflare Pages'), ('cloudflare_workers', 'Cloudflare Workers'), ('aws_secrets_manager', 'AWS Secrets Manager')], max_length=50), 17 | ), 18 | migrations.AlterField( 19 | model_name='providercredentials', 20 | name='provider', 21 | field=models.CharField(choices=[('cloudflare', 'Cloudflare'), ('aws', 'AWS')], max_length=50), 22 | ), 23 | ] 24 | -------------------------------------------------------------------------------- /backend/api/migrations/0053_alter_environmentsync_service_and_more.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.7 on 2024-01-09 08:30 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('api', '0052_alter_environmentsync_service_and_more'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterField( 14 | model_name='environmentsync', 15 | name='service', 16 | field=models.CharField(choices=[('cloudflare_pages', 'Cloudflare Pages'), ('cloudflare_workers', 'Cloudflare Workers'), ('aws_secrets_manager', 'AWS Secrets Manager'), ('gh_actions', 'GitHub Actions')], max_length=50), 17 | ), 18 | migrations.AlterField( 19 | model_name='providercredentials', 20 | name='provider', 21 | field=models.CharField(choices=[('cloudflare', 'Cloudflare'), ('aws', 'AWS'), ('github', 'GitHub')], max_length=50), 22 | ), 23 | ] 24 | -------------------------------------------------------------------------------- /backend/api/migrations/0054_alter_environmentsync_service.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.7 on 2024-01-09 13:33 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('api', '0053_alter_environmentsync_service_and_more'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterField( 14 | model_name='environmentsync', 15 | name='service', 16 | field=models.CharField(choices=[('cloudflare_pages', 'Cloudflare Pages'), ('cloudflare_workers', 'Cloudflare Workers'), ('aws_secrets_manager', 'AWS Secrets Manager'), ('github_actions', 'GitHub Actions')], max_length=50), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /backend/api/migrations/0055_alter_providercredentials_provider.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.7 on 2024-01-11 09:28 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('api', '0054_alter_environmentsync_service'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterField( 14 | model_name='providercredentials', 15 | name='provider', 16 | field=models.CharField(choices=[('cloudflare', 'Cloudflare'), ('aws', 'AWS'), ('github', 'GitHub'), ('hashicorp_vault', 'Hashicorp Vault')], max_length=50), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /backend/api/migrations/0056_alter_environmentsync_service.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.7 on 2024-01-11 09:50 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('api', '0055_alter_providercredentials_provider'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterField( 14 | model_name='environmentsync', 15 | name='service', 16 | field=models.CharField(choices=[('cloudflare_pages', 'Cloudflare Pages'), ('cloudflare_workers', 'Cloudflare Workers'), ('aws_secrets_manager', 'AWS Secrets Manager'), ('github_actions', 'GitHub Actions'), ('hashicorp_vault', 'Hashicorp Vault')], max_length=50), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /backend/api/migrations/0057_remove_secretfolder_parent_secret_path_and_more.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.7 on 2024-02-10 07:58 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('api', '0056_alter_environmentsync_service'), 10 | ] 11 | 12 | operations = [ 13 | migrations.RemoveField( 14 | model_name='secretfolder', 15 | name='parent', 16 | ), 17 | migrations.AddField( 18 | model_name='secret', 19 | name='path', 20 | field=models.TextField(default='/'), 21 | ), 22 | migrations.AddField( 23 | model_name='secretfolder', 24 | name='path', 25 | field=models.TextField(default='/'), 26 | ), 27 | migrations.AlterField( 28 | model_name='environmentsync', 29 | name='service', 30 | field=models.CharField(choices=[('cloudflare_pages', 'Cloudflare Pages'), ('aws_secrets_manager', 'AWS Secrets Manager'), ('github_actions', 'GitHub Actions'), ('hashicorp_vault', 'Hashicorp Vault')], max_length=50), 31 | ), 32 | ] 33 | -------------------------------------------------------------------------------- /backend/api/migrations/0058_secretevent_path.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.7 on 2024-02-10 09:03 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('api', '0057_remove_secretfolder_parent_secret_path_and_more'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name='secretevent', 15 | name='path', 16 | field=models.TextField(default='/'), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /backend/api/migrations/0059_secretfolder_folder.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.7 on 2024-02-13 08:22 2 | 3 | from django.db import migrations, models 4 | import django.db.models.deletion 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('api', '0058_secretevent_path'), 11 | ] 12 | 13 | operations = [ 14 | migrations.AddField( 15 | model_name='secretfolder', 16 | name='folder', 17 | field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='api.secretfolder'), 18 | ), 19 | ] 20 | -------------------------------------------------------------------------------- /backend/api/migrations/0060_alter_secretfolder_unique_together.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.7 on 2024-02-13 14:14 2 | 3 | from django.db import migrations 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('api', '0059_secretfolder_folder'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterUniqueTogether( 14 | name='secretfolder', 15 | unique_together={('environment', 'folder', 'name', 'path')}, 16 | ), 17 | ] 18 | -------------------------------------------------------------------------------- /backend/api/migrations/0061_environmentsync_path.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.7 on 2024-02-14 04:26 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('api', '0060_alter_secretfolder_unique_together'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name='environmentsync', 15 | name='path', 16 | field=models.TextField(default='/'), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /backend/api/migrations/0062_secretevent_service_token.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.7 on 2024-02-16 10:23 2 | 3 | from django.db import migrations, models 4 | import django.db.models.deletion 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('api', '0061_environmentsync_path'), 11 | ] 12 | 13 | operations = [ 14 | migrations.AddField( 15 | model_name='secretevent', 16 | name='service_token', 17 | field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='api.servicetoken'), 18 | ), 19 | ] 20 | -------------------------------------------------------------------------------- /backend/api/migrations/0063_lockbox.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.7 on 2024-03-06 08:29 2 | 3 | from django.db import migrations, models 4 | import uuid 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('api', '0062_secretevent_service_token'), 11 | ] 12 | 13 | operations = [ 14 | migrations.CreateModel( 15 | name='Lockbox', 16 | fields=[ 17 | ('id', models.TextField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)), 18 | ('data', models.JSONField()), 19 | ('views', models.IntegerField(default=0)), 20 | ('created_at', models.DateTimeField(auto_now_add=True, null=True)), 21 | ('expires_at', models.DateTimeField(null=True)), 22 | ('allowed_views', models.IntegerField(null=True)), 23 | ], 24 | ), 25 | ] 26 | -------------------------------------------------------------------------------- /backend/api/migrations/0064_alter_providercredentials_provider.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.7 on 2024-05-13 09:16 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('api', '0063_lockbox'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterField( 14 | model_name='providercredentials', 15 | name='provider', 16 | field=models.CharField(choices=[('cloudflare', 'Cloudflare'), ('aws', 'AWS'), ('github', 'GitHub'), ('hashicorp_vault', 'Hashicorp Vault'), ('hashicorp_domad', 'Hashicorp Nomad')], max_length=50), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /backend/api/migrations/0065_alter_providercredentials_provider.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.7 on 2024-05-13 09:19 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('api', '0064_alter_providercredentials_provider'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterField( 14 | model_name='providercredentials', 15 | name='provider', 16 | field=models.CharField(choices=[('cloudflare', 'Cloudflare'), ('aws', 'AWS'), ('github', 'GitHub'), ('hashicorp_vault', 'Hashicorp Vault'), ('hashicorp_nomad', 'Hashicorp Nomad')], max_length=50), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /backend/api/migrations/0066_alter_environmentsync_service.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.7 on 2024-05-13 12:09 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('api', '0065_alter_providercredentials_provider'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterField( 14 | model_name='environmentsync', 15 | name='service', 16 | field=models.CharField(choices=[('cloudflare_pages', 'Cloudflare Pages'), ('aws_secrets_manager', 'AWS Secrets Manager'), ('github_actions', 'GitHub Actions'), ('hashicorp_vault', 'Hashicorp Vault'), ('hashicorp_nomad', 'Hashicorp Nomad')], max_length=50), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /backend/api/migrations/0067_alter_providercredentials_provider.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.7 on 2024-05-21 07:55 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('api', '0066_alter_environmentsync_service'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterField( 14 | model_name='providercredentials', 15 | name='provider', 16 | field=models.CharField(choices=[('cloudflare', 'Cloudflare'), ('aws', 'AWS'), ('github', 'GitHub'), ('gitlab', 'GitLab'), ('hashicorp_vault', 'Hashicorp Vault'), ('hashicorp_nomad', 'Hashicorp Nomad')], max_length=50), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /backend/api/migrations/0068_alter_environmentsync_service.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.7 on 2024-05-22 09:59 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('api', '0067_alter_providercredentials_provider'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterField( 14 | model_name='environmentsync', 15 | name='service', 16 | field=models.CharField(choices=[('cloudflare_pages', 'Cloudflare Pages'), ('aws_secrets_manager', 'AWS Secrets Manager'), ('github_actions', 'GitHub Actions'), ('gitlab_ci', 'GitLab CI'), ('hashicorp_vault', 'Hashicorp Vault'), ('hashicorp_nomad', 'Hashicorp Nomad')], max_length=50), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /backend/api/migrations/0070_alter_providercredentials_provider.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.7 on 2024-07-16 07:05 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('api', '0069_activatedphaselicense'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterField( 14 | model_name='providercredentials', 15 | name='provider', 16 | field=models.CharField(choices=[('cloudflare', 'Cloudflare'), ('aws', 'AWS'), ('github', 'GitHub'), ('gitlab', 'GitLab'), ('hashicorp_vault', 'Hashicorp Vault'), ('hashicorp_nomad', 'Hashicorp Nomad'), ('railway', 'Railway')], max_length=50), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /backend/api/migrations/0071_alter_environmentsync_service.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.7 on 2024-07-16 07:09 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('api', '0070_alter_providercredentials_provider'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterField( 14 | model_name='environmentsync', 15 | name='service', 16 | field=models.CharField(choices=[('cloudflare_pages', 'Cloudflare Pages'), ('aws_secrets_manager', 'AWS Secrets Manager'), ('github_actions', 'GitHub Actions'), ('gitlab_ci', 'GitLab CI'), ('hashicorp_vault', 'Hashicorp Vault'), ('hashicorp_nomad', 'Hashicorp Nomad'), ('railway', 'Railway')], max_length=50), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /backend/api/migrations/0072_alter_environment_env_type.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.7 on 2024-07-23 05:40 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('api', '0071_alter_environmentsync_service'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterField( 14 | model_name='environment', 15 | name='env_type', 16 | field=models.CharField(choices=[('dev', 'Development'), ('staging', 'Staging'), ('prod', 'Production'), ('custom', 'Custom')], default='dev', max_length=7), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /backend/api/migrations/0073_environment_index.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.7 on 2024-07-23 12:17 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | def set_index_values(apps, schema_editor): 7 | Environment = apps.get_model("api", "Environment") 8 | for env in Environment.objects.all(): 9 | if env.env_type == "dev": 10 | env.index = 0 11 | elif env.env_type == "staging": 12 | env.index = 1 13 | elif env.env_type == "prod": 14 | env.index = 2 15 | env.save() 16 | 17 | 18 | class Migration(migrations.Migration): 19 | 20 | dependencies = [ 21 | ("api", "0072_alter_environment_env_type"), 22 | ] 23 | 24 | operations = [ 25 | migrations.AddField( 26 | model_name="environment", 27 | name="index", 28 | field=models.IntegerField(default=0), 29 | ), 30 | migrations.RunPython(set_index_values), 31 | ] 32 | -------------------------------------------------------------------------------- /backend/api/migrations/0074_correct_set_index_values.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.7 on 2024-07-25 16:10 2 | from django.db import migrations 3 | 4 | 5 | def correct_set_index_values(apps, schema_editor): 6 | Environment = apps.get_model("api", "Environment") 7 | for env in Environment.objects.all(): 8 | if env.env_type.lower() == "dev": 9 | env.index = 0 10 | elif env.env_type.lower() == "staging": 11 | env.index = 1 12 | elif env.env_type.lower() == "prod": 13 | env.index = 2 14 | env.save() 15 | 16 | 17 | class Migration(migrations.Migration): 18 | 19 | dependencies = [ 20 | ("api", "0073_environment_index"), 21 | ] 22 | 23 | operations = [ 24 | migrations.RunPython(correct_set_index_values), 25 | ] 26 | -------------------------------------------------------------------------------- /backend/api/migrations/0075_organisation_stripe_customer_id_and_more.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.7 on 2024-07-30 10:08 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('api', '0074_correct_set_index_values'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name='organisation', 15 | name='stripe_customer_id', 16 | field=models.CharField(blank=True, max_length=255, null=True), 17 | ), 18 | migrations.AddField( 19 | model_name='organisation', 20 | name='stripe_subscription_id', 21 | field=models.CharField(blank=True, max_length=255, null=True), 22 | ), 23 | migrations.AlterField( 24 | model_name='activatedphaselicense', 25 | name='seats', 26 | field=models.IntegerField(null=True), 27 | ), 28 | migrations.AlterField( 29 | model_name='activatedphaselicense', 30 | name='tokens', 31 | field=models.IntegerField(null=True), 32 | ), 33 | ] 34 | -------------------------------------------------------------------------------- /backend/api/migrations/0078_remove_organisationmember_role.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.15 on 2024-09-10 12:59 2 | 3 | from django.db import migrations 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('api', '0077_auto_20240910_1255'), 10 | ] 11 | 12 | operations = [ 13 | migrations.RemoveField( 14 | model_name='organisationmember', 15 | name='role', 16 | ), 17 | ] 18 | -------------------------------------------------------------------------------- /backend/api/migrations/0079_rename_organisation_role_organisationmember_role.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.15 on 2024-09-10 13:16 2 | 3 | from django.db import migrations 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('api', '0078_remove_organisationmember_role'), 10 | ] 11 | 12 | operations = [ 13 | migrations.RenameField( 14 | model_name='organisationmember', 15 | old_name='organisation_role', 16 | new_name='role', 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /backend/api/migrations/0080_remove_organisationmemberinvite_role.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.15 on 2024-09-11 15:44 2 | 3 | from django.db import migrations 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('api', '0079_rename_organisation_role_organisationmember_role'), 10 | ] 11 | 12 | operations = [ 13 | migrations.RemoveField( 14 | model_name='organisationmemberinvite', 15 | name='role', 16 | ), 17 | ] 18 | -------------------------------------------------------------------------------- /backend/api/migrations/0081_alter_role_id.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.15 on 2024-09-12 08:22 2 | 3 | from django.db import migrations, models 4 | import uuid 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('api', '0080_remove_organisationmemberinvite_role'), 11 | ] 12 | 13 | operations = [ 14 | migrations.AlterField( 15 | model_name='role', 16 | name='id', 17 | field=models.TextField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False), 18 | ), 19 | ] 20 | -------------------------------------------------------------------------------- /backend/api/migrations/0082_role_color.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.15 on 2024-09-21 08:17 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('api', '0081_alter_role_id'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name='role', 15 | name='color', 16 | field=models.CharField(blank=True, default='', max_length=7), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /backend/api/migrations/0083_app_sse_enabled.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.15 on 2024-10-08 07:08 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('api', '0082_role_color'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name='app', 15 | name='sse_enabled', 16 | field=models.BooleanField(default=False), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /backend/api/migrations/0084_auto_20241008_0708.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.15 on 2024-10-08 07:08 2 | 3 | from django.db import migrations, models 4 | from django.conf import settings 5 | 6 | 7 | def set_sse_enabled(apps, schema_editor): 8 | App = apps.get_model("api", "App") 9 | Environment = apps.get_model("api", "Environment") 10 | ServerEnvironmentKey = apps.get_model("api", "ServerEnvironmentKey") 11 | 12 | apps = App.objects.all() 13 | for app in apps: 14 | app_envs = Environment.objects.filter(app=app).values_list("id") 15 | sse_enabled = ServerEnvironmentKey.objects.filter( 16 | environment_id__in=app_envs 17 | ).exists() 18 | app.sse_enabled = sse_enabled 19 | app.save() 20 | 21 | 22 | class Migration(migrations.Migration): 23 | 24 | dependencies = [ 25 | ("api", "0083_app_sse_enabled"), 26 | ] 27 | 28 | operations = [ 29 | migrations.RunPython(set_sse_enabled), 30 | ] 31 | -------------------------------------------------------------------------------- /backend/api/migrations/0085_alter_providercredentials_provider.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.15 on 2024-11-11 14:31 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('api', '0084_auto_20241008_0708'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterField( 14 | model_name='providercredentials', 15 | name='provider', 16 | field=models.CharField(choices=[('cloudflare', 'Cloudflare'), ('aws', 'AWS'), ('github', 'GitHub'), ('gitlab', 'GitLab'), ('hashicorp_vault', 'Hashicorp Vault'), ('hashicorp_nomad', 'Hashicorp Nomad'), ('railway', 'Railway'), ('vercel', 'Vercel')], max_length=50), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /backend/api/migrations/0086_alter_environmentsync_service.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.15 on 2024-11-11 14:36 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('api', '0085_alter_providercredentials_provider'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterField( 14 | model_name='environmentsync', 15 | name='service', 16 | field=models.CharField(choices=[('cloudflare_pages', 'Cloudflare Pages'), ('aws_secrets_manager', 'AWS Secrets Manager'), ('github_actions', 'GitHub Actions'), ('gitlab_ci', 'GitLab CI'), ('hashicorp_vault', 'Hashicorp Vault'), ('hashicorp_nomad', 'Hashicorp Nomad'), ('railway', 'Railway'), ('vercel', 'Vercel')], max_length=50), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /backend/api/migrations/0087_alter_serviceaccount_apps.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.15 on 2024-10-24 12:31 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('api', '0086_remove_servicetoken_service_account_and_more'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterField( 14 | model_name='serviceaccount', 15 | name='apps', 16 | field=models.ManyToManyField(related_name='service_accounts', to='api.app'), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /backend/api/migrations/0088_secretevent_service_account.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.15 on 2024-10-28 08:43 2 | 3 | from django.db import migrations, models 4 | import django.db.models.deletion 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('api', '0087_alter_serviceaccount_apps'), 11 | ] 12 | 13 | operations = [ 14 | migrations.AddField( 15 | model_name='secretevent', 16 | name='service_account', 17 | field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='api.serviceaccount'), 18 | ), 19 | ] 20 | -------------------------------------------------------------------------------- /backend/api/migrations/0089_alter_serviceaccounthandler_service_account.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.15 on 2024-10-30 07:10 2 | 3 | from django.db import migrations, models 4 | import django.db.models.deletion 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('api', '0088_secretevent_service_account'), 11 | ] 12 | 13 | operations = [ 14 | migrations.AlterField( 15 | model_name='serviceaccounthandler', 16 | name='service_account', 17 | field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='handlers', to='api.serviceaccount'), 18 | ), 19 | ] 20 | -------------------------------------------------------------------------------- /backend/api/migrations/0090_alter_serviceaccount_organisation.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.15 on 2024-10-30 07:11 2 | 3 | from django.db import migrations, models 4 | import django.db.models.deletion 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('api', '0089_alter_serviceaccounthandler_service_account'), 11 | ] 12 | 13 | operations = [ 14 | migrations.AlterField( 15 | model_name='serviceaccount', 16 | name='organisation', 17 | field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='service_accounts', to='api.organisation'), 18 | ), 19 | ] 20 | -------------------------------------------------------------------------------- /backend/api/migrations/0091_add_managed_manager_service_roles.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.15 on 2024-11-04 08:36 2 | 3 | from django.db import migrations 4 | from api.utils.access.roles import default_roles 5 | 6 | 7 | def add_default_roles(apps, schema_editor): 8 | Organisation = apps.get_model("api", "Organisation") 9 | Role = apps.get_model("api", "Role") 10 | OrganisationMember = apps.get_model("api", "OrganisationMember") 11 | 12 | # Create default roles for each organisation 13 | for organisation in Organisation.objects.all(): 14 | for role_name, _ in default_roles.items(): 15 | Role.objects.get_or_create( 16 | name=role_name, 17 | organisation=organisation, 18 | is_default=True, 19 | ) 20 | 21 | 22 | class Migration(migrations.Migration): 23 | 24 | dependencies = [ 25 | ("api", "0090_alter_serviceaccount_organisation"), 26 | ] 27 | 28 | operations = [ 29 | migrations.RunPython(add_default_roles), 30 | ] 31 | -------------------------------------------------------------------------------- /backend/api/migrations/0092_secretevent_service_account_token.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.15 on 2024-11-13 14:47 2 | 3 | from django.db import migrations, models 4 | import django.db.models.deletion 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('api', '0091_add_managed_manager_service_roles'), 11 | ] 12 | 13 | operations = [ 14 | migrations.AddField( 15 | model_name='secretevent', 16 | name='service_account_token', 17 | field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='api.serviceaccounttoken'), 18 | ), 19 | ] 20 | -------------------------------------------------------------------------------- /backend/api/migrations/0093_merge_20241116_0744.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.15 on 2024-11-16 07:44 2 | 3 | from django.db import migrations 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('api', '0086_alter_environmentsync_service'), 10 | ('api', '0092_secretevent_service_account_token'), 11 | ] 12 | 13 | operations = [ 14 | ] 15 | -------------------------------------------------------------------------------- /backend/api/migrations/0094_alter_app_organisation_alter_environment_app.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.15 on 2025-01-25 08:18 2 | 3 | from django.db import migrations, models 4 | import django.db.models.deletion 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('api', '0093_merge_20241116_0744'), 11 | ] 12 | 13 | operations = [ 14 | migrations.AlterField( 15 | model_name='app', 16 | name='organisation', 17 | field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='apps', to='api.organisation'), 18 | ), 19 | migrations.AlterField( 20 | model_name='environment', 21 | name='app', 22 | field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='environments', to='api.app'), 23 | ), 24 | ] 25 | -------------------------------------------------------------------------------- /backend/api/migrations/0095_alter_environmentsync_service.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.15 on 2025-02-15 10:03 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('api', '0094_alter_app_organisation_alter_environment_app'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterField( 14 | model_name='environmentsync', 15 | name='service', 16 | field=models.CharField(choices=[('cloudflare_pages', 'Cloudflare Pages'), ('cloudflare_workers', 'Cloudflare Workers'), ('aws_secrets_manager', 'AWS Secrets Manager'), ('github_actions', 'GitHub Actions'), ('gitlab_ci', 'GitLab CI'), ('hashicorp_vault', 'Hashicorp Vault'), ('hashicorp_nomad', 'Hashicorp Nomad'), ('railway', 'Railway'), ('vercel', 'Vercel')], max_length=50), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /backend/api/migrations/0096_organisationmemberinvite_role.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.16 on 2025-03-14 14:46 2 | 3 | from django.db import migrations, models 4 | import django.db.models.deletion 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('api', '0095_alter_environmentsync_service'), 11 | ] 12 | 13 | operations = [ 14 | migrations.AddField( 15 | model_name='organisationmemberinvite', 16 | name='role', 17 | field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='api.role'), 18 | ), 19 | ] 20 | -------------------------------------------------------------------------------- /backend/api/migrations/0097_alter_secretfolder_unique_together_and_more.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.16 on 2025-04-02 08:15 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ("api", "0096_organisationmemberinvite_role"), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterUniqueTogether( 14 | name="secretfolder", 15 | unique_together=set(), 16 | ), 17 | ] 18 | -------------------------------------------------------------------------------- /backend/api/migrations/0099_remove_secretfolder_unique_secret_folder_and_more.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.16 on 2025-04-02 08:48 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ("api", "0098_cleanup_duplicate_folders"), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddConstraint( 14 | model_name="secretfolder", 15 | constraint=models.UniqueConstraint( 16 | condition=models.Q(("folder__isnull", False)), 17 | fields=("environment", "folder", "name", "path"), 18 | name="unique_secret_folder", 19 | ), 20 | ), 21 | migrations.AddConstraint( 22 | model_name="secretfolder", 23 | constraint=models.UniqueConstraint( 24 | condition=models.Q(("folder__isnull", True)), 25 | fields=("environment", "name", "path"), 26 | name="unique_root_folder", 27 | ), 28 | ), 29 | ] 30 | -------------------------------------------------------------------------------- /backend/api/migrations/0101_networkaccesspolicy_updated_at.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.16 on 2025-04-27 09:31 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('api', '0100_networkaccesspolicy_and_more'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name='networkaccesspolicy', 15 | name='updated_at', 16 | field=models.DateTimeField(auto_now=True), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /backend/api/migrations/0102_networkaccesspolicy_created_by_and_more.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.16 on 2025-04-28 10:14 2 | 3 | from django.db import migrations, models 4 | import django.db.models.deletion 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('api', '0101_networkaccesspolicy_updated_at'), 11 | ] 12 | 13 | operations = [ 14 | migrations.AddField( 15 | model_name='networkaccesspolicy', 16 | name='created_by', 17 | field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='network_policies_created', to='api.organisationmember'), 18 | ), 19 | migrations.AddField( 20 | model_name='networkaccesspolicy', 21 | name='updated_by', 22 | field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='network_policies_updated', to='api.organisationmember'), 23 | ), 24 | ] 25 | -------------------------------------------------------------------------------- /backend/api/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phasehq/console/29be2cac75707e7be8c8a7780aa3930367fa2e91/backend/api/migrations/__init__.py -------------------------------------------------------------------------------- /backend/api/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /backend/api/urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import path, include 2 | from .views.auth import ( 3 | GitHubEnterpriseLoginView, 4 | GoogleLoginView, 5 | GitHubLoginView, 6 | GitLabLoginView, 7 | OIDCLoginView, 8 | JumpCloudLoginView, 9 | EntraIDLoginView, 10 | ) 11 | 12 | urlpatterns = [ 13 | path("google/", GoogleLoginView.as_view(), name="google"), 14 | path("github/", GitHubLoginView.as_view(), name="github"), 15 | path( 16 | "github-enterprise/", 17 | GitHubEnterpriseLoginView.as_view(), 18 | name="github-enterprise", 19 | ), 20 | path("gitlab/", GitLabLoginView.as_view(), name="gitlab"), 21 | path("google-oidc/", OIDCLoginView.as_view(), name="google-oidc"), 22 | path("jumpcloud-oidc/", JumpCloudLoginView.as_view(), name="jumpcloud-oidc"), 23 | path("entra-id-oidc/", EntraIDLoginView.as_view(), name="microsoft"), 24 | ] 25 | -------------------------------------------------------------------------------- /backend/api/utils/organisations.py: -------------------------------------------------------------------------------- 1 | from api.models import OrganisationMember, OrganisationMemberInvite, ServiceAccount 2 | from django.utils import timezone 3 | 4 | 5 | def get_organisation_seats(organisation): 6 | seats = ( 7 | OrganisationMember.objects.filter( 8 | organisation=organisation, deleted_at=None 9 | ).count() 10 | + OrganisationMemberInvite.objects.filter( 11 | organisation=organisation, valid=True, expires_at__gte=timezone.now() 12 | ).count() 13 | + ServiceAccount.objects.filter( 14 | organisation=organisation, deleted_at=None 15 | ).count() 16 | ) 17 | 18 | return seats 19 | -------------------------------------------------------------------------------- /backend/api/utils/syncing/aws/auth.py: -------------------------------------------------------------------------------- 1 | from api.utils.crypto import decrypt_asymmetric, get_server_keypair 2 | import boto3 3 | 4 | 5 | def get_client(AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, region): 6 | session = boto3.Session( 7 | aws_access_key_id=AWS_ACCESS_KEY_ID, 8 | aws_secret_access_key=AWS_SECRET_ACCESS_KEY, 9 | region_name=region, 10 | ) 11 | return session.client("secretsmanager") 12 | 13 | 14 | def get_aws_secrets_manager_credentials(environment_sync): 15 | pk, sk = get_server_keypair() 16 | 17 | access_key_id = decrypt_asymmetric( 18 | environment_sync.authentication.credentials["access_key_id"], sk.hex(), pk.hex() 19 | ) 20 | secret_access_key = decrypt_asymmetric( 21 | environment_sync.authentication.credentials["secret_access_key"], 22 | sk.hex(), 23 | pk.hex(), 24 | ) 25 | region = decrypt_asymmetric( 26 | environment_sync.authentication.credentials["region"], sk.hex(), pk.hex() 27 | ) 28 | 29 | return { 30 | "access_key_id": access_key_id, 31 | "secret_access_key": secret_access_key, 32 | "region": region, 33 | } 34 | -------------------------------------------------------------------------------- /backend/api/utils/syncing/cloudflare/auth.py: -------------------------------------------------------------------------------- 1 | CLOUDFLARE_API_BASE_URL = "https://api.cloudflare.com/client/v4" 2 | 3 | 4 | # A function to create headers for Cloudflare API requests. 5 | def get_cloudflare_headers(ACCESS_TOKEN): 6 | """Prepare headers for Cloudflare API requests.""" 7 | return { 8 | "Authorization": f"Bearer {ACCESS_TOKEN}", 9 | "Content-Type": "application/json", 10 | } 11 | -------------------------------------------------------------------------------- /backend/api/views/graphql.py: -------------------------------------------------------------------------------- 1 | from graphene_django.views import GraphQLView 2 | from django.contrib.auth.mixins import LoginRequiredMixin 3 | 4 | 5 | class PrivateGraphQLView(LoginRequiredMixin, GraphQLView): 6 | raise_exception = True 7 | pass 8 | -------------------------------------------------------------------------------- /backend/backend/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phasehq/console/29be2cac75707e7be8c8a7780aa3930367fa2e91/backend/backend/__init__.py -------------------------------------------------------------------------------- /backend/backend/api/notifier.py: -------------------------------------------------------------------------------- 1 | import requests 2 | from django.conf import settings 3 | 4 | 5 | def notify_slack(message): 6 | url = settings.SLACK_WEBHOOK_URI 7 | 8 | headers = { 9 | "Content-Type": "application/json", 10 | } 11 | 12 | payload = { 13 | "text": message 14 | } 15 | 16 | response = requests.request("POST", url, headers=headers, json=payload) 17 | 18 | if response.status_code == 200: 19 | return True 20 | print('Error pushing notification to Slack:', response) 21 | return False 22 | -------------------------------------------------------------------------------- /backend/backend/asgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | ASGI config for backend project. 3 | 4 | It exposes the ASGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/4.1/howto/deployment/asgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.asgi import get_asgi_application 13 | 14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'backend.settings') 15 | 16 | application = get_asgi_application() 17 | -------------------------------------------------------------------------------- /backend/backend/graphene/mutations/lockbox.py: -------------------------------------------------------------------------------- 1 | from api.models import Lockbox 2 | from backend.graphene.types import LockboxType 3 | import graphene 4 | from datetime import datetime 5 | 6 | 7 | class LockboxInput(graphene.InputObjectType): 8 | data = graphene.JSONString() 9 | allowed_views = graphene.Int() 10 | expiry = graphene.BigInt(required=False) 11 | 12 | 13 | class CreateLockboxMutation(graphene.Mutation): 14 | class Arguments: 15 | input = LockboxInput(LockboxInput) 16 | 17 | lockbox = graphene.Field(LockboxType) 18 | 19 | @classmethod 20 | def mutate(cls, root, info, input): 21 | if input.expiry is not None: 22 | expires_at = datetime.fromtimestamp(input.expiry / 1000) 23 | else: 24 | expires_at = None 25 | 26 | lockbox = Lockbox.objects.create( 27 | data=input.data, expires_at=expires_at, allowed_views=input.allowed_views 28 | ) 29 | 30 | return CreateLockboxMutation(lockbox=lockbox) 31 | -------------------------------------------------------------------------------- /backend/backend/graphene/queries/license.py: -------------------------------------------------------------------------------- 1 | from django.conf import settings 2 | from api.models import ActivatedPhaseLicense 3 | from graphql import GraphQLError 4 | from api.utils.access.permissions import user_is_org_member 5 | 6 | 7 | def resolve_license(root, info): 8 | return settings.PHASE_LICENSE 9 | 10 | 11 | def resolve_organisation_license(root, info, organisation_id): 12 | if not user_is_org_member(info.context.user.userId, organisation_id): 13 | raise GraphQLError("You don't have access to this organisation") 14 | 15 | return ( 16 | ActivatedPhaseLicense.objects.filter(organisation__id=organisation_id) 17 | .order_by("-activated_at") 18 | .first() 19 | ) 20 | -------------------------------------------------------------------------------- /backend/backend/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for backend project. 3 | 4 | It exposes the WSGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/4.1/howto/deployment/wsgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.wsgi import get_wsgi_application 13 | 14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'backend.settings') 15 | 16 | application = get_wsgi_application() 17 | -------------------------------------------------------------------------------- /backend/constraints.txt: -------------------------------------------------------------------------------- 1 | setuptools<72 2 | -------------------------------------------------------------------------------- /backend/dev-requirements.txt: -------------------------------------------------------------------------------- 1 | pytest==8.3.4 -------------------------------------------------------------------------------- /backend/ee/access/utils/network.py: -------------------------------------------------------------------------------- 1 | from ipaddress import ip_address, ip_network 2 | 3 | 4 | def ip_in_range(ip: str, cidr: str) -> bool: 5 | try: 6 | return ip_address(ip) in ip_network(cidr, strict=False) 7 | except ValueError: 8 | return False 9 | 10 | 11 | def is_ip_allowed(ip, policies): 12 | client_ip = ip_address(ip) 13 | 14 | for policy in policies: 15 | for allowed in policy.get_ip_list(): 16 | try: 17 | if "/" in allowed: 18 | if client_ip in ip_network(allowed, strict=False): 19 | return True 20 | elif client_ip == ip_address(allowed): 21 | return True 22 | except ValueError: 23 | continue # skip invalid IPs 24 | 25 | return False 26 | -------------------------------------------------------------------------------- /backend/ee/authentication/sso/oauth/github_enterprise/provider.py: -------------------------------------------------------------------------------- 1 | from allauth.socialaccount.providers.github.provider import GitHubProvider 2 | 3 | 4 | class GitHubEnterpriseProvider(GitHubProvider): 5 | id = "github-enterprise" 6 | name = "GitHub Enterprise" 7 | -------------------------------------------------------------------------------- /backend/ee/authentication/sso/oidc/__init__.py: -------------------------------------------------------------------------------- 1 | default_app_config = "ee.authentication.sso.oidc.apps.OIDCProviderConfig" 2 | -------------------------------------------------------------------------------- /backend/ee/authentication/sso/oidc/util/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phasehq/console/29be2cac75707e7be8c8a7780aa3930367fa2e91/backend/ee/authentication/sso/oidc/util/__init__.py -------------------------------------------------------------------------------- /backend/ee/authentication/sso/oidc/util/generic/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phasehq/console/29be2cac75707e7be8c8a7780aa3930367fa2e91/backend/ee/authentication/sso/oidc/util/generic/__init__.py -------------------------------------------------------------------------------- /backend/ee/authentication/sso/oidc/util/generic/provider.py: -------------------------------------------------------------------------------- 1 | from allauth.socialaccount.providers.base import ProviderAccount 2 | from allauth.socialaccount.providers.oauth2.provider import OAuth2Provider 3 | 4 | class OpenIDConnectAccount(ProviderAccount): 5 | def get_avatar_url(self): 6 | return self.account.extra_data.get('picture') 7 | 8 | def to_str(self): 9 | return self.account.extra_data.get('name', 10 | super(OpenIDConnectAccount, self).to_str()) 11 | 12 | class GenericOpenIDConnectProvider(OAuth2Provider): 13 | account_class = OpenIDConnectAccount 14 | 15 | def extract_uid(self, data): 16 | return str(data['sub']) 17 | 18 | def extract_common_fields(self, data): 19 | return { 20 | 'email': data.get('email'), 21 | 'username': data.get('email'), 22 | 'display_name': data.get('name'), 23 | } 24 | -------------------------------------------------------------------------------- /backend/ee/authentication/sso/oidc/util/google/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phasehq/console/29be2cac75707e7be8c8a7780aa3930367fa2e91/backend/ee/authentication/sso/oidc/util/google/__init__.py -------------------------------------------------------------------------------- /backend/ee/authentication/sso/oidc/util/google/urls.py: -------------------------------------------------------------------------------- 1 | from allauth.socialaccount.providers.oauth2.urls import default_urlpatterns 2 | 3 | from .views import GoogleOpenIDConnectProvider 4 | 5 | 6 | urlpatterns = default_urlpatterns(GoogleOpenIDConnectProvider) 7 | -------------------------------------------------------------------------------- /backend/ee/authentication/sso/oidc/util/jumpcloud/urls.py: -------------------------------------------------------------------------------- 1 | from allauth.socialaccount.providers.oauth2.urls import default_urlpatterns 2 | 3 | from .views import JumpCloudOpenIDConnectProvider 4 | 5 | 6 | urlpatterns = default_urlpatterns(JumpCloudOpenIDConnectProvider) 7 | -------------------------------------------------------------------------------- /backend/ee/billing/graphene/types.py: -------------------------------------------------------------------------------- 1 | from graphene import Enum 2 | 3 | 4 | class PlanTypeEnum(Enum): 5 | PRO = "pro" 6 | ENTERPRISE = "enterprise" 7 | 8 | 9 | class BillingPeriodEnum(Enum): 10 | MONTHLY = "monthly" 11 | YEARLY = "yearly" 12 | -------------------------------------------------------------------------------- /backend/ee/licensing/jobs.py: -------------------------------------------------------------------------------- 1 | from .utils import check_existing_licenses 2 | import django_rq 3 | from datetime import timedelta 4 | from django.utils import timezone 5 | 6 | 7 | def init_license_checker(): 8 | interval = 60 * 60 * 24 # 24 hours 9 | scheduler = django_rq.get_scheduler("scheduled-jobs") 10 | 11 | scheduler.schedule( 12 | scheduled_time=timezone.now() 13 | + timedelta(seconds=15), # Time for first execution 14 | func=check_existing_licenses, 15 | interval=interval, # Run every 60 seconds 16 | repeat=None, # None means repeat indefinitely 17 | result_ttl=interval 18 | + 60, # TTL needs to be greater than the interval to make sure the next run is queued, so we add 60 seconds to the interval 19 | ) 20 | -------------------------------------------------------------------------------- /backend/logs/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phasehq/console/29be2cac75707e7be8c8a7780aa3930367fa2e91/backend/logs/__init__.py -------------------------------------------------------------------------------- /backend/logs/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | #admin.site.register(KMSLog) 4 | -------------------------------------------------------------------------------- /backend/logs/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class LogsConfig(AppConfig): 5 | default_auto_field = 'django.db.models.BigAutoField' 6 | name = 'logs' 7 | -------------------------------------------------------------------------------- /backend/logs/migrations/0002_alter_kmslog_timestamp.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2 on 2023-04-08 10:43 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('logs', '0001_initial'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterField( 14 | model_name='kmslog', 15 | name='timestamp', 16 | field=models.BigIntegerField(), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /backend/logs/migrations/0003_alter_kmslog_id.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2 on 2023-04-08 10:47 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('logs', '0002_alter_kmslog_timestamp'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterField( 14 | model_name='kmslog', 15 | name='id', 16 | field=models.CharField(editable=False, max_length=36, primary_key=True, serialize=False), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /backend/logs/migrations/0004_rename_kmslog_kmsdblog.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2 on 2023-06-06 06:33 2 | 3 | from django.db import migrations 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('logs', '0003_alter_kmslog_id'), 10 | ] 11 | 12 | operations = [ 13 | # migrations.RenameModel( 14 | # old_name='KMSLog', 15 | # new_name='KMSDBLog', 16 | # ), 17 | ] 18 | -------------------------------------------------------------------------------- /backend/logs/migrations/0005_delete_kmslog.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2 on 2023-06-06 06:42 2 | 3 | from django.db import migrations 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('logs', '0004_rename_kmslog_kmsdblog'), 10 | ] 11 | 12 | operations = [ 13 | migrations.DeleteModel( 14 | name='KMSLog', 15 | ), 16 | ] 17 | -------------------------------------------------------------------------------- /backend/logs/migrations/0008_alter_kmsdblog_id.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2 on 2023-06-06 14:32 2 | 3 | from django.db import migrations, models 4 | import uuid 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('logs', '0007_alter_kmsdblog_asn_alter_kmsdblog_city_and_more'), 11 | ] 12 | 13 | operations = [ 14 | migrations.AlterField( 15 | model_name='kmsdblog', 16 | name='id', 17 | field=models.CharField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False), 18 | ), 19 | ] 20 | -------------------------------------------------------------------------------- /backend/logs/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phasehq/console/29be2cac75707e7be8c8a7780aa3930367fa2e91/backend/logs/migrations/__init__.py -------------------------------------------------------------------------------- /backend/logs/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | from uuid import uuid4 3 | 4 | class KMSDBLog(models.Model): 5 | """ 6 | DB model for Logs 7 | """ 8 | id = models.CharField(default=uuid4, primary_key=True, 9 | editable=False) 10 | timestamp = models.BigIntegerField(null=False, blank=False) 11 | app_id = models.TextField(null=False, blank=False) 12 | phase_node = models.TextField(null=False, blank=False) 13 | event_type = models.TextField(null=False, blank=False) 14 | ip_address = models.GenericIPAddressField(null=False, blank=False) 15 | ph_size = models.BigIntegerField(null=False, blank=False) 16 | asn = models.BigIntegerField(null=True) 17 | isp = models.TextField(null=True) 18 | edge_location = models.TextField(null=True) 19 | country = models.CharField(max_length=2, null=True) 20 | city = models.TextField(null=True) 21 | latitude = models.DecimalField(max_digits=9, decimal_places=5, null=True) 22 | longitude = models.DecimalField(max_digits=9, decimal_places=5, null=True) 23 | 24 | list_display = ('id', 'app_id', 'timestamp', 'event_type') 25 | 26 | def __str__(self): 27 | return self.id 28 | -------------------------------------------------------------------------------- /backend/logs/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /backend/logs/views.py: -------------------------------------------------------------------------------- 1 | from django.shortcuts import render 2 | 3 | # Create your views here. 4 | -------------------------------------------------------------------------------- /backend/manage.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """Django's command-line utility for administrative tasks.""" 3 | import os 4 | import sys 5 | 6 | 7 | def main(): 8 | """Run administrative tasks.""" 9 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "backend.settings") 10 | try: 11 | from django.core.management import execute_from_command_line 12 | except ImportError as exc: 13 | raise ImportError( 14 | "Couldn't import Django. Are you sure it's installed and " 15 | "available on your PYTHONPATH environment variable? Did you " 16 | "forget to activate a virtual environment?" 17 | ) from exc 18 | execute_from_command_line(sys.argv) 19 | 20 | 21 | if __name__ == "__main__": 22 | main() 23 | -------------------------------------------------------------------------------- /backend/scripts/start.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | echo "Checking migration configuration..." 5 | if [ "$EXTERNAL_MIGRATION" = "true" ]; then 6 | echo "EXTERNAL_MIGRATION flag is set to true. Skipping migrations as they will be handled externally." 7 | else 8 | echo "EXTERNAL_MIGRATION flag is not set. Running migrations locally..." 9 | python manage.py migrate 10 | fi 11 | 12 | echo "Starting gunicorn server..." 13 | exec gunicorn -b '[::]:8000' --workers 3 backend.wsgi:application 14 | -------------------------------------------------------------------------------- /backend/tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phasehq/console/29be2cac75707e7be8c8a7780aa3930367fa2e91/backend/tests/__init__.py -------------------------------------------------------------------------------- /backend/tests/conftest.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | from pathlib import Path 4 | 5 | # Add the project root directory to Python path 6 | project_root = Path(__file__).parent.parent 7 | sys.path.append(str(project_root)) 8 | -------------------------------------------------------------------------------- /backend/version.txt: -------------------------------------------------------------------------------- 1 | v2.44.0 2 | -------------------------------------------------------------------------------- /frontend/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "next/core-web-vitals" 3 | } 4 | -------------------------------------------------------------------------------- /frontend/.prettierrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | semi: false, 3 | trailingComma: 'es5', 4 | singleQuote: true, 5 | printWidth: 100, 6 | tabWidth: 2, 7 | useTabs: false, 8 | jsxBracketSameLine: false, 9 | bracketSpacing: true, 10 | } 11 | -------------------------------------------------------------------------------- /frontend/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "typescript.tsdk": "node_modules/typescript/lib", 3 | "typescript.enablePromptUseWorkspaceTsdk": true 4 | } -------------------------------------------------------------------------------- /frontend/@types/gql.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.gql' 2 | -------------------------------------------------------------------------------- /frontend/Dockerfile.dev: -------------------------------------------------------------------------------- 1 | # Base layer 2 | FROM node:18-alpine 3 | 4 | # Set the working directory 5 | WORKDIR /app 6 | 7 | # Copy over package files 8 | COPY package.json ./ 9 | COPY yarn.lock ./ 10 | 11 | # Install dependencies 12 | RUN yarn install --frozen-lockfile --no-cache && yarn cache clean 13 | 14 | # Copy all files 15 | COPY . . 16 | 17 | CMD ["yarn", "dev"] -------------------------------------------------------------------------------- /frontend/README.md: -------------------------------------------------------------------------------- 1 | # Phase Console - Frontend 2 | 3 | React + TS + Next.js 13 + Tailwind CSS 4 | 5 | ## Getting Started 6 | 7 | First, run the development server: 8 | 9 | ```bash 10 | npm run dev 11 | # or 12 | yarn dev 13 | # or 14 | pnpm dev 15 | ``` 16 | 17 | Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. -------------------------------------------------------------------------------- /frontend/apollo/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./fragment-masking"; 2 | export * from "./gql"; -------------------------------------------------------------------------------- /frontend/app/[team]/access/network/_components/IPChip.tsx: -------------------------------------------------------------------------------- 1 | import clsx from 'clsx' 2 | import { ReactNode } from 'react' 3 | 4 | export const IPChip = ({ ip, children }: { ip: string; children?: ReactNode }) => { 5 | const isCidr = ip.includes('/') 6 | return ( 7 |