From 02c92b7c1e65aa5724d35fe0fac298cfcacdd6f5 Mon Sep 17 00:00:00 2001 From: rohan-chaturvedi Date: Tue, 14 Nov 2023 14:32:25 +0530 Subject: [PATCH 01/15] feat: add personal secret model --- backend/api/migrations/0039_personalsecret.py | 27 +++++++++++++++++++ backend/api/models.py | 11 ++++++++ 2 files changed, 38 insertions(+) create mode 100644 backend/api/migrations/0039_personalsecret.py diff --git a/backend/api/migrations/0039_personalsecret.py b/backend/api/migrations/0039_personalsecret.py new file mode 100644 index 000000000..fb7914313 --- /dev/null +++ b/backend/api/migrations/0039_personalsecret.py @@ -0,0 +1,27 @@ +# Generated by Django 4.2.3 on 2023-11-14 06:58 + +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + ('api', '0038_secretevent_ip_address_secretevent_user_agent'), + ] + + operations = [ + migrations.CreateModel( + name='PersonalSecret', + fields=[ + ('id', models.TextField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)), + ('value', models.TextField()), + ('created_at', models.DateTimeField(auto_now_add=True, null=True)), + ('updated_at', models.DateTimeField(auto_now=True)), + ('deleted_at', models.DateTimeField(blank=True, null=True)), + ('secret', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='api.secret')), + ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='api.organisationmember')), + ], + ), + ] diff --git a/backend/api/models.py b/backend/api/models.py index f0d05a3cb..4c5d5cf0b 100644 --- a/backend/api/models.py +++ b/backend/api/models.py @@ -341,3 +341,14 @@ class SecretEvent(models.Model): timestamp = models.DateTimeField(auto_now_add=True) ip_address = models.GenericIPAddressField(null=True, blank=True) user_agent = models.TextField(null=True, blank=True) + + +class PersonalSecret(models.Model): + id = models.TextField(default=uuid4, primary_key=True, editable=False) + secret = models.ForeignKey(Secret, on_delete=models.CASCADE) + user = models.ForeignKey( + OrganisationMember, on_delete=models.CASCADE) + value = models.TextField() + created_at = models.DateTimeField(auto_now_add=True, blank=True, null=True) + updated_at = models.DateTimeField(auto_now=True) + deleted_at = models.DateTimeField(blank=True, null=True) From 27e64fd369d9d58c670122bf27c886e9224be68d Mon Sep 17 00:00:00 2001 From: rohan-chaturvedi Date: Tue, 14 Nov 2023 14:32:46 +0530 Subject: [PATCH 02/15] feat: add graphql types and mutations --- .../backend/graphene/mutations/environment.py | 64 ++++++++++++++++++- backend/backend/graphene/types.py | 26 +++++++- backend/backend/schema.py | 4 +- 3 files changed, 89 insertions(+), 5 deletions(-) diff --git a/backend/backend/graphene/mutations/environment.py b/backend/backend/graphene/mutations/environment.py index 47e7a9ec8..585d4fe44 100644 --- a/backend/backend/graphene/mutations/environment.py +++ b/backend/backend/graphene/mutations/environment.py @@ -3,8 +3,8 @@ from backend.graphene.utils.permissions import member_can_access_org, user_can_access_app, user_can_access_environment, user_is_org_member import graphene from graphql import GraphQLError -from api.models import App, Environment, EnvironmentKey, EnvironmentToken, Organisation, OrganisationMember, Secret, SecretEvent, SecretFolder, SecretTag, UserToken, ServiceToken -from backend.graphene.types import AppType, EnvironmentKeyType, EnvironmentTokenType, EnvironmentType, SecretFolderType, SecretTagType, SecretType, ServiceTokenType, UserTokenType +from api.models import App, Environment, EnvironmentKey, EnvironmentToken, Organisation, OrganisationMember, PersonalSecret, Secret, SecretEvent, SecretFolder, SecretTag, UserToken, ServiceToken +from backend.graphene.types import AppType, EnvironmentKeyType, EnvironmentTokenType, EnvironmentType, PersonalSecretType, SecretFolderType, SecretTagType, SecretType, ServiceTokenType, UserTokenType from datetime import datetime @@ -35,6 +35,11 @@ class SecretInput(graphene.InputObjectType): comment = graphene.String() +class PersonalSecretInput(graphene.InputObjectType): + secret_id = graphene.ID() + value = graphene.String() + + class CreateEnvironmentMutation(graphene.Mutation): class Arguments: environment_data = EnvironmentInput(required=True) @@ -488,3 +493,58 @@ def mutate(cls, root, info, id): value=secret.value, comment=secret.comment, event_type=SecretEvent.READ, ip_address=ip_address, user_agent=user_agent) read_event.tags.set(secret.tags.all()) return ReadSecretMutation(ok=True) + + +class CreatePersonalSecretMutation(graphene.Mutation): + + class Arguments: + override_data = PersonalSecretInput(PersonalSecretInput) + + override = graphene.Field(PersonalSecretType) + + @classmethod + def mutate(cls, root, info, override_data): + secret = Secret.objects.get(id=override_data.secret_id) + org = secret.environment.app.organisation + org_member = OrganisationMember.objects.get( + organisation=org, user=info.context.user) + + if not user_can_access_environment(info.context.user, secret.environment.id): + raise GraphQLError( + "You don't have access to this secret") + + if PersonalSecret.objects.filter(secret_id=override_data.secret_id, user=org_member).exists(): + override = PersonalSecret.objects.get( + secret_id=override_data.secret_id, user=org_member) + override.value = override_data.value + override.save() + + else: + override = PersonalSecret.objects.create( + secret_id=override_data.secret_id, user=org_member, value=override_data.value) + + return CreatePersonalSecretMutation(override=override) + + +class DeletePersonalSecretMutation(graphene.Mutation): + + class Arguments: + secret_id = graphene.ID() + + ok = graphene.Boolean() + + @classmethod + def mutate(cls, root, info, secret_id): + secret = Secret.objects.get(id=secret_id) + org = secret.environment.app.organisation + org_member = OrganisationMember.objects.get( + organisation=org, user=info.context.user) + + if not user_can_access_environment(info.context.user, secret.environment.id): + raise GraphQLError( + "You don't have access to this secret") + + PersonalSecret.objects.filter( + secret_id=secret_id, user=org_member).delete() + + return DeletePersonalSecretMutation(ok=True) diff --git a/backend/backend/graphene/types.py b/backend/backend/graphene/types.py index bd45d07a1..790f82d46 100644 --- a/backend/backend/graphene/types.py +++ b/backend/backend/graphene/types.py @@ -2,7 +2,7 @@ from enum import Enum from graphene import ObjectType, relay from graphene_django import DjangoObjectType -from api.models import CustomUser, Environment, EnvironmentKey, EnvironmentToken, Organisation, App, OrganisationMember, OrganisationMemberInvite, Secret, SecretEvent, SecretFolder, SecretTag, ServiceToken, UserToken +from api.models import CustomUser, Environment, EnvironmentKey, EnvironmentToken, Organisation, App, OrganisationMember, OrganisationMemberInvite, PersonalSecret, Secret, SecretEvent, SecretFolder, SecretTag, ServiceToken, UserToken from logs.dynamodb_models import KMSLog from allauth.socialaccount.models import SocialAccount @@ -165,19 +165,41 @@ class Meta: 'version', 'tags', 'comment', 'event_type', 'timestamp', 'user', 'ip_address', 'user_agent', 'environment') +class PersonalSecretType(DjangoObjectType): + class Meta: + model = PersonalSecret + fields = ('id', 'secret', 'user', 'value', 'created_at', 'updated_at') + + class SecretType(DjangoObjectType): history = graphene.List(SecretEventType) + override = graphene.Field(PersonalSecretType) class Meta: model = Secret fields = ('id', 'key', 'value', 'folder', 'version', 'tags', - 'comment', 'created_at', 'updated_at', 'history') + 'comment', 'created_at', 'updated_at', 'history', 'override') # interfaces = (relay.Node, ) def resolve_history(self, info): return SecretEvent.objects.filter(secret_id=self.id, event_type__in=[SecretEvent.CREATE, SecretEvent.UPDATE]).order_by('timestamp') + def resolve_override(self, info): + if info.context.user: + org = self.environment.app.organisation + org_member = OrganisationMember.objects.get( + organisation=org, user=info.context.user) + + try: + override = PersonalSecret.objects.get( + secret=self, user=org_member) + + if override is not None: + return override + except: + return None + class KMSLogType(ObjectType): class Meta: diff --git a/backend/backend/schema.py b/backend/backend/schema.py index e7f16695e..74f2bdba1 100644 --- a/backend/backend/schema.py +++ b/backend/backend/schema.py @@ -1,4 +1,4 @@ -from .graphene.mutations.environment import CreateEnvironmentKeyMutation, CreateEnvironmentMutation, CreateEnvironmentTokenMutation, CreateSecretFolderMutation, CreateSecretMutation, CreateSecretTagMutation, CreateServiceTokenMutation, CreateUserTokenMutation, DeleteSecretMutation, DeleteServiceTokenMutation, DeleteUserTokenMutation, EditSecretMutation, ReadSecretMutation, UpdateMemberEnvScopeMutation +from .graphene.mutations.environment import CreateEnvironmentKeyMutation, CreateEnvironmentMutation, CreateEnvironmentTokenMutation, CreatePersonalSecretMutation, CreateSecretFolderMutation, CreateSecretMutation, CreateSecretTagMutation, CreateServiceTokenMutation, CreateUserTokenMutation, DeletePersonalSecretMutation, DeleteSecretMutation, DeleteServiceTokenMutation, DeleteUserTokenMutation, EditSecretMutation, ReadSecretMutation, UpdateMemberEnvScopeMutation from .graphene.utils.permissions import user_can_access_app, user_can_access_environment, user_is_admin, user_is_org_member from .graphene.mutations.app import AddAppMemberMutation, CreateAppMutation, DeleteAppMutation, RemoveAppMemberMutation, RotateAppKeysMutation from .graphene.mutations.organisation import CreateOrganisationMemberMutation, CreateOrganisationMutation, DeleteInviteMutation, DeleteOrganisationMemberMutation, InviteOrganisationMemberMutation, UpdateOrganisationMemberRole, UpdateUserWrappedSecretsMutation @@ -409,6 +409,8 @@ class Mutation(graphene.ObjectType): edit_secret = EditSecretMutation.Field() delete_secret = DeleteSecretMutation.Field() read_secret = ReadSecretMutation.Field() + create_override = CreatePersonalSecretMutation.Field() + remove_override = DeletePersonalSecretMutation.Field() schema = graphene.Schema(query=Query, mutation=Mutation) From 9833a2f5c4e059b7b58542d8f34f735dfb35d4c5 Mon Sep 17 00:00:00 2001 From: rohan-chaturvedi Date: Tue, 14 Nov 2023 14:33:38 +0530 Subject: [PATCH 03/15] feat: personal secrets ui, queries, mutations --- frontend/apollo/gql.ts | 18 +- frontend/apollo/graphql.ts | 62 +++++- frontend/apollo/schema.graphql | 25 +++ .../[app]/environments/[environment]/page.tsx | 9 + .../components/environments/SecretRow.tsx | 208 ++++++++++++++++-- .../environments/createPersonalSecret.gql | 12 + .../environments/removePersonalSecret.gql | 5 + .../graphql/queries/secrets/getSecrets.gql | 3 + 8 files changed, 311 insertions(+), 31 deletions(-) create mode 100644 frontend/graphql/mutations/environments/createPersonalSecret.gql create mode 100644 frontend/graphql/mutations/environments/removePersonalSecret.gql diff --git a/frontend/apollo/gql.ts b/frontend/apollo/gql.ts index 497ecb2ef..dd768c7bc 100644 --- a/frontend/apollo/gql.ts +++ b/frontend/apollo/gql.ts @@ -22,6 +22,7 @@ const documents = { "mutation CreateEnv($input: EnvironmentInput!) {\n createEnvironment(environmentData: $input) {\n environment {\n id\n name\n createdAt\n identityKey\n }\n }\n}": types.CreateEnvDocument, "mutation CreateEnvKey($envId: ID!, $userId: ID, $wrappedSeed: String!, $wrappedSalt: String!, $identityKey: String!) {\n createEnvironmentKey(\n envId: $envId\n userId: $userId\n wrappedSeed: $wrappedSeed\n wrappedSalt: $wrappedSalt\n identityKey: $identityKey\n ) {\n environmentKey {\n id\n createdAt\n }\n }\n}": types.CreateEnvKeyDocument, "mutation CreateEnvToken($envId: ID!, $name: String!, $identityKey: String!, $token: String!, $wrappedKeyShare: String!) {\n createEnvironmentToken(\n envId: $envId\n name: $name\n identityKey: $identityKey\n token: $token\n wrappedKeyShare: $wrappedKeyShare\n ) {\n environmentToken {\n id\n createdAt\n }\n }\n}": types.CreateEnvTokenDocument, + "mutation CreateNewPersonalSecret($newPersonalSecret: PersonalSecretInput!) {\n createOverride(overrideData: $newPersonalSecret) {\n override {\n id\n secret {\n id\n }\n value\n createdAt\n }\n }\n}": types.CreateNewPersonalSecretDocument, "mutation CreateNewSecret($newSecret: SecretInput!) {\n createSecret(secretData: $newSecret) {\n secret {\n id\n key\n value\n createdAt\n }\n }\n}": types.CreateNewSecretDocument, "mutation CreateNewSecretTag($orgId: ID!, $name: String!, $color: String!) {\n createSecretTag(orgId: $orgId, name: $name, color: $color) {\n tag {\n id\n }\n }\n}": types.CreateNewSecretTagDocument, "mutation CreateNewServiceToken($appId: ID!, $environmentKeys: [EnvironmentKeyInput], $identityKey: String!, $token: String!, $wrappedKeyShare: String!, $name: String!, $expiry: BigInt) {\n createServiceToken(\n appId: $appId\n environmentKeys: $environmentKeys\n identityKey: $identityKey\n token: $token\n wrappedKeyShare: $wrappedKeyShare\n name: $name\n expiry: $expiry\n ) {\n serviceToken {\n id\n createdAt\n expiresAt\n }\n }\n}": types.CreateNewServiceTokenDocument, @@ -30,6 +31,7 @@ const documents = { "mutation UpdateSecret($id: ID!, $secretData: SecretInput!) {\n editSecret(id: $id, secretData: $secretData) {\n secret {\n id\n updatedAt\n }\n }\n}": types.UpdateSecretDocument, "mutation InitAppEnvironments($devEnv: EnvironmentInput!, $stagingEnv: EnvironmentInput!, $prodEnv: EnvironmentInput!, $devAdminKeys: [EnvironmentKeyInput], $stagAdminKeys: [EnvironmentKeyInput], $prodAdminKeys: [EnvironmentKeyInput]) {\n devEnvironment: createEnvironment(\n environmentData: $devEnv\n adminKeys: $devAdminKeys\n ) {\n environment {\n id\n name\n createdAt\n identityKey\n }\n }\n stagingEnvironment: createEnvironment(\n environmentData: $stagingEnv\n adminKeys: $stagAdminKeys\n ) {\n environment {\n id\n name\n createdAt\n identityKey\n }\n }\n prodEnvironment: createEnvironment(\n environmentData: $prodEnv\n adminKeys: $prodAdminKeys\n ) {\n environment {\n id\n name\n createdAt\n identityKey\n }\n }\n}": types.InitAppEnvironmentsDocument, "mutation LogSecretRead($id: ID!) {\n readSecret(id: $id) {\n ok\n }\n}": types.LogSecretReadDocument, + "mutation DeletePersonalSecret($secretId: ID!) {\n removeOverride(secretId: $secretId) {\n ok\n }\n}": types.DeletePersonalSecretDocument, "mutation AcceptOrganisationInvite($orgId: ID!, $identityKey: String!, $wrappedKeyring: String!, $wrappedRecovery: String!, $inviteId: ID!) {\n createOrganisationMember(\n orgId: $orgId\n identityKey: $identityKey\n wrappedKeyring: $wrappedKeyring\n wrappedRecovery: $wrappedRecovery\n inviteId: $inviteId\n ) {\n orgMember {\n id\n email\n createdAt\n role\n }\n }\n}": types.AcceptOrganisationInviteDocument, "mutation DeleteOrgInvite($inviteId: ID!) {\n deleteInvitation(inviteId: $inviteId) {\n ok\n }\n}": types.DeleteOrgInviteDocument, "mutation RemoveMember($memberId: ID!) {\n deleteOrganisationMember(memberId: $memberId) {\n ok\n }\n}": types.RemoveMemberDocument, @@ -55,8 +57,8 @@ const documents = { "query GetEnvironmentTokens($envId: ID!) {\n environmentTokens(environmentId: $envId) {\n id\n name\n wrappedKeyShare\n createdAt\n }\n}": types.GetEnvironmentTokensDocument, "query GetEnvSecretsKV($envId: ID!) {\n secrets(envId: $envId) {\n id\n key\n value\n }\n environmentKeys(environmentId: $envId) {\n id\n identityKey\n wrappedSeed\n wrappedSalt\n }\n}": types.GetEnvSecretsKvDocument, "query GetSecretTags($orgId: ID!) {\n secretTags(orgId: $orgId) {\n id\n name\n color\n }\n}": types.GetSecretTagsDocument, - "query GetSecrets($appId: ID!, $envId: ID!) {\n secrets(envId: $envId) {\n id\n key\n value\n tags {\n id\n name\n color\n }\n comment\n createdAt\n history {\n id\n key\n value\n tags {\n id\n name\n color\n }\n version\n comment\n timestamp\n ipAddress\n userAgent\n user {\n email\n username\n fullName\n avatarUrl\n }\n eventType\n }\n }\n appEnvironments(appId: $appId, environmentId: $envId) {\n id\n name\n envType\n identityKey\n }\n environmentKeys(appId: $appId, environmentId: $envId) {\n id\n identityKey\n wrappedSeed\n wrappedSalt\n }\n}": types.GetSecretsDocument, - "query GetServiceTokens($appId: ID!) {\n serviceTokens(appId: $appId) {\n id\n name\n createdAt\n createdBy {\n fullName\n avatarUrl\n self\n }\n expiresAt\n keys {\n id\n }\n }\n}": types.GetServiceTokensDocument, + "query GetSecrets($appId: ID!, $envId: ID!) {\n secrets(envId: $envId) {\n id\n key\n value\n tags {\n id\n name\n color\n }\n comment\n createdAt\n history {\n id\n key\n value\n tags {\n id\n name\n color\n }\n version\n comment\n timestamp\n ipAddress\n userAgent\n user {\n email\n username\n fullName\n avatarUrl\n }\n eventType\n }\n override {\n value\n }\n }\n appEnvironments(appId: $appId, environmentId: $envId) {\n id\n name\n envType\n identityKey\n }\n environmentKeys(appId: $appId, environmentId: $envId) {\n id\n identityKey\n wrappedSeed\n wrappedSalt\n }\n}": types.GetSecretsDocument, + "query GetServiceTokens($appId: ID!) {\n serviceTokens(appId: $appId) {\n id\n name\n createdAt\n createdBy {\n fullName\n avatarUrl\n self\n }\n expiresAt\n keys {\n id\n identityKey\n }\n }\n}": types.GetServiceTokensDocument, "query GetUserTokens($organisationId: ID!) {\n userTokens(organisationId: $organisationId) {\n id\n name\n wrappedKeyShare\n createdAt\n expiresAt\n }\n}": types.GetUserTokensDocument, }; @@ -110,6 +112,10 @@ export function graphql(source: "mutation CreateEnvKey($envId: ID!, $userId: ID, * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. */ export function graphql(source: "mutation CreateEnvToken($envId: ID!, $name: String!, $identityKey: String!, $token: String!, $wrappedKeyShare: String!) {\n createEnvironmentToken(\n envId: $envId\n name: $name\n identityKey: $identityKey\n token: $token\n wrappedKeyShare: $wrappedKeyShare\n ) {\n environmentToken {\n id\n createdAt\n }\n }\n}"): (typeof documents)["mutation CreateEnvToken($envId: ID!, $name: String!, $identityKey: String!, $token: String!, $wrappedKeyShare: String!) {\n createEnvironmentToken(\n envId: $envId\n name: $name\n identityKey: $identityKey\n token: $token\n wrappedKeyShare: $wrappedKeyShare\n ) {\n environmentToken {\n id\n createdAt\n }\n }\n}"]; +/** + * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. + */ +export function graphql(source: "mutation CreateNewPersonalSecret($newPersonalSecret: PersonalSecretInput!) {\n createOverride(overrideData: $newPersonalSecret) {\n override {\n id\n secret {\n id\n }\n value\n createdAt\n }\n }\n}"): (typeof documents)["mutation CreateNewPersonalSecret($newPersonalSecret: PersonalSecretInput!) {\n createOverride(overrideData: $newPersonalSecret) {\n override {\n id\n secret {\n id\n }\n value\n createdAt\n }\n }\n}"]; /** * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. */ @@ -142,6 +148,10 @@ export function graphql(source: "mutation InitAppEnvironments($devEnv: Environme * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. */ export function graphql(source: "mutation LogSecretRead($id: ID!) {\n readSecret(id: $id) {\n ok\n }\n}"): (typeof documents)["mutation LogSecretRead($id: ID!) {\n readSecret(id: $id) {\n ok\n }\n}"]; +/** + * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. + */ +export function graphql(source: "mutation DeletePersonalSecret($secretId: ID!) {\n removeOverride(secretId: $secretId) {\n ok\n }\n}"): (typeof documents)["mutation DeletePersonalSecret($secretId: ID!) {\n removeOverride(secretId: $secretId) {\n ok\n }\n}"]; /** * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. */ @@ -245,11 +255,11 @@ export function graphql(source: "query GetSecretTags($orgId: ID!) {\n secretTag /** * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. */ -export function graphql(source: "query GetSecrets($appId: ID!, $envId: ID!) {\n secrets(envId: $envId) {\n id\n key\n value\n tags {\n id\n name\n color\n }\n comment\n createdAt\n history {\n id\n key\n value\n tags {\n id\n name\n color\n }\n version\n comment\n timestamp\n ipAddress\n userAgent\n user {\n email\n username\n fullName\n avatarUrl\n }\n eventType\n }\n }\n appEnvironments(appId: $appId, environmentId: $envId) {\n id\n name\n envType\n identityKey\n }\n environmentKeys(appId: $appId, environmentId: $envId) {\n id\n identityKey\n wrappedSeed\n wrappedSalt\n }\n}"): (typeof documents)["query GetSecrets($appId: ID!, $envId: ID!) {\n secrets(envId: $envId) {\n id\n key\n value\n tags {\n id\n name\n color\n }\n comment\n createdAt\n history {\n id\n key\n value\n tags {\n id\n name\n color\n }\n version\n comment\n timestamp\n ipAddress\n userAgent\n user {\n email\n username\n fullName\n avatarUrl\n }\n eventType\n }\n }\n appEnvironments(appId: $appId, environmentId: $envId) {\n id\n name\n envType\n identityKey\n }\n environmentKeys(appId: $appId, environmentId: $envId) {\n id\n identityKey\n wrappedSeed\n wrappedSalt\n }\n}"]; +export function graphql(source: "query GetSecrets($appId: ID!, $envId: ID!) {\n secrets(envId: $envId) {\n id\n key\n value\n tags {\n id\n name\n color\n }\n comment\n createdAt\n history {\n id\n key\n value\n tags {\n id\n name\n color\n }\n version\n comment\n timestamp\n ipAddress\n userAgent\n user {\n email\n username\n fullName\n avatarUrl\n }\n eventType\n }\n override {\n value\n }\n }\n appEnvironments(appId: $appId, environmentId: $envId) {\n id\n name\n envType\n identityKey\n }\n environmentKeys(appId: $appId, environmentId: $envId) {\n id\n identityKey\n wrappedSeed\n wrappedSalt\n }\n}"): (typeof documents)["query GetSecrets($appId: ID!, $envId: ID!) {\n secrets(envId: $envId) {\n id\n key\n value\n tags {\n id\n name\n color\n }\n comment\n createdAt\n history {\n id\n key\n value\n tags {\n id\n name\n color\n }\n version\n comment\n timestamp\n ipAddress\n userAgent\n user {\n email\n username\n fullName\n avatarUrl\n }\n eventType\n }\n override {\n value\n }\n }\n appEnvironments(appId: $appId, environmentId: $envId) {\n id\n name\n envType\n identityKey\n }\n environmentKeys(appId: $appId, environmentId: $envId) {\n id\n identityKey\n wrappedSeed\n wrappedSalt\n }\n}"]; /** * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. */ -export function graphql(source: "query GetServiceTokens($appId: ID!) {\n serviceTokens(appId: $appId) {\n id\n name\n createdAt\n createdBy {\n fullName\n avatarUrl\n self\n }\n expiresAt\n keys {\n id\n }\n }\n}"): (typeof documents)["query GetServiceTokens($appId: ID!) {\n serviceTokens(appId: $appId) {\n id\n name\n createdAt\n createdBy {\n fullName\n avatarUrl\n self\n }\n expiresAt\n keys {\n id\n }\n }\n}"]; +export function graphql(source: "query GetServiceTokens($appId: ID!) {\n serviceTokens(appId: $appId) {\n id\n name\n createdAt\n createdBy {\n fullName\n avatarUrl\n self\n }\n expiresAt\n keys {\n id\n identityKey\n }\n }\n}"): (typeof documents)["query GetServiceTokens($appId: ID!) {\n serviceTokens(appId: $appId) {\n id\n name\n createdAt\n createdBy {\n fullName\n avatarUrl\n self\n }\n expiresAt\n keys {\n id\n identityKey\n }\n }\n}"]; /** * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. */ diff --git a/frontend/apollo/graphql.ts b/frontend/apollo/graphql.ts index a6b000c98..3b3ce38b2 100644 --- a/frontend/apollo/graphql.ts +++ b/frontend/apollo/graphql.ts @@ -132,6 +132,11 @@ export type CreateOrganisationMutation = { organisation?: Maybe; }; +export type CreatePersonalSecretMutation = { + __typename?: 'CreatePersonalSecretMutation'; + override?: Maybe; +}; + export type CreateSecretFolderMutation = { __typename?: 'CreateSecretFolderMutation'; folder?: Maybe; @@ -173,6 +178,11 @@ export type DeleteOrganisationMemberMutation = { ok?: Maybe; }; +export type DeletePersonalSecretMutation = { + __typename?: 'DeletePersonalSecretMutation'; + ok?: Maybe; +}; + export type DeleteSecretMutation = { __typename?: 'DeleteSecretMutation'; secret?: Maybe; @@ -282,6 +292,7 @@ export type Mutation = { createEnvironmentToken?: Maybe; createOrganisation?: Maybe; createOrganisationMember?: Maybe; + createOverride?: Maybe; createSecret?: Maybe; createSecretFolder?: Maybe; createSecretTag?: Maybe; @@ -297,6 +308,7 @@ export type Mutation = { inviteOrganisationMember?: Maybe; readSecret?: Maybe; removeAppMember?: Maybe; + removeOverride?: Maybe; rotateAppKeys?: Maybe; updateMemberEnvironmentScope?: Maybe; updateMemberWrappedSecrets?: Maybe; @@ -365,6 +377,11 @@ export type MutationCreateOrganisationMemberArgs = { }; +export type MutationCreateOverrideArgs = { + overrideData?: InputMaybe; +}; + + export type MutationCreateSecretArgs = { secretData?: InputMaybe; }; @@ -461,6 +478,11 @@ export type MutationRemoveAppMemberArgs = { }; +export type MutationRemoveOverrideArgs = { + secretId?: InputMaybe; +}; + + export type MutationRotateAppKeysArgs = { appToken: Scalars['String']; id: Scalars['ID']; @@ -535,6 +557,21 @@ export type OrganisationType = { role?: Maybe; }; +export type PersonalSecretInput = { + secretId?: InputMaybe; + value?: InputMaybe; +}; + +export type PersonalSecretType = { + __typename?: 'PersonalSecretType'; + createdAt?: Maybe; + id: Scalars['String']; + secret: SecretType; + updatedAt: Scalars['DateTime']; + user: OrganisationMemberType; + value: Scalars['String']; +}; + export type Query = { __typename?: 'Query'; appActivityChart?: Maybe>>; @@ -724,6 +761,7 @@ export type SecretType = { history?: Maybe>>; id: Scalars['String']; key: Scalars['String']; + override?: Maybe; tags: Array; updatedAt: Scalars['DateTime']; value: Scalars['String']; @@ -868,6 +906,13 @@ export type CreateEnvTokenMutationVariables = Exact<{ export type CreateEnvTokenMutation = { __typename?: 'Mutation', createEnvironmentToken?: { __typename?: 'CreateEnvironmentTokenMutation', environmentToken?: { __typename?: 'EnvironmentTokenType', id: string, createdAt?: any | null } | null } | null }; +export type CreateNewPersonalSecretMutationVariables = Exact<{ + newPersonalSecret: PersonalSecretInput; +}>; + + +export type CreateNewPersonalSecretMutation = { __typename?: 'Mutation', createOverride?: { __typename?: 'CreatePersonalSecretMutation', override?: { __typename?: 'PersonalSecretType', id: string, value: string, createdAt?: any | null, secret: { __typename?: 'SecretType', id: string } } | null } | null }; + export type CreateNewSecretMutationVariables = Exact<{ newSecret: SecretInput; }>; @@ -938,6 +983,13 @@ export type LogSecretReadMutationVariables = Exact<{ export type LogSecretReadMutation = { __typename?: 'Mutation', readSecret?: { __typename?: 'ReadSecretMutation', ok?: boolean | null } | null }; +export type DeletePersonalSecretMutationVariables = Exact<{ + secretId: Scalars['ID']; +}>; + + +export type DeletePersonalSecretMutation = { __typename?: 'Mutation', removeOverride?: { __typename?: 'DeletePersonalSecretMutation', ok?: boolean | null } | null }; + export type AcceptOrganisationInviteMutationVariables = Exact<{ orgId: Scalars['ID']; identityKey: Scalars['String']; @@ -1144,14 +1196,14 @@ export type GetSecretsQueryVariables = Exact<{ }>; -export type GetSecretsQuery = { __typename?: 'Query', secrets?: Array<{ __typename?: 'SecretType', id: string, key: string, value: string, comment: string, createdAt?: any | null, tags: Array<{ __typename?: 'SecretTagType', id: string, name: string, color: string }>, history?: Array<{ __typename?: 'SecretEventType', id: string, key: string, value: string, version: number, comment: string, timestamp: any, ipAddress?: string | null, userAgent?: string | null, eventType: ApiSecretEventEventTypeChoices, tags: Array<{ __typename?: 'SecretTagType', id: string, name: string, color: string }>, user?: { __typename?: 'OrganisationMemberType', email?: string | null, username?: string | null, fullName?: string | null, avatarUrl?: string | null } | null } | null> | null } | null> | null, appEnvironments?: Array<{ __typename?: 'EnvironmentType', id: string, name: string, envType: ApiEnvironmentEnvTypeChoices, identityKey: string } | null> | null, environmentKeys?: Array<{ __typename?: 'EnvironmentKeyType', id: string, identityKey: string, wrappedSeed: string, wrappedSalt: string } | null> | null }; +export type GetSecretsQuery = { __typename?: 'Query', secrets?: Array<{ __typename?: 'SecretType', id: string, key: string, value: string, comment: string, createdAt?: any | null, tags: Array<{ __typename?: 'SecretTagType', id: string, name: string, color: string }>, history?: Array<{ __typename?: 'SecretEventType', id: string, key: string, value: string, version: number, comment: string, timestamp: any, ipAddress?: string | null, userAgent?: string | null, eventType: ApiSecretEventEventTypeChoices, tags: Array<{ __typename?: 'SecretTagType', id: string, name: string, color: string }>, user?: { __typename?: 'OrganisationMemberType', email?: string | null, username?: string | null, fullName?: string | null, avatarUrl?: string | null } | null } | null> | null, override?: { __typename?: 'PersonalSecretType', value: string } | null } | null> | null, appEnvironments?: Array<{ __typename?: 'EnvironmentType', id: string, name: string, envType: ApiEnvironmentEnvTypeChoices, identityKey: string } | null> | null, environmentKeys?: Array<{ __typename?: 'EnvironmentKeyType', id: string, identityKey: string, wrappedSeed: string, wrappedSalt: string } | null> | null }; export type GetServiceTokensQueryVariables = Exact<{ appId: Scalars['ID']; }>; -export type GetServiceTokensQuery = { __typename?: 'Query', serviceTokens?: Array<{ __typename?: 'ServiceTokenType', id: string, name: string, createdAt?: any | null, expiresAt?: any | null, createdBy?: { __typename?: 'OrganisationMemberType', fullName?: string | null, avatarUrl?: string | null, self?: boolean | null } | null, keys: Array<{ __typename?: 'EnvironmentKeyType', id: string }> } | null> | null }; +export type GetServiceTokensQuery = { __typename?: 'Query', serviceTokens?: Array<{ __typename?: 'ServiceTokenType', id: string, name: string, createdAt?: any | null, expiresAt?: any | null, createdBy?: { __typename?: 'OrganisationMemberType', fullName?: string | null, avatarUrl?: string | null, self?: boolean | null } | null, keys: Array<{ __typename?: 'EnvironmentKeyType', id: string, identityKey: string }> } | null> | null }; export type GetUserTokensQueryVariables = Exact<{ organisationId: Scalars['ID']; @@ -1170,6 +1222,7 @@ export const DeleteApplicationDocument = {"kind":"Document","definitions":[{"kin export const CreateEnvDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"CreateEnv"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"EnvironmentInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"createEnvironment"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"environmentData"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"environment"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"identityKey"}}]}}]}}]}}]} as unknown as DocumentNode; export const CreateEnvKeyDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"CreateEnvKey"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"envId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"userId"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"wrappedSeed"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"wrappedSalt"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"identityKey"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"createEnvironmentKey"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"envId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"envId"}}},{"kind":"Argument","name":{"kind":"Name","value":"userId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"userId"}}},{"kind":"Argument","name":{"kind":"Name","value":"wrappedSeed"},"value":{"kind":"Variable","name":{"kind":"Name","value":"wrappedSeed"}}},{"kind":"Argument","name":{"kind":"Name","value":"wrappedSalt"},"value":{"kind":"Variable","name":{"kind":"Name","value":"wrappedSalt"}}},{"kind":"Argument","name":{"kind":"Name","value":"identityKey"},"value":{"kind":"Variable","name":{"kind":"Name","value":"identityKey"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"environmentKey"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}}]}}]}}]}}]} as unknown as DocumentNode; export const CreateEnvTokenDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"CreateEnvToken"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"envId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"name"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"identityKey"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"token"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"wrappedKeyShare"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"createEnvironmentToken"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"envId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"envId"}}},{"kind":"Argument","name":{"kind":"Name","value":"name"},"value":{"kind":"Variable","name":{"kind":"Name","value":"name"}}},{"kind":"Argument","name":{"kind":"Name","value":"identityKey"},"value":{"kind":"Variable","name":{"kind":"Name","value":"identityKey"}}},{"kind":"Argument","name":{"kind":"Name","value":"token"},"value":{"kind":"Variable","name":{"kind":"Name","value":"token"}}},{"kind":"Argument","name":{"kind":"Name","value":"wrappedKeyShare"},"value":{"kind":"Variable","name":{"kind":"Name","value":"wrappedKeyShare"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"environmentToken"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}}]}}]}}]}}]} as unknown as DocumentNode; +export const CreateNewPersonalSecretDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"CreateNewPersonalSecret"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"newPersonalSecret"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"PersonalSecretInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"createOverride"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"overrideData"},"value":{"kind":"Variable","name":{"kind":"Name","value":"newPersonalSecret"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"override"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"secret"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}}]}},{"kind":"Field","name":{"kind":"Name","value":"value"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}}]}}]}}]}}]} as unknown as DocumentNode; export const CreateNewSecretDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"CreateNewSecret"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"newSecret"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"SecretInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"createSecret"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"secretData"},"value":{"kind":"Variable","name":{"kind":"Name","value":"newSecret"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"secret"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"key"}},{"kind":"Field","name":{"kind":"Name","value":"value"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}}]}}]}}]}}]} as unknown as DocumentNode; export const CreateNewSecretTagDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"CreateNewSecretTag"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"orgId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"name"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"color"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"createSecretTag"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"orgId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"orgId"}}},{"kind":"Argument","name":{"kind":"Name","value":"name"},"value":{"kind":"Variable","name":{"kind":"Name","value":"name"}}},{"kind":"Argument","name":{"kind":"Name","value":"color"},"value":{"kind":"Variable","name":{"kind":"Name","value":"color"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"tag"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}}]}}]}}]}}]} as unknown as DocumentNode; export const CreateNewServiceTokenDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"CreateNewServiceToken"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"appId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"environmentKeys"}},"type":{"kind":"ListType","type":{"kind":"NamedType","name":{"kind":"Name","value":"EnvironmentKeyInput"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"identityKey"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"token"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"wrappedKeyShare"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"name"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"expiry"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"BigInt"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"createServiceToken"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"appId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"appId"}}},{"kind":"Argument","name":{"kind":"Name","value":"environmentKeys"},"value":{"kind":"Variable","name":{"kind":"Name","value":"environmentKeys"}}},{"kind":"Argument","name":{"kind":"Name","value":"identityKey"},"value":{"kind":"Variable","name":{"kind":"Name","value":"identityKey"}}},{"kind":"Argument","name":{"kind":"Name","value":"token"},"value":{"kind":"Variable","name":{"kind":"Name","value":"token"}}},{"kind":"Argument","name":{"kind":"Name","value":"wrappedKeyShare"},"value":{"kind":"Variable","name":{"kind":"Name","value":"wrappedKeyShare"}}},{"kind":"Argument","name":{"kind":"Name","value":"name"},"value":{"kind":"Variable","name":{"kind":"Name","value":"name"}}},{"kind":"Argument","name":{"kind":"Name","value":"expiry"},"value":{"kind":"Variable","name":{"kind":"Name","value":"expiry"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"serviceToken"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"expiresAt"}}]}}]}}]}}]} as unknown as DocumentNode; @@ -1178,6 +1231,7 @@ export const RevokeServiceTokenDocument = {"kind":"Document","definitions":[{"ki export const UpdateSecretDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"UpdateSecret"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"id"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"secretData"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"SecretInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"editSecret"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"id"}}},{"kind":"Argument","name":{"kind":"Name","value":"secretData"},"value":{"kind":"Variable","name":{"kind":"Name","value":"secretData"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"secret"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}}]}}]}}]}}]} as unknown as DocumentNode; export const InitAppEnvironmentsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"InitAppEnvironments"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"devEnv"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"EnvironmentInput"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"stagingEnv"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"EnvironmentInput"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"prodEnv"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"EnvironmentInput"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"devAdminKeys"}},"type":{"kind":"ListType","type":{"kind":"NamedType","name":{"kind":"Name","value":"EnvironmentKeyInput"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"stagAdminKeys"}},"type":{"kind":"ListType","type":{"kind":"NamedType","name":{"kind":"Name","value":"EnvironmentKeyInput"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"prodAdminKeys"}},"type":{"kind":"ListType","type":{"kind":"NamedType","name":{"kind":"Name","value":"EnvironmentKeyInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","alias":{"kind":"Name","value":"devEnvironment"},"name":{"kind":"Name","value":"createEnvironment"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"environmentData"},"value":{"kind":"Variable","name":{"kind":"Name","value":"devEnv"}}},{"kind":"Argument","name":{"kind":"Name","value":"adminKeys"},"value":{"kind":"Variable","name":{"kind":"Name","value":"devAdminKeys"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"environment"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"identityKey"}}]}}]}},{"kind":"Field","alias":{"kind":"Name","value":"stagingEnvironment"},"name":{"kind":"Name","value":"createEnvironment"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"environmentData"},"value":{"kind":"Variable","name":{"kind":"Name","value":"stagingEnv"}}},{"kind":"Argument","name":{"kind":"Name","value":"adminKeys"},"value":{"kind":"Variable","name":{"kind":"Name","value":"stagAdminKeys"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"environment"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"identityKey"}}]}}]}},{"kind":"Field","alias":{"kind":"Name","value":"prodEnvironment"},"name":{"kind":"Name","value":"createEnvironment"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"environmentData"},"value":{"kind":"Variable","name":{"kind":"Name","value":"prodEnv"}}},{"kind":"Argument","name":{"kind":"Name","value":"adminKeys"},"value":{"kind":"Variable","name":{"kind":"Name","value":"prodAdminKeys"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"environment"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"identityKey"}}]}}]}}]}}]} as unknown as DocumentNode; export const LogSecretReadDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"LogSecretRead"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"id"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"readSecret"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"id"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"ok"}}]}}]}}]} as unknown as DocumentNode; +export const DeletePersonalSecretDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"DeletePersonalSecret"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"secretId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"removeOverride"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"secretId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"secretId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"ok"}}]}}]}}]} as unknown as DocumentNode; export const AcceptOrganisationInviteDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"AcceptOrganisationInvite"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"orgId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"identityKey"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"wrappedKeyring"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"wrappedRecovery"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"inviteId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"createOrganisationMember"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"orgId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"orgId"}}},{"kind":"Argument","name":{"kind":"Name","value":"identityKey"},"value":{"kind":"Variable","name":{"kind":"Name","value":"identityKey"}}},{"kind":"Argument","name":{"kind":"Name","value":"wrappedKeyring"},"value":{"kind":"Variable","name":{"kind":"Name","value":"wrappedKeyring"}}},{"kind":"Argument","name":{"kind":"Name","value":"wrappedRecovery"},"value":{"kind":"Variable","name":{"kind":"Name","value":"wrappedRecovery"}}},{"kind":"Argument","name":{"kind":"Name","value":"inviteId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"inviteId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"orgMember"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"email"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"role"}}]}}]}}]}}]} as unknown as DocumentNode; export const DeleteOrgInviteDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"DeleteOrgInvite"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"inviteId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"deleteInvitation"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"inviteId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"inviteId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"ok"}}]}}]}}]} as unknown as DocumentNode; export const RemoveMemberDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"RemoveMember"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"memberId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"deleteOrganisationMember"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"memberId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"memberId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"ok"}}]}}]}}]} as unknown as DocumentNode; @@ -1203,6 +1257,6 @@ export const GetEnvironmentKeyDocument = {"kind":"Document","definitions":[{"kin export const GetEnvironmentTokensDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetEnvironmentTokens"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"envId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"environmentTokens"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"environmentId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"envId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"wrappedKeyShare"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}}]}}]}}]} as unknown as DocumentNode; export const GetEnvSecretsKvDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetEnvSecretsKV"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"envId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"secrets"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"envId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"envId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"key"}},{"kind":"Field","name":{"kind":"Name","value":"value"}}]}},{"kind":"Field","name":{"kind":"Name","value":"environmentKeys"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"environmentId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"envId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"identityKey"}},{"kind":"Field","name":{"kind":"Name","value":"wrappedSeed"}},{"kind":"Field","name":{"kind":"Name","value":"wrappedSalt"}}]}}]}}]} as unknown as DocumentNode; export const GetSecretTagsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetSecretTags"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"orgId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"secretTags"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"orgId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"orgId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"color"}}]}}]}}]} as unknown as DocumentNode; -export const GetSecretsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetSecrets"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"appId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"envId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"secrets"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"envId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"envId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"key"}},{"kind":"Field","name":{"kind":"Name","value":"value"}},{"kind":"Field","name":{"kind":"Name","value":"tags"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"color"}}]}},{"kind":"Field","name":{"kind":"Name","value":"comment"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"history"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"key"}},{"kind":"Field","name":{"kind":"Name","value":"value"}},{"kind":"Field","name":{"kind":"Name","value":"tags"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"color"}}]}},{"kind":"Field","name":{"kind":"Name","value":"version"}},{"kind":"Field","name":{"kind":"Name","value":"comment"}},{"kind":"Field","name":{"kind":"Name","value":"timestamp"}},{"kind":"Field","name":{"kind":"Name","value":"ipAddress"}},{"kind":"Field","name":{"kind":"Name","value":"userAgent"}},{"kind":"Field","name":{"kind":"Name","value":"user"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"email"}},{"kind":"Field","name":{"kind":"Name","value":"username"}},{"kind":"Field","name":{"kind":"Name","value":"fullName"}},{"kind":"Field","name":{"kind":"Name","value":"avatarUrl"}}]}},{"kind":"Field","name":{"kind":"Name","value":"eventType"}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"appEnvironments"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"appId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"appId"}}},{"kind":"Argument","name":{"kind":"Name","value":"environmentId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"envId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"envType"}},{"kind":"Field","name":{"kind":"Name","value":"identityKey"}}]}},{"kind":"Field","name":{"kind":"Name","value":"environmentKeys"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"appId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"appId"}}},{"kind":"Argument","name":{"kind":"Name","value":"environmentId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"envId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"identityKey"}},{"kind":"Field","name":{"kind":"Name","value":"wrappedSeed"}},{"kind":"Field","name":{"kind":"Name","value":"wrappedSalt"}}]}}]}}]} as unknown as DocumentNode; -export const GetServiceTokensDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetServiceTokens"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"appId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"serviceTokens"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"appId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"appId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"createdBy"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"fullName"}},{"kind":"Field","name":{"kind":"Name","value":"avatarUrl"}},{"kind":"Field","name":{"kind":"Name","value":"self"}}]}},{"kind":"Field","name":{"kind":"Name","value":"expiresAt"}},{"kind":"Field","name":{"kind":"Name","value":"keys"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}}]}}]}}]}}]} as unknown as DocumentNode; +export const GetSecretsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetSecrets"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"appId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"envId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"secrets"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"envId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"envId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"key"}},{"kind":"Field","name":{"kind":"Name","value":"value"}},{"kind":"Field","name":{"kind":"Name","value":"tags"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"color"}}]}},{"kind":"Field","name":{"kind":"Name","value":"comment"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"history"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"key"}},{"kind":"Field","name":{"kind":"Name","value":"value"}},{"kind":"Field","name":{"kind":"Name","value":"tags"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"color"}}]}},{"kind":"Field","name":{"kind":"Name","value":"version"}},{"kind":"Field","name":{"kind":"Name","value":"comment"}},{"kind":"Field","name":{"kind":"Name","value":"timestamp"}},{"kind":"Field","name":{"kind":"Name","value":"ipAddress"}},{"kind":"Field","name":{"kind":"Name","value":"userAgent"}},{"kind":"Field","name":{"kind":"Name","value":"user"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"email"}},{"kind":"Field","name":{"kind":"Name","value":"username"}},{"kind":"Field","name":{"kind":"Name","value":"fullName"}},{"kind":"Field","name":{"kind":"Name","value":"avatarUrl"}}]}},{"kind":"Field","name":{"kind":"Name","value":"eventType"}}]}},{"kind":"Field","name":{"kind":"Name","value":"override"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"value"}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"appEnvironments"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"appId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"appId"}}},{"kind":"Argument","name":{"kind":"Name","value":"environmentId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"envId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"envType"}},{"kind":"Field","name":{"kind":"Name","value":"identityKey"}}]}},{"kind":"Field","name":{"kind":"Name","value":"environmentKeys"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"appId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"appId"}}},{"kind":"Argument","name":{"kind":"Name","value":"environmentId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"envId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"identityKey"}},{"kind":"Field","name":{"kind":"Name","value":"wrappedSeed"}},{"kind":"Field","name":{"kind":"Name","value":"wrappedSalt"}}]}}]}}]} as unknown as DocumentNode; +export const GetServiceTokensDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetServiceTokens"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"appId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"serviceTokens"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"appId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"appId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"createdBy"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"fullName"}},{"kind":"Field","name":{"kind":"Name","value":"avatarUrl"}},{"kind":"Field","name":{"kind":"Name","value":"self"}}]}},{"kind":"Field","name":{"kind":"Name","value":"expiresAt"}},{"kind":"Field","name":{"kind":"Name","value":"keys"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"identityKey"}}]}}]}}]}}]} as unknown as DocumentNode; export const GetUserTokensDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetUserTokens"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"organisationId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"userTokens"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"organisationId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"organisationId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"wrappedKeyShare"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"expiresAt"}}]}}]}}]} as unknown as DocumentNode; \ No newline at end of file diff --git a/frontend/apollo/schema.graphql b/frontend/apollo/schema.graphql index 620916db6..d74d6f67a 100644 --- a/frontend/apollo/schema.graphql +++ b/frontend/apollo/schema.graphql @@ -175,6 +175,7 @@ type SecretType { createdAt: DateTime updatedAt: DateTime! history: [SecretEventType] + override: PersonalSecretType } type SecretFolderType { @@ -190,6 +191,15 @@ type SecretTagType { color: String! } +type PersonalSecretType { + id: String! + secret: SecretType! + user: OrganisationMemberType! + value: String! + createdAt: DateTime + updatedAt: DateTime! +} + type EnvironmentType { id: String! name: String! @@ -315,6 +325,8 @@ type Mutation { editSecret(id: ID!, secretData: SecretInput): EditSecretMutation deleteSecret(id: ID!): DeleteSecretMutation readSecret(id: ID!): ReadSecretMutation + createOverride(overrideData: PersonalSecretInput): CreatePersonalSecretMutation + removeOverride(secretId: ID): DeletePersonalSecretMutation } type CreateOrganisationMutation { @@ -447,4 +459,17 @@ type DeleteSecretMutation { type ReadSecretMutation { ok: Boolean +} + +type CreatePersonalSecretMutation { + override: PersonalSecretType +} + +input PersonalSecretInput { + secretId: ID + value: String +} + +type DeletePersonalSecretMutation { + ok: Boolean } \ No newline at end of file diff --git a/frontend/app/[team]/apps/[app]/environments/[environment]/page.tsx b/frontend/app/[team]/apps/[app]/environments/[environment]/page.tsx index e9947101b..3721f10c4 100644 --- a/frontend/app/[team]/apps/[app]/environments/[environment]/page.tsx +++ b/frontend/app/[team]/apps/[app]/environments/[environment]/page.tsx @@ -308,6 +308,14 @@ export default function Environment({ decryptedSecret.history = decryptedHistory } + if (secret.override?.value) { + decryptedSecret.override!.value = await decryptAsymmetric( + secret.override?.value, + envKeys.privateKey, + envKeys.publicKey + ) + } + return decryptedSecret }) ) @@ -595,6 +603,7 @@ export default function Environment({ { const { name, color } = props.tag @@ -267,7 +271,7 @@ const HistoryDialog = (props: { secret: SecretType }) => { <>
@@ -297,13 +301,18 @@ const HistoryDialog = (props: { secret: SecretType }) => { leaveTo="opacity-0 scale-95" > - -

- - {secret.key} - {' '} - history -

+ +
+

+ + {secret.key} + {' '} + history +

+
+ View the chronological history of changes made to this secret. +
+
@@ -423,14 +433,20 @@ const CommentDialog = (props: { leaveTo="opacity-0 scale-95" > - -

- Update{' '} - - {secretName} - {' '} - comment -

+ +
+

+ Update{' '} + + {secretName} + {' '} + comment +

+
+ Add a comment to this secret to provide additional information, context or + instructions. +
+
+ + + + + +
+ + +
+
+ + + +
+

+ Override{' '} + + {secretName} + {' '} +

+
+ Override this value with a Personal Secret. This value will only be visible + to you, and will not affect the value of this secret in the environment or + other users. +
+
+ + +
+ +
+ +
+ +
+ +
+
+
+
+
+
+
+ + ) +} + const DeleteConfirmDialog = (props: { secretId: string secretName: string @@ -551,6 +699,7 @@ const DeleteConfirmDialog = (props: { export default function SecretRow(props: { orgId: string secret: SecretType + environment: EnvironmentType cannonicalSecret: SecretType | undefined secretNames: Array> handlePropertyChange: Function @@ -640,8 +789,8 @@ export default function SecretRow(props: { onClick={toggleReveal} title={isRevealed ? 'Mask value' : 'Reveal value'} > - {isRevealed ? : }{' '} - {isRevealed ? 'Mask' : 'Reveal'} + {isRevealed ? : }{' '} + {isRevealed ? 'Mask' : 'Reveal'} @@ -662,6 +811,19 @@ export default function SecretRow(props: { handlePropertyChange={handlePropertyChange} /> +
+ +
diff --git a/frontend/graphql/mutations/environments/createPersonalSecret.gql b/frontend/graphql/mutations/environments/createPersonalSecret.gql new file mode 100644 index 000000000..ae2499ed1 --- /dev/null +++ b/frontend/graphql/mutations/environments/createPersonalSecret.gql @@ -0,0 +1,12 @@ +mutation CreateNewPersonalSecret($newPersonalSecret: PersonalSecretInput!) { + createOverride(overrideData: $newPersonalSecret) { + override { + id + secret { + id + } + value + createdAt + } + } +} diff --git a/frontend/graphql/mutations/environments/removePersonalSecret.gql b/frontend/graphql/mutations/environments/removePersonalSecret.gql new file mode 100644 index 000000000..f0007469d --- /dev/null +++ b/frontend/graphql/mutations/environments/removePersonalSecret.gql @@ -0,0 +1,5 @@ +mutation DeletePersonalSecret($secretId: ID!) { + removeOverride(secretId: $secretId) { + ok + } +} diff --git a/frontend/graphql/queries/secrets/getSecrets.gql b/frontend/graphql/queries/secrets/getSecrets.gql index 7e7f7218c..292bfdab8 100644 --- a/frontend/graphql/queries/secrets/getSecrets.gql +++ b/frontend/graphql/queries/secrets/getSecrets.gql @@ -32,6 +32,9 @@ query GetSecrets($appId: ID!, $envId: ID!) { } eventType } + override { + value + } } appEnvironments(appId: $appId, environmentId: $envId) { id From 812355416223d975fbdf580ccc88569b1e655806 Mon Sep 17 00:00:00 2001 From: rohan-chaturvedi Date: Tue, 14 Nov 2023 17:15:25 +0530 Subject: [PATCH 04/15] fix: misc ui fixes --- .../components/environments/SecretRow.tsx | 29 ++++++++++++------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/frontend/components/environments/SecretRow.tsx b/frontend/components/environments/SecretRow.tsx index 9ed0a3c5b..d5df1333c 100644 --- a/frontend/components/environments/SecretRow.tsx +++ b/frontend/components/environments/SecretRow.tsx @@ -500,6 +500,16 @@ const OverrideDialog = (props: { setIsOpen(true) } + const handleDeleteOverride = async () => { + await removeOverride({ + variables: { + secretId, + }, + }) + setValue('') + toast.success('Removed personal secret') + } + const handleUpdateOverride = async () => { if (value.length > 0) { const encryptedValue = await encryptAsymmetric(value, environment.identityKey) @@ -513,18 +523,10 @@ const OverrideDialog = (props: { }, }) toast.success('Saved personal secret') - } else if (override?.value !== undefined && value === '') { - await removeOverride({ - variables: { - secretId, - }, - }) - toast.success('Removed personal secret') } } const handleClose = () => { - handleUpdateOverride() closeModal() } @@ -533,7 +535,7 @@ const OverrideDialog = (props: {
@@ -594,8 +596,13 @@ const OverrideDialog = (props: { >
-
- + )} +
From ae611aefbfb856cb5eefd9e402f832b2153f6925 Mon Sep 17 00:00:00 2001 From: rohan-chaturvedi Date: Tue, 14 Nov 2023 17:15:52 +0530 Subject: [PATCH 05/15] feat: add personal secrets to REST api response --- backend/api/serializers.py | 23 ++++++++++++++++++++++- backend/api/views.py | 3 ++- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/backend/api/serializers.py b/backend/api/serializers.py index a3e44c364..26dabe490 100644 --- a/backend/api/serializers.py +++ b/backend/api/serializers.py @@ -1,5 +1,5 @@ from rest_framework import serializers -from .models import CustomUser, Environment, EnvironmentKey, Organisation, Secret, ServiceToken, UserToken +from .models import CustomUser, Environment, EnvironmentKey, Organisation, Secret, ServiceToken, UserToken, PersonalSecret def find_index_by_id(dictionaries, target_id): @@ -38,11 +38,32 @@ def create(self, validated_data): return Organisation(**validated_data) +class PersonalSecretSerializer(serializers.ModelSerializer): + class Meta: + model = PersonalSecret + fields = '__all__' + + class SecretSerializer(serializers.ModelSerializer): + override = serializers.SerializerMethodField() + class Meta: model = Secret fields = '__all__' + def get_override(self, obj): + # Assuming 'request' is passed to the context of the serializer. + org_member = self.context.get('org_member') + if org_member: + + try: + personal_secret = PersonalSecret.objects.get( + secret=obj, user=org_member) + return PersonalSecretSerializer(personal_secret).data + except PersonalSecret.DoesNotExist: + return None + return None + class EnvironmentSerializer(serializers.ModelSerializer): class Meta: diff --git a/backend/api/views.py b/backend/api/views.py index e15bfdef0..1258f61cc 100644 --- a/backend/api/views.py +++ b/backend/api/views.py @@ -346,7 +346,8 @@ def get(self, request): value=secret.value, comment=secret.comment, event_type=SecretEvent.READ, ip_address=ip_address, user_agent=user_agent) read_event.tags.set(secret.tags.all()) - serializer = SecretSerializer(secrets, many=True) + serializer = SecretSerializer(secrets, many=True, context={ + 'org_member': org_member}) return Response(serializer.data, status=status.HTTP_200_OK) From ecf58a9304de1b9fd5068e5c7e02c9db44dcbe0e Mon Sep 17 00:00:00 2001 From: rohan-chaturvedi Date: Tue, 14 Nov 2023 17:23:42 +0530 Subject: [PATCH 06/15] fix: operation name conflict, regenerate types --- frontend/apollo/gql.ts | 4 ++-- frontend/apollo/graphql.ts | 6 +++--- frontend/components/environments/SecretRow.tsx | 2 +- .../graphql/mutations/environments/removePersonalSecret.gql | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/frontend/apollo/gql.ts b/frontend/apollo/gql.ts index dd768c7bc..527e5ad05 100644 --- a/frontend/apollo/gql.ts +++ b/frontend/apollo/gql.ts @@ -31,7 +31,7 @@ const documents = { "mutation UpdateSecret($id: ID!, $secretData: SecretInput!) {\n editSecret(id: $id, secretData: $secretData) {\n secret {\n id\n updatedAt\n }\n }\n}": types.UpdateSecretDocument, "mutation InitAppEnvironments($devEnv: EnvironmentInput!, $stagingEnv: EnvironmentInput!, $prodEnv: EnvironmentInput!, $devAdminKeys: [EnvironmentKeyInput], $stagAdminKeys: [EnvironmentKeyInput], $prodAdminKeys: [EnvironmentKeyInput]) {\n devEnvironment: createEnvironment(\n environmentData: $devEnv\n adminKeys: $devAdminKeys\n ) {\n environment {\n id\n name\n createdAt\n identityKey\n }\n }\n stagingEnvironment: createEnvironment(\n environmentData: $stagingEnv\n adminKeys: $stagAdminKeys\n ) {\n environment {\n id\n name\n createdAt\n identityKey\n }\n }\n prodEnvironment: createEnvironment(\n environmentData: $prodEnv\n adminKeys: $prodAdminKeys\n ) {\n environment {\n id\n name\n createdAt\n identityKey\n }\n }\n}": types.InitAppEnvironmentsDocument, "mutation LogSecretRead($id: ID!) {\n readSecret(id: $id) {\n ok\n }\n}": types.LogSecretReadDocument, - "mutation DeletePersonalSecret($secretId: ID!) {\n removeOverride(secretId: $secretId) {\n ok\n }\n}": types.DeletePersonalSecretDocument, + "mutation RemovePersonalSecret($secretId: ID!) {\n removeOverride(secretId: $secretId) {\n ok\n }\n}": types.RemovePersonalSecretDocument, "mutation AcceptOrganisationInvite($orgId: ID!, $identityKey: String!, $wrappedKeyring: String!, $wrappedRecovery: String!, $inviteId: ID!) {\n createOrganisationMember(\n orgId: $orgId\n identityKey: $identityKey\n wrappedKeyring: $wrappedKeyring\n wrappedRecovery: $wrappedRecovery\n inviteId: $inviteId\n ) {\n orgMember {\n id\n email\n createdAt\n role\n }\n }\n}": types.AcceptOrganisationInviteDocument, "mutation DeleteOrgInvite($inviteId: ID!) {\n deleteInvitation(inviteId: $inviteId) {\n ok\n }\n}": types.DeleteOrgInviteDocument, "mutation RemoveMember($memberId: ID!) {\n deleteOrganisationMember(memberId: $memberId) {\n ok\n }\n}": types.RemoveMemberDocument, @@ -151,7 +151,7 @@ export function graphql(source: "mutation LogSecretRead($id: ID!) {\n readSecre /** * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. */ -export function graphql(source: "mutation DeletePersonalSecret($secretId: ID!) {\n removeOverride(secretId: $secretId) {\n ok\n }\n}"): (typeof documents)["mutation DeletePersonalSecret($secretId: ID!) {\n removeOverride(secretId: $secretId) {\n ok\n }\n}"]; +export function graphql(source: "mutation RemovePersonalSecret($secretId: ID!) {\n removeOverride(secretId: $secretId) {\n ok\n }\n}"): (typeof documents)["mutation RemovePersonalSecret($secretId: ID!) {\n removeOverride(secretId: $secretId) {\n ok\n }\n}"]; /** * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. */ diff --git a/frontend/apollo/graphql.ts b/frontend/apollo/graphql.ts index 3b3ce38b2..ebc0750f3 100644 --- a/frontend/apollo/graphql.ts +++ b/frontend/apollo/graphql.ts @@ -983,12 +983,12 @@ export type LogSecretReadMutationVariables = Exact<{ export type LogSecretReadMutation = { __typename?: 'Mutation', readSecret?: { __typename?: 'ReadSecretMutation', ok?: boolean | null } | null }; -export type DeletePersonalSecretMutationVariables = Exact<{ +export type RemovePersonalSecretMutationVariables = Exact<{ secretId: Scalars['ID']; }>; -export type DeletePersonalSecretMutation = { __typename?: 'Mutation', removeOverride?: { __typename?: 'DeletePersonalSecretMutation', ok?: boolean | null } | null }; +export type RemovePersonalSecretMutation = { __typename?: 'Mutation', removeOverride?: { __typename?: 'DeletePersonalSecretMutation', ok?: boolean | null } | null }; export type AcceptOrganisationInviteMutationVariables = Exact<{ orgId: Scalars['ID']; @@ -1231,7 +1231,7 @@ export const RevokeServiceTokenDocument = {"kind":"Document","definitions":[{"ki export const UpdateSecretDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"UpdateSecret"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"id"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"secretData"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"SecretInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"editSecret"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"id"}}},{"kind":"Argument","name":{"kind":"Name","value":"secretData"},"value":{"kind":"Variable","name":{"kind":"Name","value":"secretData"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"secret"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}}]}}]}}]}}]} as unknown as DocumentNode; export const InitAppEnvironmentsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"InitAppEnvironments"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"devEnv"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"EnvironmentInput"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"stagingEnv"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"EnvironmentInput"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"prodEnv"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"EnvironmentInput"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"devAdminKeys"}},"type":{"kind":"ListType","type":{"kind":"NamedType","name":{"kind":"Name","value":"EnvironmentKeyInput"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"stagAdminKeys"}},"type":{"kind":"ListType","type":{"kind":"NamedType","name":{"kind":"Name","value":"EnvironmentKeyInput"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"prodAdminKeys"}},"type":{"kind":"ListType","type":{"kind":"NamedType","name":{"kind":"Name","value":"EnvironmentKeyInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","alias":{"kind":"Name","value":"devEnvironment"},"name":{"kind":"Name","value":"createEnvironment"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"environmentData"},"value":{"kind":"Variable","name":{"kind":"Name","value":"devEnv"}}},{"kind":"Argument","name":{"kind":"Name","value":"adminKeys"},"value":{"kind":"Variable","name":{"kind":"Name","value":"devAdminKeys"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"environment"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"identityKey"}}]}}]}},{"kind":"Field","alias":{"kind":"Name","value":"stagingEnvironment"},"name":{"kind":"Name","value":"createEnvironment"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"environmentData"},"value":{"kind":"Variable","name":{"kind":"Name","value":"stagingEnv"}}},{"kind":"Argument","name":{"kind":"Name","value":"adminKeys"},"value":{"kind":"Variable","name":{"kind":"Name","value":"stagAdminKeys"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"environment"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"identityKey"}}]}}]}},{"kind":"Field","alias":{"kind":"Name","value":"prodEnvironment"},"name":{"kind":"Name","value":"createEnvironment"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"environmentData"},"value":{"kind":"Variable","name":{"kind":"Name","value":"prodEnv"}}},{"kind":"Argument","name":{"kind":"Name","value":"adminKeys"},"value":{"kind":"Variable","name":{"kind":"Name","value":"prodAdminKeys"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"environment"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"identityKey"}}]}}]}}]}}]} as unknown as DocumentNode; export const LogSecretReadDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"LogSecretRead"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"id"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"readSecret"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"id"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"ok"}}]}}]}}]} as unknown as DocumentNode; -export const DeletePersonalSecretDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"DeletePersonalSecret"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"secretId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"removeOverride"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"secretId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"secretId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"ok"}}]}}]}}]} as unknown as DocumentNode; +export const RemovePersonalSecretDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"RemovePersonalSecret"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"secretId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"removeOverride"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"secretId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"secretId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"ok"}}]}}]}}]} as unknown as DocumentNode; export const AcceptOrganisationInviteDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"AcceptOrganisationInvite"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"orgId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"identityKey"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"wrappedKeyring"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"wrappedRecovery"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"inviteId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"createOrganisationMember"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"orgId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"orgId"}}},{"kind":"Argument","name":{"kind":"Name","value":"identityKey"},"value":{"kind":"Variable","name":{"kind":"Name","value":"identityKey"}}},{"kind":"Argument","name":{"kind":"Name","value":"wrappedKeyring"},"value":{"kind":"Variable","name":{"kind":"Name","value":"wrappedKeyring"}}},{"kind":"Argument","name":{"kind":"Name","value":"wrappedRecovery"},"value":{"kind":"Variable","name":{"kind":"Name","value":"wrappedRecovery"}}},{"kind":"Argument","name":{"kind":"Name","value":"inviteId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"inviteId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"orgMember"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"email"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"role"}}]}}]}}]}}]} as unknown as DocumentNode; export const DeleteOrgInviteDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"DeleteOrgInvite"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"inviteId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"deleteInvitation"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"inviteId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"inviteId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"ok"}}]}}]}}]} as unknown as DocumentNode; export const RemoveMemberDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"RemoveMember"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"memberId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"deleteOrganisationMember"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"memberId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"memberId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"ok"}}]}}]}}]} as unknown as DocumentNode; diff --git a/frontend/components/environments/SecretRow.tsx b/frontend/components/environments/SecretRow.tsx index d5df1333c..ff6b7777f 100644 --- a/frontend/components/environments/SecretRow.tsx +++ b/frontend/components/environments/SecretRow.tsx @@ -27,7 +27,7 @@ import { GetSecretTags } from '@/graphql/queries/secrets/getSecretTags.gql' import { CreateNewSecretTag } from '@/graphql/mutations/environments/createSecretTag.gql' import { LogSecretRead } from '@/graphql/mutations/environments/readSecret.gql' import { CreateNewPersonalSecret } from '@/graphql/mutations/environments/createPersonalSecret.gql' -import { DeletePersonalSecret } from '@/graphql/mutations/environments/removePersonalSecret.gql' +import { RemovePersonalSecret } from '@/graphql/mutations/environments/removePersonalSecret.gql' import clsx from 'clsx' import { relativeTimeFromDates } from '@/utils/time' import { useLazyQuery, useMutation } from '@apollo/client' diff --git a/frontend/graphql/mutations/environments/removePersonalSecret.gql b/frontend/graphql/mutations/environments/removePersonalSecret.gql index f0007469d..2fb5fd518 100644 --- a/frontend/graphql/mutations/environments/removePersonalSecret.gql +++ b/frontend/graphql/mutations/environments/removePersonalSecret.gql @@ -1,4 +1,4 @@ -mutation DeletePersonalSecret($secretId: ID!) { +mutation RemovePersonalSecret($secretId: ID!) { removeOverride(secretId: $secretId) { ok } From a1463a559e7f82bbe38ab01a8eee7eb57e49500f Mon Sep 17 00:00:00 2001 From: rohan-chaturvedi Date: Tue, 14 Nov 2023 17:37:09 +0530 Subject: [PATCH 07/15] fix: operation name --- frontend/components/environments/SecretRow.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/components/environments/SecretRow.tsx b/frontend/components/environments/SecretRow.tsx index ff6b7777f..bd8550e29 100644 --- a/frontend/components/environments/SecretRow.tsx +++ b/frontend/components/environments/SecretRow.tsx @@ -486,7 +486,7 @@ const OverrideDialog = (props: { const { secretId, secretName, environment, override } = props const [createOverride] = useMutation(CreateNewPersonalSecret) - const [removeOverride] = useMutation(DeletePersonalSecret) + const [removeOverride] = useMutation(RemovePersonalSecret) const [value, setValue] = useState(override?.value || '') From bddd868726695f2152a7d858feeb7170245f8369 Mon Sep 17 00:00:00 2001 From: rohan-chaturvedi Date: Thu, 16 Nov 2023 12:50:31 +0530 Subject: [PATCH 08/15] feat: add is_active field to personal secret model --- ...ret_isactive_alter_personalsecret_value.py | 23 +++++++++++++++++++ ...ename_isactive_personalsecret_is_active.py | 18 +++++++++++++++ backend/api/models.py | 3 ++- .../backend/graphene/mutations/environment.py | 15 +++++------- backend/backend/graphene/types.py | 3 ++- frontend/apollo/schema.graphql | 4 +++- 6 files changed, 54 insertions(+), 12 deletions(-) create mode 100644 backend/api/migrations/0040_personalsecret_isactive_alter_personalsecret_value.py create mode 100644 backend/api/migrations/0041_rename_isactive_personalsecret_is_active.py diff --git a/backend/api/migrations/0040_personalsecret_isactive_alter_personalsecret_value.py b/backend/api/migrations/0040_personalsecret_isactive_alter_personalsecret_value.py new file mode 100644 index 000000000..8532a001d --- /dev/null +++ b/backend/api/migrations/0040_personalsecret_isactive_alter_personalsecret_value.py @@ -0,0 +1,23 @@ +# Generated by Django 4.2.3 on 2023-11-16 05:46 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('api', '0039_personalsecret'), + ] + + operations = [ + migrations.AddField( + model_name='personalsecret', + name='isActive', + field=models.BooleanField(default=True), + ), + migrations.AlterField( + model_name='personalsecret', + name='value', + field=models.TextField(blank=True, null=True), + ), + ] diff --git a/backend/api/migrations/0041_rename_isactive_personalsecret_is_active.py b/backend/api/migrations/0041_rename_isactive_personalsecret_is_active.py new file mode 100644 index 000000000..6cec45f9b --- /dev/null +++ b/backend/api/migrations/0041_rename_isactive_personalsecret_is_active.py @@ -0,0 +1,18 @@ +# Generated by Django 4.2.3 on 2023-11-16 05:53 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('api', '0040_personalsecret_isactive_alter_personalsecret_value'), + ] + + operations = [ + migrations.RenameField( + model_name='personalsecret', + old_name='isActive', + new_name='is_active', + ), + ] diff --git a/backend/api/models.py b/backend/api/models.py index 4c5d5cf0b..0d9b0a6c5 100644 --- a/backend/api/models.py +++ b/backend/api/models.py @@ -348,7 +348,8 @@ class PersonalSecret(models.Model): secret = models.ForeignKey(Secret, on_delete=models.CASCADE) user = models.ForeignKey( OrganisationMember, on_delete=models.CASCADE) - value = models.TextField() + value = models.TextField(blank=True, null=True) + is_active = models.BooleanField(default=True) created_at = models.DateTimeField(auto_now_add=True, blank=True, null=True) updated_at = models.DateTimeField(auto_now=True) deleted_at = models.DateTimeField(blank=True, null=True) diff --git a/backend/backend/graphene/mutations/environment.py b/backend/backend/graphene/mutations/environment.py index 585d4fe44..77501a2fd 100644 --- a/backend/backend/graphene/mutations/environment.py +++ b/backend/backend/graphene/mutations/environment.py @@ -38,6 +38,7 @@ class SecretInput(graphene.InputObjectType): class PersonalSecretInput(graphene.InputObjectType): secret_id = graphene.ID() value = graphene.String() + is_active = graphene.Boolean() class CreateEnvironmentMutation(graphene.Mutation): @@ -513,15 +514,11 @@ def mutate(cls, root, info, override_data): raise GraphQLError( "You don't have access to this secret") - if PersonalSecret.objects.filter(secret_id=override_data.secret_id, user=org_member).exists(): - override = PersonalSecret.objects.get( - secret_id=override_data.secret_id, user=org_member) - override.value = override_data.value - override.save() - - else: - override = PersonalSecret.objects.create( - secret_id=override_data.secret_id, user=org_member, value=override_data.value) + override, created = PersonalSecret.objects.get_or_create( + secret_id=override_data.secret_id, user=org_member) + override.value = override_data.value + override.is_active = override_data.is_active + override.save() return CreatePersonalSecretMutation(override=override) diff --git a/backend/backend/graphene/types.py b/backend/backend/graphene/types.py index 790f82d46..c5b2c3876 100644 --- a/backend/backend/graphene/types.py +++ b/backend/backend/graphene/types.py @@ -168,7 +168,8 @@ class Meta: class PersonalSecretType(DjangoObjectType): class Meta: model = PersonalSecret - fields = ('id', 'secret', 'user', 'value', 'created_at', 'updated_at') + fields = ('id', 'secret', 'user', 'value', + 'is_active', 'created_at', 'updated_at') class SecretType(DjangoObjectType): diff --git a/frontend/apollo/schema.graphql b/frontend/apollo/schema.graphql index d74d6f67a..6f11f0273 100644 --- a/frontend/apollo/schema.graphql +++ b/frontend/apollo/schema.graphql @@ -195,7 +195,8 @@ type PersonalSecretType { id: String! secret: SecretType! user: OrganisationMemberType! - value: String! + value: String + isActive: Boolean! createdAt: DateTime updatedAt: DateTime! } @@ -468,6 +469,7 @@ type CreatePersonalSecretMutation { input PersonalSecretInput { secretId: ID value: String + isActive: Boolean } type DeletePersonalSecretMutation { From c45dc29a085abb6696c4dbb30ed33612bc858b0a Mon Sep 17 00:00:00 2001 From: rohan-chaturvedi Date: Thu, 16 Nov 2023 12:50:45 +0530 Subject: [PATCH 09/15] feat: update frontend queries and mutations --- frontend/graphql/mutations/environments/createPersonalSecret.gql | 1 + frontend/graphql/queries/secrets/getSecrets.gql | 1 + 2 files changed, 2 insertions(+) diff --git a/frontend/graphql/mutations/environments/createPersonalSecret.gql b/frontend/graphql/mutations/environments/createPersonalSecret.gql index ae2499ed1..cc8a3d85c 100644 --- a/frontend/graphql/mutations/environments/createPersonalSecret.gql +++ b/frontend/graphql/mutations/environments/createPersonalSecret.gql @@ -6,6 +6,7 @@ mutation CreateNewPersonalSecret($newPersonalSecret: PersonalSecretInput!) { id } value + isActive createdAt } } diff --git a/frontend/graphql/queries/secrets/getSecrets.gql b/frontend/graphql/queries/secrets/getSecrets.gql index 292bfdab8..3bd928fba 100644 --- a/frontend/graphql/queries/secrets/getSecrets.gql +++ b/frontend/graphql/queries/secrets/getSecrets.gql @@ -34,6 +34,7 @@ query GetSecrets($appId: ID!, $envId: ID!) { } override { value + isActive } } appEnvironments(appId: $appId, environmentId: $envId) { From d0986adaaebdf79a328a21ac07ac952dca707aee Mon Sep 17 00:00:00 2001 From: rohan-chaturvedi Date: Thu, 16 Nov 2023 12:50:54 +0530 Subject: [PATCH 10/15] chore: regenerate types --- frontend/apollo/gql.ts | 4 ++-- frontend/apollo/graphql.ts | 10 ++++++---- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/frontend/apollo/gql.ts b/frontend/apollo/gql.ts index 527e5ad05..01c9ca029 100644 --- a/frontend/apollo/gql.ts +++ b/frontend/apollo/gql.ts @@ -57,7 +57,7 @@ const documents = { "query GetEnvironmentTokens($envId: ID!) {\n environmentTokens(environmentId: $envId) {\n id\n name\n wrappedKeyShare\n createdAt\n }\n}": types.GetEnvironmentTokensDocument, "query GetEnvSecretsKV($envId: ID!) {\n secrets(envId: $envId) {\n id\n key\n value\n }\n environmentKeys(environmentId: $envId) {\n id\n identityKey\n wrappedSeed\n wrappedSalt\n }\n}": types.GetEnvSecretsKvDocument, "query GetSecretTags($orgId: ID!) {\n secretTags(orgId: $orgId) {\n id\n name\n color\n }\n}": types.GetSecretTagsDocument, - "query GetSecrets($appId: ID!, $envId: ID!) {\n secrets(envId: $envId) {\n id\n key\n value\n tags {\n id\n name\n color\n }\n comment\n createdAt\n history {\n id\n key\n value\n tags {\n id\n name\n color\n }\n version\n comment\n timestamp\n ipAddress\n userAgent\n user {\n email\n username\n fullName\n avatarUrl\n }\n eventType\n }\n override {\n value\n }\n }\n appEnvironments(appId: $appId, environmentId: $envId) {\n id\n name\n envType\n identityKey\n }\n environmentKeys(appId: $appId, environmentId: $envId) {\n id\n identityKey\n wrappedSeed\n wrappedSalt\n }\n}": types.GetSecretsDocument, + "query GetSecrets($appId: ID!, $envId: ID!) {\n secrets(envId: $envId) {\n id\n key\n value\n tags {\n id\n name\n color\n }\n comment\n createdAt\n history {\n id\n key\n value\n tags {\n id\n name\n color\n }\n version\n comment\n timestamp\n ipAddress\n userAgent\n user {\n email\n username\n fullName\n avatarUrl\n }\n eventType\n }\n override {\n value\n isActive\n }\n }\n appEnvironments(appId: $appId, environmentId: $envId) {\n id\n name\n envType\n identityKey\n }\n environmentKeys(appId: $appId, environmentId: $envId) {\n id\n identityKey\n wrappedSeed\n wrappedSalt\n }\n}": types.GetSecretsDocument, "query GetServiceTokens($appId: ID!) {\n serviceTokens(appId: $appId) {\n id\n name\n createdAt\n createdBy {\n fullName\n avatarUrl\n self\n }\n expiresAt\n keys {\n id\n identityKey\n }\n }\n}": types.GetServiceTokensDocument, "query GetUserTokens($organisationId: ID!) {\n userTokens(organisationId: $organisationId) {\n id\n name\n wrappedKeyShare\n createdAt\n expiresAt\n }\n}": types.GetUserTokensDocument, }; @@ -255,7 +255,7 @@ export function graphql(source: "query GetSecretTags($orgId: ID!) {\n secretTag /** * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. */ -export function graphql(source: "query GetSecrets($appId: ID!, $envId: ID!) {\n secrets(envId: $envId) {\n id\n key\n value\n tags {\n id\n name\n color\n }\n comment\n createdAt\n history {\n id\n key\n value\n tags {\n id\n name\n color\n }\n version\n comment\n timestamp\n ipAddress\n userAgent\n user {\n email\n username\n fullName\n avatarUrl\n }\n eventType\n }\n override {\n value\n }\n }\n appEnvironments(appId: $appId, environmentId: $envId) {\n id\n name\n envType\n identityKey\n }\n environmentKeys(appId: $appId, environmentId: $envId) {\n id\n identityKey\n wrappedSeed\n wrappedSalt\n }\n}"): (typeof documents)["query GetSecrets($appId: ID!, $envId: ID!) {\n secrets(envId: $envId) {\n id\n key\n value\n tags {\n id\n name\n color\n }\n comment\n createdAt\n history {\n id\n key\n value\n tags {\n id\n name\n color\n }\n version\n comment\n timestamp\n ipAddress\n userAgent\n user {\n email\n username\n fullName\n avatarUrl\n }\n eventType\n }\n override {\n value\n }\n }\n appEnvironments(appId: $appId, environmentId: $envId) {\n id\n name\n envType\n identityKey\n }\n environmentKeys(appId: $appId, environmentId: $envId) {\n id\n identityKey\n wrappedSeed\n wrappedSalt\n }\n}"]; +export function graphql(source: "query GetSecrets($appId: ID!, $envId: ID!) {\n secrets(envId: $envId) {\n id\n key\n value\n tags {\n id\n name\n color\n }\n comment\n createdAt\n history {\n id\n key\n value\n tags {\n id\n name\n color\n }\n version\n comment\n timestamp\n ipAddress\n userAgent\n user {\n email\n username\n fullName\n avatarUrl\n }\n eventType\n }\n override {\n value\n isActive\n }\n }\n appEnvironments(appId: $appId, environmentId: $envId) {\n id\n name\n envType\n identityKey\n }\n environmentKeys(appId: $appId, environmentId: $envId) {\n id\n identityKey\n wrappedSeed\n wrappedSalt\n }\n}"): (typeof documents)["query GetSecrets($appId: ID!, $envId: ID!) {\n secrets(envId: $envId) {\n id\n key\n value\n tags {\n id\n name\n color\n }\n comment\n createdAt\n history {\n id\n key\n value\n tags {\n id\n name\n color\n }\n version\n comment\n timestamp\n ipAddress\n userAgent\n user {\n email\n username\n fullName\n avatarUrl\n }\n eventType\n }\n override {\n value\n isActive\n }\n }\n appEnvironments(appId: $appId, environmentId: $envId) {\n id\n name\n envType\n identityKey\n }\n environmentKeys(appId: $appId, environmentId: $envId) {\n id\n identityKey\n wrappedSeed\n wrappedSalt\n }\n}"]; /** * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. */ diff --git a/frontend/apollo/graphql.ts b/frontend/apollo/graphql.ts index ebc0750f3..e7099b408 100644 --- a/frontend/apollo/graphql.ts +++ b/frontend/apollo/graphql.ts @@ -558,6 +558,7 @@ export type OrganisationType = { }; export type PersonalSecretInput = { + isActive?: InputMaybe; secretId?: InputMaybe; value?: InputMaybe; }; @@ -566,10 +567,11 @@ export type PersonalSecretType = { __typename?: 'PersonalSecretType'; createdAt?: Maybe; id: Scalars['String']; + isActive: Scalars['Boolean']; secret: SecretType; updatedAt: Scalars['DateTime']; user: OrganisationMemberType; - value: Scalars['String']; + value?: Maybe; }; export type Query = { @@ -911,7 +913,7 @@ export type CreateNewPersonalSecretMutationVariables = Exact<{ }>; -export type CreateNewPersonalSecretMutation = { __typename?: 'Mutation', createOverride?: { __typename?: 'CreatePersonalSecretMutation', override?: { __typename?: 'PersonalSecretType', id: string, value: string, createdAt?: any | null, secret: { __typename?: 'SecretType', id: string } } | null } | null }; +export type CreateNewPersonalSecretMutation = { __typename?: 'Mutation', createOverride?: { __typename?: 'CreatePersonalSecretMutation', override?: { __typename?: 'PersonalSecretType', id: string, value?: string | null, createdAt?: any | null, secret: { __typename?: 'SecretType', id: string } } | null } | null }; export type CreateNewSecretMutationVariables = Exact<{ newSecret: SecretInput; @@ -1196,7 +1198,7 @@ export type GetSecretsQueryVariables = Exact<{ }>; -export type GetSecretsQuery = { __typename?: 'Query', secrets?: Array<{ __typename?: 'SecretType', id: string, key: string, value: string, comment: string, createdAt?: any | null, tags: Array<{ __typename?: 'SecretTagType', id: string, name: string, color: string }>, history?: Array<{ __typename?: 'SecretEventType', id: string, key: string, value: string, version: number, comment: string, timestamp: any, ipAddress?: string | null, userAgent?: string | null, eventType: ApiSecretEventEventTypeChoices, tags: Array<{ __typename?: 'SecretTagType', id: string, name: string, color: string }>, user?: { __typename?: 'OrganisationMemberType', email?: string | null, username?: string | null, fullName?: string | null, avatarUrl?: string | null } | null } | null> | null, override?: { __typename?: 'PersonalSecretType', value: string } | null } | null> | null, appEnvironments?: Array<{ __typename?: 'EnvironmentType', id: string, name: string, envType: ApiEnvironmentEnvTypeChoices, identityKey: string } | null> | null, environmentKeys?: Array<{ __typename?: 'EnvironmentKeyType', id: string, identityKey: string, wrappedSeed: string, wrappedSalt: string } | null> | null }; +export type GetSecretsQuery = { __typename?: 'Query', secrets?: Array<{ __typename?: 'SecretType', id: string, key: string, value: string, comment: string, createdAt?: any | null, tags: Array<{ __typename?: 'SecretTagType', id: string, name: string, color: string }>, history?: Array<{ __typename?: 'SecretEventType', id: string, key: string, value: string, version: number, comment: string, timestamp: any, ipAddress?: string | null, userAgent?: string | null, eventType: ApiSecretEventEventTypeChoices, tags: Array<{ __typename?: 'SecretTagType', id: string, name: string, color: string }>, user?: { __typename?: 'OrganisationMemberType', email?: string | null, username?: string | null, fullName?: string | null, avatarUrl?: string | null } | null } | null> | null, override?: { __typename?: 'PersonalSecretType', value?: string | null, isActive: boolean } | null } | null> | null, appEnvironments?: Array<{ __typename?: 'EnvironmentType', id: string, name: string, envType: ApiEnvironmentEnvTypeChoices, identityKey: string } | null> | null, environmentKeys?: Array<{ __typename?: 'EnvironmentKeyType', id: string, identityKey: string, wrappedSeed: string, wrappedSalt: string } | null> | null }; export type GetServiceTokensQueryVariables = Exact<{ appId: Scalars['ID']; @@ -1257,6 +1259,6 @@ export const GetEnvironmentKeyDocument = {"kind":"Document","definitions":[{"kin export const GetEnvironmentTokensDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetEnvironmentTokens"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"envId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"environmentTokens"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"environmentId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"envId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"wrappedKeyShare"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}}]}}]}}]} as unknown as DocumentNode; export const GetEnvSecretsKvDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetEnvSecretsKV"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"envId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"secrets"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"envId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"envId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"key"}},{"kind":"Field","name":{"kind":"Name","value":"value"}}]}},{"kind":"Field","name":{"kind":"Name","value":"environmentKeys"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"environmentId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"envId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"identityKey"}},{"kind":"Field","name":{"kind":"Name","value":"wrappedSeed"}},{"kind":"Field","name":{"kind":"Name","value":"wrappedSalt"}}]}}]}}]} as unknown as DocumentNode; export const GetSecretTagsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetSecretTags"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"orgId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"secretTags"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"orgId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"orgId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"color"}}]}}]}}]} as unknown as DocumentNode; -export const GetSecretsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetSecrets"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"appId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"envId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"secrets"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"envId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"envId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"key"}},{"kind":"Field","name":{"kind":"Name","value":"value"}},{"kind":"Field","name":{"kind":"Name","value":"tags"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"color"}}]}},{"kind":"Field","name":{"kind":"Name","value":"comment"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"history"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"key"}},{"kind":"Field","name":{"kind":"Name","value":"value"}},{"kind":"Field","name":{"kind":"Name","value":"tags"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"color"}}]}},{"kind":"Field","name":{"kind":"Name","value":"version"}},{"kind":"Field","name":{"kind":"Name","value":"comment"}},{"kind":"Field","name":{"kind":"Name","value":"timestamp"}},{"kind":"Field","name":{"kind":"Name","value":"ipAddress"}},{"kind":"Field","name":{"kind":"Name","value":"userAgent"}},{"kind":"Field","name":{"kind":"Name","value":"user"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"email"}},{"kind":"Field","name":{"kind":"Name","value":"username"}},{"kind":"Field","name":{"kind":"Name","value":"fullName"}},{"kind":"Field","name":{"kind":"Name","value":"avatarUrl"}}]}},{"kind":"Field","name":{"kind":"Name","value":"eventType"}}]}},{"kind":"Field","name":{"kind":"Name","value":"override"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"value"}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"appEnvironments"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"appId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"appId"}}},{"kind":"Argument","name":{"kind":"Name","value":"environmentId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"envId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"envType"}},{"kind":"Field","name":{"kind":"Name","value":"identityKey"}}]}},{"kind":"Field","name":{"kind":"Name","value":"environmentKeys"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"appId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"appId"}}},{"kind":"Argument","name":{"kind":"Name","value":"environmentId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"envId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"identityKey"}},{"kind":"Field","name":{"kind":"Name","value":"wrappedSeed"}},{"kind":"Field","name":{"kind":"Name","value":"wrappedSalt"}}]}}]}}]} as unknown as DocumentNode; +export const GetSecretsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetSecrets"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"appId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"envId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"secrets"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"envId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"envId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"key"}},{"kind":"Field","name":{"kind":"Name","value":"value"}},{"kind":"Field","name":{"kind":"Name","value":"tags"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"color"}}]}},{"kind":"Field","name":{"kind":"Name","value":"comment"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"history"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"key"}},{"kind":"Field","name":{"kind":"Name","value":"value"}},{"kind":"Field","name":{"kind":"Name","value":"tags"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"color"}}]}},{"kind":"Field","name":{"kind":"Name","value":"version"}},{"kind":"Field","name":{"kind":"Name","value":"comment"}},{"kind":"Field","name":{"kind":"Name","value":"timestamp"}},{"kind":"Field","name":{"kind":"Name","value":"ipAddress"}},{"kind":"Field","name":{"kind":"Name","value":"userAgent"}},{"kind":"Field","name":{"kind":"Name","value":"user"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"email"}},{"kind":"Field","name":{"kind":"Name","value":"username"}},{"kind":"Field","name":{"kind":"Name","value":"fullName"}},{"kind":"Field","name":{"kind":"Name","value":"avatarUrl"}}]}},{"kind":"Field","name":{"kind":"Name","value":"eventType"}}]}},{"kind":"Field","name":{"kind":"Name","value":"override"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"value"}},{"kind":"Field","name":{"kind":"Name","value":"isActive"}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"appEnvironments"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"appId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"appId"}}},{"kind":"Argument","name":{"kind":"Name","value":"environmentId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"envId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"envType"}},{"kind":"Field","name":{"kind":"Name","value":"identityKey"}}]}},{"kind":"Field","name":{"kind":"Name","value":"environmentKeys"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"appId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"appId"}}},{"kind":"Argument","name":{"kind":"Name","value":"environmentId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"envId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"identityKey"}},{"kind":"Field","name":{"kind":"Name","value":"wrappedSeed"}},{"kind":"Field","name":{"kind":"Name","value":"wrappedSalt"}}]}}]}}]} as unknown as DocumentNode; export const GetServiceTokensDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetServiceTokens"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"appId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"serviceTokens"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"appId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"appId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"createdBy"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"fullName"}},{"kind":"Field","name":{"kind":"Name","value":"avatarUrl"}},{"kind":"Field","name":{"kind":"Name","value":"self"}}]}},{"kind":"Field","name":{"kind":"Name","value":"expiresAt"}},{"kind":"Field","name":{"kind":"Name","value":"keys"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"identityKey"}}]}}]}}]}}]} as unknown as DocumentNode; export const GetUserTokensDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetUserTokens"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"organisationId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"userTokens"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"organisationId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"organisationId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"wrappedKeyShare"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"expiresAt"}}]}}]}}]} as unknown as DocumentNode; \ No newline at end of file From 7f328bfe6202ed2a14c6c65f8c248cdf49aa3631 Mon Sep 17 00:00:00 2001 From: rohan-chaturvedi Date: Thu, 16 Nov 2023 12:51:10 +0530 Subject: [PATCH 11/15] feat: show red spinner on danger buttons when isLoading --- frontend/components/common/Button.tsx | 4 +++- frontend/components/common/Spinner.tsx | 19 +++++++++++++++---- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/frontend/components/common/Button.tsx b/frontend/components/common/Button.tsx index fb84f1fc5..a943ebe8d 100644 --- a/frontend/components/common/Button.tsx +++ b/frontend/components/common/Button.tsx @@ -67,6 +67,8 @@ export function Button(buttonProps: ButtonProps) { /> ) + const spinnerColor = variant === 'danger' ? 'red' : 'emerald' + return ( diff --git a/frontend/components/common/Spinner.tsx b/frontend/components/common/Spinner.tsx index 684f896f6..d93cf0558 100644 --- a/frontend/components/common/Spinner.tsx +++ b/frontend/components/common/Spinner.tsx @@ -1,4 +1,5 @@ import clsx from 'clsx' +import { color } from 'framer-motion' const SIZES = { sm: 'border-2 h-4 w-4', @@ -7,16 +8,26 @@ const SIZES = { xl: 'border-6 h-12 w-12', } +const COLORS = { + emerald: 'border-emerald-500', + red: 'border-red-500', +} + interface SpinnerProps { size: 'sm' | 'md' | 'lg' | 'xl' + color?: 'emerald' | 'red' } -export default function Spinner(props: SpinnerProps = { size: 'lg' }) { - const { size } = props +export default function Spinner(props: SpinnerProps = { size: 'lg', color: 'emerald' }) { + const { size, color } = props + + const spinnerColor = color || 'emerald' + const BASE_STYLE = - 'inline-block animate-spin rounded-full border-4 border-solid border-emerald-500 border-r-transparent align-[-0.125em] motion-reduce:animate-[spin_1.5s_linear_infinite]' + 'inline-block animate-spin rounded-full border-4 border-solid border-r-transparent align-[-0.125em] motion-reduce:animate-[spin_1.5s_linear_infinite]' + return ( -
+
Loading... From 82b96ff148c28142e8ef7c5c63cec7ec0c692828 Mon Sep 17 00:00:00 2001 From: rohan-chaturvedi Date: Thu, 16 Nov 2023 12:51:23 +0530 Subject: [PATCH 12/15] feat: handle isActive field, misc ux improvements --- .../components/environments/SecretRow.tsx | 111 +++++++++++++++--- 1 file changed, 92 insertions(+), 19 deletions(-) diff --git a/frontend/components/environments/SecretRow.tsx b/frontend/components/environments/SecretRow.tsx index bd8550e29..b8f9aeafe 100644 --- a/frontend/components/environments/SecretRow.tsx +++ b/frontend/components/environments/SecretRow.tsx @@ -22,7 +22,7 @@ import { FaUserEdit, } from 'react-icons/fa' import { Button } from '../common/Button' -import { Dialog, Transition } from '@headlessui/react' +import { Dialog, Switch, Transition } from '@headlessui/react' import { GetSecretTags } from '@/graphql/queries/secrets/getSecretTags.gql' import { CreateNewSecretTag } from '@/graphql/mutations/environments/createSecretTag.gql' import { LogSecretRead } from '@/graphql/mutations/environments/readSecret.gql' @@ -485,13 +485,21 @@ const OverrideDialog = (props: { }) => { const { secretId, secretName, environment, override } = props - const [createOverride] = useMutation(CreateNewPersonalSecret) - const [removeOverride] = useMutation(RemovePersonalSecret) + const [createOverride, { loading: createLoading }] = useMutation(CreateNewPersonalSecret) + const [removeOverride, { loading: removeLoading }] = useMutation(RemovePersonalSecret) const [value, setValue] = useState(override?.value || '') + const [isActive, setIsActive] = useState(override ? override.isActive : true) + const [saved, setSaved] = useState(true) const [isOpen, setIsOpen] = useState(false) + const reset = () => { + console.log('reset') + setValue(override?.value || '') + setIsActive(override?.isActive || true) + } + const closeModal = () => { setIsOpen(false) } @@ -500,14 +508,37 @@ const OverrideDialog = (props: { setIsOpen(true) } + const valueUpdated = () => { + if (override === null && value === '') return false + else { + return override?.value !== value + } + } + + const isActiveUpdated = () => { + if (override === null && value === '') return false + else { + return isActive !== override?.isActive + } + } + + const saveRequired = valueUpdated() || isActiveUpdated() + + useEffect(() => { + if (saveRequired) setSaved(false) + }, [saveRequired]) + + const toggleIsActive = () => setIsActive(!isActive) + const handleDeleteOverride = async () => { await removeOverride({ variables: { secretId, }, }) - setValue('') + reset() toast.success('Removed personal secret') + closeModal() } const handleUpdateOverride = async () => { @@ -519,25 +550,37 @@ const OverrideDialog = (props: { newPersonalSecret: { secretId, value: encryptedValue, + isActive, }, }, }) toast.success('Saved personal secret') + setSaved(true) + closeModal() } } const handleClose = () => { + if (saveRequired && !saved) reset() closeModal() } + const activeOverride = override?.value?.length && override?.isActive + return ( <>
-
@@ -587,7 +630,7 @@ const OverrideDialog = (props: { -
+
-
- {override && ( - + )} + - )} - +
@@ -820,7 +893,7 @@ export default function SecretRow(props: {
From a2df7eb0e93ec8af2daecc36e32423a8f85d34db Mon Sep 17 00:00:00 2001 From: rohan-chaturvedi Date: Thu, 16 Nov 2023 12:56:00 +0530 Subject: [PATCH 13/15] fix: remove console.log --- frontend/components/environments/SecretRow.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/frontend/components/environments/SecretRow.tsx b/frontend/components/environments/SecretRow.tsx index b8f9aeafe..f65f2c9fa 100644 --- a/frontend/components/environments/SecretRow.tsx +++ b/frontend/components/environments/SecretRow.tsx @@ -495,7 +495,6 @@ const OverrideDialog = (props: { const [isOpen, setIsOpen] = useState(false) const reset = () => { - console.log('reset') setValue(override?.value || '') setIsActive(override?.isActive || true) } From a47d96a3e0222f197f3709d8bae120d232cd4aa7 Mon Sep 17 00:00:00 2001 From: rohan-chaturvedi Date: Thu, 16 Nov 2023 18:23:44 +0530 Subject: [PATCH 14/15] fix: misc bugs, ui layout in override dialog --- .../components/environments/SecretRow.tsx | 93 +++++++++++-------- 1 file changed, 53 insertions(+), 40 deletions(-) diff --git a/frontend/components/environments/SecretRow.tsx b/frontend/components/environments/SecretRow.tsx index f65f2c9fa..9de88d65f 100644 --- a/frontend/components/environments/SecretRow.tsx +++ b/frontend/components/environments/SecretRow.tsx @@ -20,6 +20,8 @@ import { FaSquare, FaKey, FaUserEdit, + FaTrash, + FaCheck, } from 'react-icons/fa' import { Button } from '../common/Button' import { Dialog, Switch, Transition } from '@headlessui/react' @@ -499,6 +501,11 @@ const OverrideDialog = (props: { setIsActive(override?.isActive || true) } + const clear = () => { + setValue('') + setIsActive(true) + } + const closeModal = () => { setIsOpen(false) } @@ -535,28 +542,26 @@ const OverrideDialog = (props: { secretId, }, }) - reset() + clear() toast.success('Removed personal secret') closeModal() } const handleUpdateOverride = async () => { - if (value.length > 0) { - const encryptedValue = await encryptAsymmetric(value, environment.identityKey) + const encryptedValue = await encryptAsymmetric(value, environment.identityKey) - await createOverride({ - variables: { - newPersonalSecret: { - secretId, - value: encryptedValue, - isActive, - }, + await createOverride({ + variables: { + newPersonalSecret: { + secretId, + value: encryptedValue, + isActive, }, - }) - toast.success('Saved personal secret') - setSaved(true) - closeModal() - } + }, + }) + toast.success('Saved personal secret') + setSaved(true) + closeModal() } const handleClose = () => { @@ -564,7 +569,7 @@ const OverrideDialog = (props: { closeModal() } - const activeOverride = override?.value?.length && override?.isActive + const activeOverride = override && override?.isActive return ( <> @@ -619,8 +624,8 @@ const OverrideDialog = (props: {
Override this value with a Personal Secret. This value will only be visible - to you, and will not affect the value of this secret in the environment or - other users. + to you, and will not alter the value of this secret for other users or 3rd + party services.
@@ -629,18 +634,22 @@ const OverrideDialog = (props: { -
- -
- -
-
-
Activate override
+
+
+
+ Override Value +
+ +
+
+
+ Activate Secret Override +
-
+
+ +
+
{override && ( )} -
+
@@ -892,7 +905,7 @@ export default function SecretRow(props: {
From bbf4f54cc55715a26f2db84e3753141aa17d29c6 Mon Sep 17 00:00:00 2001 From: rohan-chaturvedi Date: Thu, 16 Nov 2023 18:52:14 +0530 Subject: [PATCH 15/15] fix: tweak spacing --- frontend/components/environments/SecretRow.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/components/environments/SecretRow.tsx b/frontend/components/environments/SecretRow.tsx index 9de88d65f..f3b3a4850 100644 --- a/frontend/components/environments/SecretRow.tsx +++ b/frontend/components/environments/SecretRow.tsx @@ -634,7 +634,7 @@ const OverrideDialog = (props: { -
+
Override Value