├── .config └── dotnet-tools.json ├── .editorconfig ├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ ├── custom.md │ └── feature_request.md ├── PULL_REQUEST_TEMPLATE.md └── workflows │ └── codeql-analysis.yml ├── .gitignore ├── .vscode └── extensions.json ├── CODE_OF_CONDUCT.md ├── LICENSE ├── README.md ├── build-ui.sh ├── docs └── arch.drawio.svg ├── global.json ├── nuget.config └── src ├── Backend ├── Confix.sln ├── Directory.Build.props ├── Directory.Packages.props ├── src │ ├── Authentication │ │ ├── ApiKey │ │ │ ├── ApiKey.cs │ │ │ ├── ApiKeyAuthenticationSucceededContext.cs │ │ │ ├── ApiKeyDefaults.cs │ │ │ ├── ApiKeyExtensions.cs │ │ │ ├── ApiKeyHandler.cs │ │ │ ├── ApiKeyOptions.cs │ │ │ └── IApiKeyProvider.cs │ │ ├── Authentication.csproj │ │ ├── Authorization │ │ │ ├── AuthorizationRule.cs │ │ │ ├── AuthorizationService.cs │ │ │ ├── ClaimRequirement.cs │ │ │ ├── Extensions │ │ │ │ ├── AuthorizationPolicyExtensions.cs │ │ │ │ ├── AuthorizationRuleExtensions.cs │ │ │ │ ├── AuthorizationRuleServiceCollectionExtensions.cs │ │ │ │ └── SessionAccessorExtensions.cs │ │ │ ├── Group.cs │ │ │ ├── IAuthorizationRule.cs │ │ │ ├── IAuthorizationService.cs │ │ │ ├── ISession.cs │ │ │ ├── ISessionAccessor.cs │ │ │ ├── Permission.cs │ │ │ ├── Permissions.cs │ │ │ ├── Policies.cs │ │ │ ├── Providers │ │ │ │ ├── GroupProvider.cs │ │ │ │ ├── IGroupProvider.cs │ │ │ │ ├── IRoleProvider.cs │ │ │ │ └── RoleProvider.cs │ │ │ ├── Repositories │ │ │ │ ├── IGroupStore.cs │ │ │ │ └── IRoleStore.cs │ │ │ ├── Requirement.cs │ │ │ ├── Role.cs │ │ │ ├── RoleScope.cs │ │ │ ├── Scope.cs │ │ │ ├── Scopes.cs │ │ │ ├── Session.cs │ │ │ ├── SessionAccessor.cs │ │ │ ├── UserInfo.cs │ │ │ └── WellKnownNamespaces.cs │ │ ├── ClientCredentials │ │ │ ├── AddTokenMessageHandler.cs │ │ │ ├── ClientCredentialCache.cs │ │ │ ├── ClientCredentialServiceCollectionExtensions.cs │ │ │ ├── ClientCredentialsClientOptions.cs │ │ │ └── IClientCredentialCache.cs │ │ ├── Extensions │ │ │ └── StringExtensions.cs │ │ └── InternalsVisibleTo.cs │ ├── Authoring.Abstractions │ │ ├── ApiKeys │ │ │ ├── DataLoaders │ │ │ │ └── IApiKeyById.cs │ │ │ ├── Models │ │ │ │ └── ApiKeyWithSecret.cs │ │ │ ├── Service │ │ │ │ └── IApiKeyService.cs │ │ │ └── Stores │ │ │ │ └── IApiKeyStore.cs │ │ ├── Applications │ │ │ ├── Changes │ │ │ │ ├── AddComponentToApplicationPartChange.cs │ │ │ │ ├── AddPartToApplicationChange.cs │ │ │ │ ├── ApplicationPartComponentValuesChange.cs │ │ │ │ ├── CreateApplicationChange.cs │ │ │ │ ├── IApplicationChange.cs │ │ │ │ ├── IApplicationPartChange.cs │ │ │ │ ├── IApplicationPartComponentChange.cs │ │ │ │ ├── PublishedApplicationPartChange.cs │ │ │ │ ├── RemoveComponentFromApplicationPartChange.cs │ │ │ │ ├── RemovePartFromApplicationChange.cs │ │ │ │ ├── RenameApplicationChange.cs │ │ │ │ └── RenameApplicationPartChange.cs │ │ │ ├── DataLoaders │ │ │ │ ├── IApplicationByComponentIdDataLoader.cs │ │ │ │ ├── IApplicationByPartIdDataLoader.cs │ │ │ │ ├── IApplicationDataLoader.cs │ │ │ │ ├── IApplicationPartComponentDataLoader.cs │ │ │ │ └── IApplicationPartDataLoader.cs │ │ │ ├── Exceptions │ │ │ │ ├── ApplicationNotFoundException.cs │ │ │ │ ├── ApplicationPartComponentNotFoundException.cs │ │ │ │ └── ApplicationPartNotFoundException.cs │ │ │ ├── Models │ │ │ │ ├── Application.cs │ │ │ │ ├── ApplicationPart.cs │ │ │ │ └── ApplicationPartComponent.cs │ │ │ ├── Services │ │ │ │ └── IApplicationService.cs │ │ │ └── Stores │ │ │ │ └── IApplicationStore.cs │ │ ├── Authoring.Abstractions.csproj │ │ ├── ChangeLog │ │ │ ├── Models │ │ │ │ ├── ChangeLog.cs │ │ │ │ └── IChange.cs │ │ │ └── Stores │ │ │ │ └── IChangeLogStore.cs │ │ ├── Components │ │ │ ├── Changes │ │ │ │ ├── ChangeScopeOfComponentChange.cs │ │ │ │ ├── ComponentSchemaChange.cs │ │ │ │ ├── ComponentValuesChange.cs │ │ │ │ ├── CreateComponentChange.cs │ │ │ │ ├── IComponentChange.cs │ │ │ │ ├── RemoveComponentChange.cs │ │ │ │ └── RenameComponentChange.cs │ │ │ ├── DataLoaders │ │ │ │ └── IComponentDataLoader.cs │ │ │ ├── Exceptions │ │ │ │ └── ComponentNotFoundException.cs │ │ │ ├── Models │ │ │ │ ├── ApplicationComponentScope.cs │ │ │ │ ├── ApplicationPartComponentScope.cs │ │ │ │ ├── Component.cs │ │ │ │ ├── ComponentScope.cs │ │ │ │ └── NamespaceComponentScope.cs │ │ │ ├── Services │ │ │ │ └── IComponentService.cs │ │ │ └── Stores │ │ │ │ └── IComponentStore.cs │ │ ├── Configuration │ │ │ └── IAuthoringServerBuilder.cs │ │ ├── Environment │ │ │ ├── Exceptions │ │ │ │ ├── EnvironmentCycleDetectedException.cs │ │ │ │ ├── EnvironmentNameCollisionException.cs │ │ │ │ └── EnvironmentNotFoundException.cs │ │ │ ├── Models │ │ │ │ └── Environment.cs │ │ │ ├── Services │ │ │ │ └── IEnvironmentService.cs │ │ │ └── Stores │ │ │ │ └── IEnvironmentStore.cs │ │ ├── Exceptions │ │ │ ├── EntityIdInvalidException.cs │ │ │ └── NameTakenException.cs │ │ ├── Groups │ │ │ └── Dataloaders │ │ │ │ └── IGroupByIdDataLoader.cs │ │ ├── Publishing │ │ │ ├── DataLoader │ │ │ │ ├── IPublishedApplicationPartByIdDataloader.cs │ │ │ │ └── IPublishedApplicationPartsByPartIdDataloader.cs │ │ │ ├── Models │ │ │ │ ├── ClaimedVersion.cs │ │ │ │ └── PublishedApplicationPart.cs │ │ │ ├── Services │ │ │ │ └── IPublishingService.cs │ │ │ └── Stores │ │ │ │ └── IPublishingStore.cs │ │ ├── Roles │ │ │ └── Dataloaders │ │ │ │ └── IRoleByIdDataLoader.cs │ │ ├── ScalarNames.cs │ │ ├── Schema │ │ │ ├── Exceptions │ │ │ │ ├── InvalidSchemaException.cs │ │ │ │ └── SchemaViolationException.cs │ │ │ └── Models │ │ │ │ └── SchemaViolation.cs │ │ └── Variables │ │ │ ├── Changes │ │ │ ├── CreateVariableChange.cs │ │ │ ├── DeleteVariableValueChange.cs │ │ │ ├── IVariableChange.cs │ │ │ ├── RenameVariableChange.cs │ │ │ └── VariableValueChanged.cs │ │ │ ├── DataLoaders │ │ │ └── IVariableDataLoader.cs │ │ │ ├── Models │ │ │ ├── ApplicationPartVariableScope.cs │ │ │ ├── ApplicationVariableValueScope.cs │ │ │ ├── NamespaceVariableScope.cs │ │ │ ├── Variable.cs │ │ │ ├── VariableState.cs │ │ │ ├── VariableValue.cs │ │ │ └── VariableValueScope.cs │ │ │ ├── Services │ │ │ ├── IVariableService.cs │ │ │ └── VariableValueScopeInput.cs │ │ │ └── Stores │ │ │ ├── IVariableStore.cs │ │ │ └── IVariableValueStore.cs │ ├── Authoring.Core │ │ ├── ApiKey │ │ │ ├── ApiKeyProvider.cs │ │ │ ├── ApiKeyRequestExecutorBuilderExtensions.cs │ │ │ ├── Authorization │ │ │ │ └── ApiKeyAuthorizationPolicy.cs │ │ │ ├── DataLoaders │ │ │ │ └── ApiKeyByIdDataloader.cs │ │ │ └── Services │ │ │ │ └── ApiKeyService.cs │ │ ├── Applications │ │ │ ├── ApplicationServiceCollectionExtensions.cs │ │ │ ├── Authorization │ │ │ │ ├── ApplicationAuthorizationRule.cs │ │ │ │ ├── ApplicationPartAuthorizationRule.cs │ │ │ │ └── ApplicationPartComponentAuthorizationRule.cs │ │ │ ├── DataLoaders │ │ │ │ ├── ApplicationByComponentIdDataLoader.cs │ │ │ │ ├── ApplicationByIdDataLoader.cs │ │ │ │ ├── ApplicationByPartIdDataLoader.cs │ │ │ │ ├── ApplicationPartByIdDataLoader.cs │ │ │ │ └── ApplicationPartComponentByIdDataloader.cs │ │ │ └── Services │ │ │ │ └── ApplicationService.cs │ │ ├── Authentication │ │ │ ├── AuthenticationExtensions.cs │ │ │ ├── AuthoringServerAuthenticationBuilder.cs │ │ │ └── IAuthoringServerAuthenticationBuilder.cs │ │ ├── Authoring.Core.csproj │ │ ├── AuthoringServiceCollectionExtensions.cs │ │ ├── ChangeLog │ │ │ ├── Authorization │ │ │ │ └── ChangeLogAuthorizationRule.cs │ │ │ ├── ChangeLogServiceCollectionExtensions.cs │ │ │ ├── DataLoaders │ │ │ │ ├── ChangeLogByApplicationIdDataloader.cs │ │ │ │ ├── ChangeLogByApplicationPartComponentIdDataloader.cs │ │ │ │ ├── ChangeLogByApplicationPartIdDataloader.cs │ │ │ │ ├── ChangeLogByComponentIdDataloader.cs │ │ │ │ ├── ChangeLogByIdDataloader.cs │ │ │ │ └── ChangeLogByVariableIdDataloader.cs │ │ │ └── Services │ │ │ │ ├── ChangeLogService.cs │ │ │ │ └── IChangeLogService.cs │ │ ├── Components │ │ │ ├── Authorization │ │ │ │ └── ComponentAuthorizationRule.cs │ │ │ ├── ComponentServiceCollectionExtensions.cs │ │ │ ├── DataLoaders │ │ │ │ └── ComponentByIdDataLoader.cs │ │ │ └── Services │ │ │ │ ├── ComponentService.cs │ │ │ │ └── ComponentValidationFailed.cs │ │ ├── Environement │ │ │ ├── Authorization │ │ │ │ └── EnvironmentAuthorizationRule.cs │ │ │ ├── DataLoaders │ │ │ │ └── EnvironmentByIdDataLoader.cs │ │ │ ├── EnvironmentServiceCollectionExtensions.cs │ │ │ └── Services │ │ │ │ └── EnvironmentService.cs │ │ ├── Extensions │ │ │ ├── CollectionExtensions.cs │ │ │ └── PathExtensions.cs │ │ ├── Groups │ │ │ ├── Authorization │ │ │ │ └── GroupAuthorizationRule.cs │ │ │ ├── DataLoaders │ │ │ │ └── ApplicationByIdDataLoader.cs │ │ │ ├── GroupServiceCollectionExtensions.cs │ │ │ └── Services │ │ │ │ ├── GroupService.cs │ │ │ │ └── IGroupService.cs │ │ ├── InternalsVisibleTo.cs │ │ ├── Publishing │ │ │ ├── Authorization │ │ │ │ ├── DeveloperAccessAuthorizationRule.cs │ │ │ │ ├── DeveloperAccessRequest.cs │ │ │ │ └── PublishedApplicationPartAuthorizationRule.cs │ │ │ ├── DataLoader │ │ │ │ ├── PublishedApplicationPartByIdDataloader.cs │ │ │ │ └── PublishedApplicationPartByIdPartDataloader.cs │ │ │ ├── Exceptions │ │ │ │ ├── ClaimVersionFailedException.cs │ │ │ │ └── PublishingException.cs │ │ │ ├── PublishingServiceCollectionExtensions.cs │ │ │ └── Services │ │ │ │ ├── JsonVariableVisitor.cs │ │ │ │ ├── JsonVariableVisitorContext.cs │ │ │ │ ├── PublishingService.cs │ │ │ │ └── VariableMatch.cs │ │ ├── Roles │ │ │ ├── Authorization │ │ │ │ └── RoleAuthorizationRule.cs │ │ │ ├── DataLoaders │ │ │ │ └── RoleByIdDataloader.cs │ │ │ └── Services │ │ │ │ ├── IRoleService.cs │ │ │ │ ├── RoleService.cs │ │ │ │ └── RoleServiceCollectionExtensions.cs │ │ ├── Schema │ │ │ ├── SchemaServiceCollectionExtensions.cs │ │ │ └── Services │ │ │ │ ├── ISchemaValidator.cs │ │ │ │ ├── SchemaValidator.cs │ │ │ │ └── ValueHelper.cs │ │ ├── ThrowHelper.cs │ │ └── Variables │ │ │ ├── Authorization │ │ │ ├── VariableAuthorizationRule.cs │ │ │ └── VariableValueAuthorizationRule.cs │ │ │ ├── DataLoaders │ │ │ └── VariableByIdDataLoader.cs │ │ │ ├── Services │ │ │ └── VariableService.cs │ │ │ └── VariableServiceCollectionExtensions.cs │ ├── Authoring.GraphQL │ │ ├── ApiKeys │ │ │ ├── ApiKeyMutations.cs │ │ │ ├── ApiKeyQueries.cs │ │ │ └── Configuration │ │ │ │ └── ApplicationRequestExecutorBuilderExtensions.cs │ │ ├── Applications │ │ │ ├── ApplicationMutations.cs │ │ │ ├── ApplicationQueries.cs │ │ │ ├── Configuration │ │ │ │ └── ApplicationRequestExecutorBuilderExtensions.cs │ │ │ ├── Errors │ │ │ │ ├── ApplicationIdInvalid.cs │ │ │ │ ├── ApplicationNameTaken.cs │ │ │ │ ├── ApplicationNotFoundError.cs │ │ │ │ ├── ApplicationPartComponentNotFoundError.cs │ │ │ │ ├── ApplicationPartIdInvalid.cs │ │ │ │ ├── ApplicationPartNameTaken.cs │ │ │ │ ├── ApplicationPartNotFoundError.cs │ │ │ │ ├── ComponentNotFoundError.cs │ │ │ │ ├── EnvironmentNameCollisionError.cs │ │ │ │ └── EnvironmentPartNotFoundError.cs │ │ │ ├── Extensions │ │ │ │ ├── ApplicationApplicationPartExtensions.cs │ │ │ │ ├── ApplicationExtensions.cs │ │ │ │ ├── ApplicationPartComponentChangeLogExtensions.cs │ │ │ │ ├── ApplicationPartComponentExtensions.cs │ │ │ │ ├── ApplicationPartExtensions.cs │ │ │ │ └── DeployedEnvironement.cs │ │ │ └── Relay │ │ │ │ ├── ApplicationNode.cs │ │ │ │ ├── ApplicationPartComponentNode.cs │ │ │ │ └── ApplicationPartNode.cs │ │ ├── Authoring.GraphQL.csproj │ │ ├── ChangeLog │ │ │ ├── ChangeLogQueries.cs │ │ │ ├── Configuration │ │ │ │ └── ChangeLogRequestExecutorBuilderExtensions.cs │ │ │ └── Relay │ │ │ │ └── ChangeLogNode.cs │ │ ├── Components │ │ │ ├── ComponentMutations.cs │ │ │ ├── ComponentQueries.cs │ │ │ ├── Configuration │ │ │ │ └── ComponentsRequestExecutorBuilderExtensions.cs │ │ │ ├── Errors │ │ │ │ ├── ComponentNameTaken.cs │ │ │ │ ├── SchemaInvalidError.cs │ │ │ │ └── ValueSchemaViolation.cs │ │ │ ├── Extensions │ │ │ │ ├── ComponentExtensions.cs │ │ │ │ └── ComponentScopeExtensions.cs │ │ │ ├── PaginationResolverContextExtensions.cs │ │ │ ├── Relay │ │ │ │ └── ComponentNode.cs │ │ │ └── Types │ │ │ │ ├── ComponentScopeInput.cs │ │ │ │ └── ComponentScopeType.cs │ │ ├── Environment │ │ │ ├── Configuration │ │ │ │ └── EnvironmentsRequestExecutorBuilderExtensions.cs │ │ │ ├── EnvironmentMutations.cs │ │ │ ├── EnvironmentQueries.cs │ │ │ ├── Extensions │ │ │ │ └── EnvironementExtenstions.cs │ │ │ └── Relay │ │ │ │ └── EnvironmentNode.cs │ │ ├── GraphQLServiceCollectionExtensions.cs │ │ ├── Groups │ │ │ ├── Configuration │ │ │ │ └── GroupsRequestExecutorBuilderExtensions.cs │ │ │ ├── GroupMutations.cs │ │ │ ├── GroupQueries.cs │ │ │ ├── RoleScopeExtensions.cs │ │ │ └── Transport │ │ │ │ ├── ClaimRequirementInput.cs │ │ │ │ ├── IRequirementInput.cs │ │ │ │ └── RequirementInput.cs │ │ ├── InternalsVisibleTo.cs │ │ ├── PersistedQueries │ │ │ └── RelayResourceManifestQueryStorage.cs │ │ ├── Publishing │ │ │ ├── ApplicationPartPublishingExtensions.cs │ │ │ ├── ClaimVersionResult.cs │ │ │ ├── Configuration │ │ │ │ └── PublishingRequestExecutorBuilderExtensions.cs │ │ │ ├── Extensions │ │ │ │ ├── ClaimResultExtensions.cs │ │ │ │ ├── ClaimedVersionExtensions.cs │ │ │ │ └── PublishedApplicationPartExtensions.cs │ │ │ ├── LatestPublishedVersion.cs │ │ │ ├── LatestPublishedVersionResultType.cs │ │ │ ├── PublishedApplicationPartNode.cs │ │ │ ├── PublishingMutations.cs │ │ │ └── PublishingQueries.cs │ │ ├── Roles │ │ │ ├── Configuration │ │ │ │ └── RolesRequestExecutorBuilderExtensions.cs │ │ │ ├── RoleMutations.cs │ │ │ └── RoleQueries.cs │ │ ├── Shared │ │ │ ├── IUserError.cs │ │ │ ├── SchemaViolationType.cs │ │ │ ├── SdlType.cs │ │ │ └── UserError.cs │ │ ├── Tracing │ │ │ ├── ErrorLoggingDiagnosticEventListener.cs │ │ │ └── GraphQLActivityEnricher.cs │ │ ├── Variable │ │ │ ├── Configuration │ │ │ │ └── VariablesRequestExecutorBuilderExtensions.cs │ │ │ ├── Extensions │ │ │ │ ├── VariableExtensions.cs │ │ │ │ └── VariableValueExtensions.cs │ │ │ ├── Relay │ │ │ │ └── VariableNode.cs │ │ │ ├── VariableMutations.cs │ │ │ ├── VariableQueries.cs │ │ │ └── VariableValueScopeType.cs │ │ └── Viewer │ │ │ ├── Configuration │ │ │ └── RolesRequestExecutorBuilderExtensions.cs │ │ │ ├── Viewer.cs │ │ │ └── ViewerQueries.cs │ ├── Authoring.Host │ │ ├── Authoring.Host.csproj │ │ ├── Program.cs │ │ ├── Properties │ │ │ └── launchSettings.json │ │ ├── appsettings.Development.json │ │ └── appsettings.json │ ├── Authoring.Messaging │ │ ├── Authoring.Messaging.csproj │ │ ├── AuthoringServerBuilderMessagingExtensions.cs │ │ ├── CreateVaultConfigClient.cs │ │ └── ICreateVaultConfigClient.cs │ ├── Authoring.Store.Mongo │ │ ├── ApiKey │ │ │ ├── ApiKeyCollectionConfiguration.cs │ │ │ └── ApiKeyStore.cs │ │ ├── Applications │ │ │ ├── ApplicationCollectionConfiguration.cs │ │ │ └── ApplicationStore.cs │ │ ├── Authoring.Store.Mongo.csproj │ │ ├── AuthoringDbContext.cs │ │ ├── ChangeLogs │ │ │ ├── ChangeLogCollectionConfiguration.cs │ │ │ ├── ChangeLogStore.cs │ │ │ └── WellKnownChangeLogFields.cs │ │ ├── Components │ │ │ ├── ComponentCollectionConfiguration.cs │ │ │ └── ComponentStore.cs │ │ ├── Environments │ │ │ ├── EnvironmentCollectionConfiguration.cs │ │ │ └── EnvironmentStore.cs │ │ ├── Groups │ │ │ ├── GroupCollectionConfiguration.cs │ │ │ └── GroupStore.cs │ │ ├── IAuthoringDbContext.cs │ │ ├── ImmutableHashSetSerializer.cs │ │ ├── MongoStoreServiceCollectionExtensions.cs │ │ ├── Publishing │ │ │ ├── ClaimedVersionCollectionConfiguration.cs │ │ │ ├── PublishedApplicationPartCollectionConfiguration.cs │ │ │ └── PublishingStore.cs │ │ ├── Roles │ │ │ ├── RoleCollectionConfiguration.cs │ │ │ └── RoleStore.cs │ │ ├── SerializerHelpers.cs │ │ └── Variables │ │ │ ├── FilterDefinitionBuilderExtensions.cs │ │ │ ├── VariableCollectionConfiguration.cs │ │ │ ├── VariableStore.cs │ │ │ ├── VariableValueCollectionConfiguration.cs │ │ │ └── VariableValueStore.cs │ ├── Authoring.UI │ │ ├── .gitignore │ │ ├── Authoring.UI.csproj │ │ ├── EmbeddedUIMiddlewareExtensions.cs │ │ ├── EmbeddedUiMiddleware.cs │ │ └── UI │ │ │ └── .keep │ ├── Authoring │ │ ├── Authoring.csproj │ │ ├── Configuration │ │ │ ├── AuthoringApplicationBuilderExtensions.cs │ │ │ ├── AuthoringServerBuilder.cs │ │ │ ├── AuthoringServerBuilderExtensions.cs │ │ │ ├── ConfixServerBuilderExtensions.cs │ │ │ └── SessionManagementEndpoints.cs │ │ └── Seed │ │ │ ├── AdminRequirementOptions.cs │ │ │ ├── SeedExtensions.cs │ │ │ ├── SeedOptions.cs │ │ │ └── SeedWorker.cs │ ├── Common │ │ ├── Common.csproj │ │ ├── Exceptions │ │ │ └── UnauthorizedOperationException.cs │ │ ├── Settings.cs │ │ ├── TaskHelper.cs │ │ ├── Token │ │ │ ├── ITokenProvider.cs │ │ │ ├── Token.cs │ │ │ ├── TokenProvider.cs │ │ │ └── TokenProviderServiceCollectionExtensions.cs │ │ └── TransactionHelper.cs │ ├── CryptoProviders.Abstractions │ │ ├── CryptoProviderDescriptor.cs │ │ ├── CryptoProviders.Abstractions.csproj │ │ ├── Encryption │ │ │ ├── EncryptedValue.cs │ │ │ ├── IDecryptor.cs │ │ │ └── IEncryptor.cs │ │ ├── Extensions │ │ │ └── EncryptorExtensions.cs │ │ ├── ICryptoProviderDescriptor.cs │ │ ├── IEncryptionKeyProvider.cs │ │ └── Secrets │ │ │ ├── DataEncryptionKey.cs │ │ │ └── IDataEncryptionKeyRepository.cs │ ├── CryptoProviders.AzureKeyVault │ │ ├── Configuration │ │ │ ├── AzureKeyVaultOptions.cs │ │ │ └── AzureKeyVaultServiceCollectionExtensions.cs │ │ ├── CryptoProviders.AzureKeyVault.csproj │ │ ├── CryptographyClientFactory.cs │ │ ├── EncryptionKeyProvider.cs │ │ ├── ICryptographyClientFactory.cs │ │ ├── IKeyEncryptionKeyCache.cs │ │ └── KeyEncryptionKeyCache.cs │ ├── CryptoProviders.Mongo │ │ ├── CryptoDbContext.cs │ │ ├── CryptoProviders.Mongo.csproj │ │ ├── DataEncryptionKeyRepository.cs │ │ ├── ICryptoDbContext.cs │ │ ├── MongoCryptoServiceCollectionExtensions.cs │ │ └── SecretCollectionConfiguration.cs │ ├── CryptoProviders │ │ ├── CfbEncryption.cs │ │ ├── CryptoProviders.csproj │ │ ├── CypherAndIv.cs │ │ ├── EncryptionKeyCryptoProvider.cs │ │ └── InMemoryCryptoProvider.cs │ ├── Messaging.RabbitMQ │ │ ├── Messaging.RabbitMQ.csproj │ │ ├── RabbitMqMessagingBuilderExtensions.cs │ │ ├── RabbitMqMessagingUrlFactory.cs │ │ └── RabbitMqOptions.cs │ ├── Messaging.ServiceBus │ │ ├── Messaging.ServiceBus.csproj │ │ ├── ServiceBusMessagingBuilderExtensions.cs │ │ ├── ServiceBusMessagingUrlFactory.cs │ │ └── ServiceBusOptions.cs │ ├── Messaging │ │ ├── IMessagingBuilder.cs │ │ ├── IMessagingUrlFactory.cs │ │ ├── Messages │ │ │ ├── CreateVaultConfigRequest.cs │ │ │ └── CreateVaultConfigResponse.cs │ │ ├── Messaging.csproj │ │ ├── MessagingBuilder.cs │ │ ├── MessagingServiceCollectionConfigurationExtensions.cs │ │ └── RequestClient.cs │ ├── Samples.Host │ │ ├── Program.cs │ │ ├── Properties │ │ │ └── launchSettings.json │ │ ├── Samples.Host.csproj │ │ ├── appsettings.Development.json │ │ └── appsettings.json │ ├── Tooling │ │ ├── .graphqlrc.json │ │ ├── Bind.cs │ │ ├── ClaimCommand.cs │ │ ├── ClaimCommand.graphql │ │ ├── ConfixApp.cs │ │ ├── ConfixClientCommandLineBuilderExtensions.cs │ │ ├── ConfixRootCommand.cs │ │ ├── Extensions │ │ │ ├── ConsoleExtensions.cs │ │ │ └── ExitException.cs │ │ ├── Helpers │ │ │ ├── CommandLineBuilderExtensions.cs │ │ │ └── ExitCodes.cs │ │ ├── Options │ │ │ ├── ApiKeyOption.cs │ │ │ ├── AppOption.cs │ │ │ ├── EnvironmentOption.cs │ │ │ ├── JsonOption.cs │ │ │ ├── Optional.cs │ │ │ ├── PartOption.cs │ │ │ ├── Required.cs │ │ │ ├── TagOption.cs │ │ │ └── UrlOption.cs │ │ ├── Program.cs │ │ ├── Tooling.csproj │ │ ├── persisted │ │ │ └── queries.json │ │ ├── schema.extensions.graphql │ │ └── schema.graphql │ ├── Vault.Abstractions │ │ ├── Configuration │ │ │ ├── Configuration.cs │ │ │ ├── IConfigurationStore.cs │ │ │ ├── TokenPair.cs │ │ │ └── Transport │ │ │ │ ├── GetConfigurationResponse.cs │ │ │ │ ├── PutConfigurationRequest.cs │ │ │ │ ├── PutConfigurationResponse.cs │ │ │ │ ├── RefreshConfigurationRequest.cs │ │ │ │ └── RefreshConfigurationResponse.cs │ │ ├── IConfigurationService.cs │ │ ├── IVaultServerBuilder.cs │ │ ├── Vault.Abstractions.csproj │ │ └── WellKnown.cs │ ├── Vault.Authentication │ │ ├── AuthenticationExtensions.cs │ │ └── Vault.Authentication.csproj │ ├── Vault.Client │ │ ├── ConfigurationClient.cs │ │ ├── ConfigurationClientOptions.cs │ │ ├── IConfigurationClient.cs │ │ ├── QueryBuilderExtensions.cs │ │ ├── Vault.Client.csproj │ │ └── VaultClientServiceCollectionExtensions.cs │ ├── Vault.Configuration │ │ ├── .graphqlrc.json │ │ ├── ApplicationPart.cs │ │ ├── AuthoringClientFactory.cs │ │ ├── ConfixConfigurationBuilderExtensions.cs │ │ ├── JsonConfigurationFileParser.cs │ │ ├── VariableProvider.cs │ │ ├── VaulConfigurationProvider.cs │ │ ├── Vault.Configuration.csproj │ │ ├── VaultClientFactory.cs │ │ ├── VaultConfiguration.graphql │ │ ├── VaultConfigurationSource.cs │ │ ├── persisted │ │ │ └── queries.json │ │ ├── schema.extensions.graphql │ │ └── schema.graphql │ ├── Vault.Console │ │ ├── Program.cs │ │ └── Vault.Console.csproj │ ├── Vault.Core │ │ ├── Configuration │ │ │ └── ConfigurationService.cs │ │ ├── Controllers │ │ │ └── ConfigurationController.cs │ │ ├── Exceptions │ │ │ └── ConfigurationNotFoundException.cs │ │ ├── Vault.Core.csproj │ │ └── VaultCoreServiceCollectionExtensions.cs │ ├── Vault.Host │ │ ├── Program.cs │ │ ├── Properties │ │ │ └── launchSettings.json │ │ └── Vault.Host.csproj │ ├── Vault.Messaging │ │ ├── CreateVaultConfigConsumer.cs │ │ ├── Properties │ │ │ └── launchSettings.json │ │ ├── Vault.Messaging.csproj │ │ └── VaultServerBuilderMessagingExtensions.cs │ ├── Vault.Store.Mongo │ │ ├── ConfigurationCollectionConfiguration.cs │ │ ├── ConfigurationStore.cs │ │ ├── IVaultDbContext.cs │ │ ├── MongoStoreServiceCollectionExtensions.cs │ │ ├── Vault.Store.Mongo.csproj │ │ └── VaultDbContext.cs │ └── Vault │ │ ├── EndpointRouteBuilderExtensions.cs │ │ ├── Vault.csproj │ │ ├── VaultServerBuilder.cs │ │ ├── VaultServerBuilderExtensions.cs │ │ └── VaultServiceCollectionExtensions.cs └── test │ ├── Authoring.Authentication.Tests │ ├── Authoring.Authentication.Tests.csproj │ ├── GroupProviderTests.cs │ ├── RoleProviderTests.cs │ ├── SessionAccessorTests.cs │ ├── SessionTests.cs │ └── __snapshots__ │ │ ├── SessionAccessorTests.GetSession_WithValidAPIToken_ReturnsSession.snap │ │ ├── SessionAccessorTests.GetSession_WithValidUserClaims_ReturnsSession.snap │ │ ├── SessionTests.GetGrantsForScope_ForScope_MatchSnapshot_Application.snap │ │ ├── SessionTests.GetGrantsForScope_ForScope_MatchSnapshot_Component.snap │ │ ├── SessionTests.GetGrantsForScope_ForScope_MatchSnapshot_Configuration.snap │ │ ├── SessionTests.GetGrantsForScope_ForScope_MatchSnapshot_Identity.snap │ │ └── SessionTests.GetGrantsForScope_ForScope_MatchSnapshot_Variable.snap │ ├── Authoring.GraphQL.Tests │ ├── Authoring.GraphQL.Tests.csproj │ ├── RelayResourceManifestQueryStorageTests.cs │ ├── SchemaTests.cs │ └── __snapshots__ │ │ └── SchemaTests.PrintSchema.snap │ ├── Authoring.Integration.Tests │ ├── .graphqlrc.json │ ├── ApplicationTests.cs │ ├── ApplicationTests.graphql │ ├── Authoring.Integration.Tests.csproj │ ├── ComponentTests.cs │ ├── ComponentTests.graphql │ ├── Fragments.graphql │ ├── Helpers │ │ ├── AssertHelpers.cs │ │ ├── InMemoryKeyEncryptionKeyExtensions.cs │ │ ├── InMemoryMessagingBuilderExtensions.cs │ │ ├── TestExecutorBuilder.cs │ │ ├── TestHelper.cs │ │ ├── UserExtensions.cs │ │ └── Wellknown.cs │ ├── __snapshots__ │ │ ├── ComponentTests.ComponentById_ValidId_ReturnsComponent.snap │ │ ├── ComponentTests.CreateComponent_BrokenSchema_ReturnsError.snap │ │ ├── ComponentTests.CreateComponent_ReadPermission_Fail.snap │ │ ├── ComponentTests.CreateComponent_ValidInput_CreatesComponent.snap │ │ ├── ComponentTests.RenameComponent_ReadPermission_Fails.snap │ │ ├── ComponentTests.UpdateComponentSchema_InvalidSchema_Error.snap │ │ ├── ComponentTests.UpdateComponentSchema_NewValuesDontMatchSchema_Error.snap │ │ ├── ComponentTests.UpdateComponentSchema_ValidValues_UpdatesComponent.snap │ │ ├── ComponentTests.UpdateComponentSchema_WithoutWritePermission_Fails.snap │ │ ├── ComponentTests.UpdateComponentScopes_ValidScopes_UpdatesComponent.snap │ │ ├── ComponentTests.UpdateComponentScopes_WithoutWritePermission_Fails.snap │ │ ├── ComponentTests.UpdateComponentValues_NewValuesDontMatchSchema_Error.snap │ │ ├── ComponentTests.UpdateComponentValues_ValidValues_UpdatesComponent.snap │ │ └── ComponentTests.UpdateComponentValues_WithoutWritePermission_Fails.snap │ ├── schema.extensions.graphql │ └── schema.graphql │ ├── Authoring.Store.Mongo.Tests │ ├── Authoring.Store.Mongo.Tests.csproj │ ├── VariableValueStoreTests.cs │ └── __snapshots__ │ │ ├── VariableValueStoreTests.GetByKeyAsync_GetAllKeyFieldsNullVariable_ReturnsRightVariable.snap │ │ ├── VariableValueStoreTests.GetByKeyAsync_GetAllKeyFieldsSetVariable_ReturnsRightVariable.snap │ │ ├── VariableValueStoreTests.GetByKeyAsync_GetOneKeyFieldSetVariable_ReturnsRightVariable.snap │ │ ├── VariableValueStoreTests.GetByKeyAsync_GetTwoKeyFieldsSetVariable_ReturnsRightVariable.snap │ │ ├── VariableValueStoreTests.UpsertAsync_SaveNewVariableValueEmptyValues_SuccessfullyInserted.snap │ │ ├── VariableValueStoreTests.UpsertAsync_SaveNewVariableValue_SuccessfullyInserted.snap │ │ ├── VariableValueStoreTests.UpsertAsync_SaveVariableWithNewKey_NewInserted.snap │ │ └── VariableValueStoreTests.UpsertAsync_UpdateVariableByExistingKey_SuccessfullyUpdated.snap │ ├── CryptoProviders.AzureKeyVault.Tests │ ├── CryptoProviders.AzureKeyVault.Tests.csproj │ ├── KeyVaultVariableCryptoProviderTests.cs │ ├── TestContext.cs │ └── appsettings.json │ └── Directory.Build.props └── Frontend ├── .gitignore ├── .graphqlrc.json ├── .prettierignore ├── .prettierrc.json ├── README.md ├── index.html ├── package.json ├── persisted_queries.json ├── public ├── favicon.ico ├── logo192.png ├── logo512.png ├── manifest.json └── robots.txt ├── relay.config.js ├── schema-extensions └── relay-directives.graphql ├── schema.graphql ├── src ├── App.css ├── App.tsx ├── Connections.ts ├── RelayEnvironment.ts ├── __generated__ │ ├── AddComponentsToApplicationPartDialog.graphql.ts │ ├── AddComponentsToApplicationPartDialogMutation.graphql.ts │ ├── AddPartToApplicationDialogMutation.graphql.ts │ ├── ApiKeysList.graphql.ts │ ├── ApiKeysListPaginationQuery.graphql.ts │ ├── ApiKeysListQuery.graphql.ts │ ├── ApiKeysList_ApiKeyListItem.graphql.ts │ ├── ApplicationCascader.graphql.ts │ ├── ApplicationCascader_ApplicationPagination_Query.graphql.ts │ ├── ApplicationCascader_Applications.graphql.ts │ ├── ApplicationPartChangeLog.graphql.ts │ ├── ApplicationPartComponents.graphql.ts │ ├── ApplicationPartComponents_ApplicationPartComponentsDisplay.graphql.ts │ ├── ApplicationPartSectionHeader.graphql.ts │ ├── ApplicationsList.graphql.ts │ ├── ApplicationsListItem.graphql.ts │ ├── ApplicationsListItem_ApplicationPart.graphql.ts │ ├── ApplicationsListItem_Component.graphql.ts │ ├── ApplicationsListItem_DefaultListItem.graphql.ts │ ├── ApplicationsListItem_SelectedListItem.graphql.ts │ ├── ApplicationsListPaginationQuery.graphql.ts │ ├── ApplicationsListQuery.graphql.ts │ ├── ChangeComponentScopeDialog.graphql.ts │ ├── ChangeComponentScopeDialogMutation.graphql.ts │ ├── ChangeLog.graphql.ts │ ├── ChangeLog_AddComponentToApplicationPartChange.graphql.ts │ ├── ChangeLog_AddPartToApplicationChange.graphql.ts │ ├── ChangeLog_ApplicationPartComponentValuesChange.graphql.ts │ ├── ChangeLog_ComponentSchemaChange.graphql.ts │ ├── ChangeLog_ComponentValuesChange.graphql.ts │ ├── ChangeLog_CreateComponentChange.graphql.ts │ ├── ChangeLog_CreateVariableChange.graphql.ts │ ├── ChangeLog_DeleteVariableValueChange.graphql.ts │ ├── ChangeLog_PublishedApplicationPartChange.graphql.ts │ ├── ChangeLog_RemoveComponentChange.graphql.ts │ ├── ChangeLog_RemoveComponentFromApplicationPartChange.graphql.ts │ ├── ChangeLog_RemovePartFromApplicationChange.graphql.ts │ ├── ChangeLog_RenameApplicationChange.graphql.ts │ ├── ChangeLog_RenameApplicationPartChange.graphql.ts │ ├── ChangeLog_RenameComponentChange.graphql.ts │ ├── ChangeLog_RenameVariableChange.graphql.ts │ ├── ChangeLog_VariableValueChange.graphql.ts │ ├── CompareApplicationPartComponentVersions_Query.graphql.ts │ ├── ComponentsList.graphql.ts │ ├── ComponentsListPaginationQuery.graphql.ts │ ├── ComponentsListQuery.graphql.ts │ ├── ComponentsSelectQuery.graphql.ts │ ├── Connections_applications.graphql.ts │ ├── Connections_components.graphql.ts │ ├── DeployedEnvironmentsOverview.graphql.ts │ ├── EditApiKeyQuery.graphql.ts │ ├── EditApiKey_Form.graphql.ts │ ├── EditApiKey_Header.graphql.ts │ ├── EditApiKey_RoleScopeSection.graphql.ts │ ├── EditApiKey_UpdateApiKeyRoles_Mutation.graphql.ts │ ├── EditApplication.graphql.ts │ ├── EditApplicationPart.graphql.ts │ ├── EditApplicationPartComponent.graphql.ts │ ├── EditApplicationPartComponent_ApplicationPartComponentChangeLog.graphql.ts │ ├── EditApplicationPartComponent_EditConfiguration.graphql.ts │ ├── EditApplicationPartComponent_GetById_Query.graphql.ts │ ├── EditApplicationPartComponent_UpdateComponentValues_Mutation.graphql.ts │ ├── EditApplicationPartQuery.graphql.ts │ ├── EditApplicationPart_DeployedEnvironments.graphql.ts │ ├── EditApplicationPart_Variable.graphql.ts │ ├── EditApplication_ApplicationChangeLog.graphql.ts │ ├── EditApplication_ApplicationParts.graphql.ts │ ├── EditApplication_ApplicationPartsDisplay.graphql.ts │ ├── EditApplication_Query.graphql.ts │ ├── EditApplication_RefetchQuery.graphql.ts │ ├── EditApplication_Variables.graphql.ts │ ├── EditComponent.graphql.ts │ ├── EditComponentQuery.graphql.ts │ ├── EditComponentUpdateMutation.graphql.ts │ ├── EditComponent_AvailableIn.graphql.ts │ ├── EditComponent_AvailableIn_Query.graphql.ts │ ├── EditComponent_ComponentChangeLog.graphql.ts │ ├── EditComponent_EditComponentForm.graphql.ts │ ├── EditEnvironmentQuery.graphql.ts │ ├── EditEnvironment_EditEnvironmentForm.graphql.ts │ ├── EditEnvironment_Header.graphql.ts │ ├── EditEnvironment_IsDeveloperAccessAllowedFrom.graphql.ts │ ├── EditEnvironment_ParentEnvironement.graphql.ts │ ├── EditGroupQuery.graphql.ts │ ├── EditGroup_Form.graphql.ts │ ├── EditGroup_Header.graphql.ts │ ├── EditGroup_RequirementsSection.graphql.ts │ ├── EditGroup_RoleScopeSection.graphql.ts │ ├── EditGroup_UpdateGroupRequirements_Mutation.graphql.ts │ ├── EditGroup_UpdateGroupRoles_Mutation.graphql.ts │ ├── EditRoleForm_ChangeRolePermissions_Mutation.graphql.ts │ ├── EditRoleQuery.graphql.ts │ ├── EditRole_Form.graphql.ts │ ├── EditRole_Header.graphql.ts │ ├── EditVariable.graphql.ts │ ├── EditVariableQuery.graphql.ts │ ├── EditVariable_ApplicationPartSelector.graphql.ts │ ├── EditVariable_ApplicationSelector.graphql.ts │ ├── EditVariable_ApplicationSelector_Query.graphql.ts │ ├── EditVariable_EditVariableForm.graphql.ts │ ├── EditVariable_VariableChangeLog.graphql.ts │ ├── EnvironmentsList.graphql.ts │ ├── EnvironmentsListPaginationQuery.graphql.ts │ ├── EnvironmentsListQuery.graphql.ts │ ├── EnvironmentsList_EnvironmentListItem.graphql.ts │ ├── EnvironmentsSelectQuery.graphql.ts │ ├── ExplorerTreePaginationQuery.graphql.ts │ ├── ExplorerTreeQuery.graphql.ts │ ├── ExplorerTree_Application.graphql.ts │ ├── ExplorerTree_ApplicationDetails.graphql.ts │ ├── ExplorerTree_ApplicationPart.graphql.ts │ ├── ExplorerTree_Applications.graphql.ts │ ├── GroupsList.graphql.ts │ ├── GroupsListPaginationQuery.graphql.ts │ ├── GroupsListQuery.graphql.ts │ ├── GroupsList_ListItem.graphql.ts │ ├── NewApiKeyMutation.graphql.ts │ ├── NewApplicationMutation.graphql.ts │ ├── NewComponentMutation.graphql.ts │ ├── NewComponent_Query.graphql.ts │ ├── NewEnvironmentMutation.graphql.ts │ ├── NewGroupMutation.graphql.ts │ ├── NewRoleMutation.graphql.ts │ ├── NewVariableMutation.graphql.ts │ ├── PublishApplicationPartDialogMutation.graphql.ts │ ├── PublishedApplicationParts.graphql.ts │ ├── PublishedApplicationPartsQuery.graphql.ts │ ├── RemoveApiKeyDialogMutation.graphql.ts │ ├── RemoveComponentFromApplicationPartDialogMutation.graphql.ts │ ├── RemoveEnvironmentDialogMutation.graphql.ts │ ├── RemoveGroupDialogMutation.graphql.ts │ ├── RemovePartFromApplicationDialogMutation.graphql.ts │ ├── RemoveRoleDialogMutation.graphql.ts │ ├── RenameApplicationDialogMutation.graphql.ts │ ├── RenameApplicationPartDialogMutation.graphql.ts │ ├── RenameComponentDialogMutation.graphql.ts │ ├── RenameEnvironmentDialogMutation.graphql.ts │ ├── RenameGroupDialogMutation.graphql.ts │ ├── RenameRoleDialogMutation.graphql.ts │ ├── RenameVariableDialogMutation.graphql.ts │ ├── RolesList.graphql.ts │ ├── RolesListPaginationQuery.graphql.ts │ ├── RolesListQuery.graphql.ts │ ├── RolesList_RoleListItem.graphql.ts │ ├── RolesSelectQuery.graphql.ts │ ├── SaveDeveloperAccessButtonMutation.graphql.ts │ ├── SetParentEnvironmentDialogMutation.graphql.ts │ ├── UserContextProviderQuery.graphql.ts │ ├── VariableEditorDeleteVariableValueMutation.graphql.ts │ ├── VariableEditorQuery.graphql.ts │ ├── VariableEditorSaveVariableMutation.graphql.ts │ ├── VariableEditor_useEnvironments.graphql.ts │ ├── VariableEditor_useEnvironmentsPaginationQuery.graphql.ts │ ├── VariableSelectQuery.graphql.ts │ ├── VariableValueList.graphql.ts │ ├── VariablesList.graphql.ts │ ├── VariablesListPaginationQuery.graphql.ts │ ├── VariablesListQuery.graphql.ts │ └── VariablesList_ListItem.graphql.ts ├── applications │ ├── Applications.tsx │ ├── ApplicationsList.tsx │ ├── CompareApplicationPartComponentVersions.tsx │ ├── EditApplication.tsx │ ├── EditApplicationPart.tsx │ ├── EditApplicationPartComponent.tsx │ ├── NewApplication.tsx │ ├── components │ │ ├── ApplicationCascader.tsx │ │ ├── ApplicationPartChangeLog.tsx │ │ ├── ApplicationPartComponents.tsx │ │ ├── ApplicationPartSectionHeader.tsx │ │ ├── ComponentDiffEditor.tsx │ │ ├── DeployedEnvironmentsOverview.tsx │ │ ├── PublishedApplicationParts.tsx │ │ ├── SchemaComponentEditor.tsx │ │ └── buildJsonSchema.tsx │ ├── dialogs │ │ ├── AddComponentsToApplicationPartDialog.tsx │ │ ├── AddPartToApplicationDialog.tsx │ │ ├── PublishApplicationPartDialog.tsx │ │ ├── RemoveComponentFromApplicationPartDialog.tsx │ │ ├── RemovePartFromApplicationDialog.tsx │ │ ├── RenameApplicationDialog.tsx │ │ └── RenameApplicationPartDialog.tsx │ └── validation │ │ └── applicationSchema.tsx ├── components │ ├── Components.tsx │ ├── ComponentsList.tsx │ ├── EditComponent.tsx │ ├── NewComponent.tsx │ ├── componentSchema.tsx │ └── controls │ │ ├── ComponentsSelect.tsx │ │ └── dialogs │ │ ├── ChangeComponentScopeDialog.tsx │ │ └── RenameComponentDialog.tsx ├── config.ts ├── environment │ ├── EditEnvironment.tsx │ ├── Environments.tsx │ ├── EnvironmentsList.tsx │ ├── NewEnvironment.tsx │ ├── controls │ │ ├── EnvironmentsSelect.tsx │ │ ├── buttons │ │ │ └── SaveDeveloperAccessButton.tsx │ │ └── dialogs │ │ │ ├── RemoveEnvironmentDialog.tsx │ │ │ ├── RenameEnvironmentDialog.tsx │ │ │ └── SetParentEnvironmentDialog.tsx │ └── environmentSchema.tsx ├── explorer │ ├── Explorer.tsx │ └── ExplorerTree.tsx ├── fetchGraphQL.ts ├── icons │ └── icons.tsx ├── images │ ├── logo.png │ └── logo_small.png ├── index.css ├── index.tsx ├── logo.svg ├── react-app-env.d.ts ├── reportWebVitals.ts ├── routes.tsx ├── settings │ ├── Settings.tsx │ ├── apiKeys │ │ ├── ApiKeys.tsx │ │ ├── ApiKeysList.tsx │ │ ├── EditApiKey.tsx │ │ ├── NewApiKey.tsx │ │ └── controls │ │ │ └── dialogs │ │ │ └── RemoveApiKeyDialog.tsx │ ├── groups │ │ ├── EditGroup.tsx │ │ ├── Groups.tsx │ │ ├── GroupsList.tsx │ │ ├── NewGroup.tsx │ │ ├── controls │ │ │ └── dialogs │ │ │ │ ├── RemoveGroupDialog.tsx │ │ │ │ └── RenameGroupDialog.tsx │ │ └── groupSchema.tsx │ ├── roles │ │ ├── EditRole.tsx │ │ ├── NewRole.tsx │ │ ├── Roles.tsx │ │ ├── RolesList.tsx │ │ ├── controls │ │ │ ├── RolesSelect.tsx │ │ │ ├── dialogs │ │ │ │ ├── RemoveRoleDialog.tsx │ │ │ │ └── RenameRoleDialog.tsx │ │ │ └── forms │ │ │ │ └── PermissionForm.tsx │ │ └── roleSchema.tsx │ └── shared │ │ └── RoleScopeEdit.tsx ├── setupTests.ts ├── shared │ ├── ButtonBar.tsx │ ├── ChangeLog.tsx │ ├── ColorTag.tsx │ ├── CommitErrors.tsx │ ├── DefaultSuspense.tsx │ ├── DetailView.tsx │ ├── EditablePageHeader.tsx │ ├── FormField.tsx │ ├── FullSizeBox.tsx │ ├── InfiniteScrollList.tsx │ ├── InlinePage.tsx │ ├── Page.tsx │ ├── PaginatedListWithSearch.tsx │ ├── QueryOptions.ts │ ├── SearchBar.tsx │ ├── SectionHeader.tsx │ ├── TabRow.tsx │ ├── UseFormik.ts │ ├── UserContext.tsx │ ├── Wrapper.tsx │ ├── chunkBy.ts │ ├── colors.ts │ ├── debounce.ts │ ├── distinct.ts │ ├── editor │ │ ├── ComponentEditor.tsx │ │ ├── SchemaEditor.tsx │ │ └── defaultEditorOptions.tsx │ ├── ensureDate.ts │ ├── formatDate.ts │ ├── formatGraphQL.tsx │ ├── groupBy.ts │ ├── hacks.ts │ ├── hashCode.ts │ ├── id.tsx │ ├── noop.ts │ ├── pipeCommitFn.tsx │ ├── useCommitForm.ts │ ├── useConnectionId.ts │ ├── useDefaultRefetch.ts │ ├── useDelay.ts │ ├── useEventListener.ts │ ├── useGoTo.ts │ ├── useHandler.ts │ ├── useIntersectionObserver.ts │ ├── useLoadNextChain.ts │ ├── useMultiplexer.ts │ ├── useQuery.ts │ ├── useTabSwitcher.ts │ ├── useToggle.ts │ └── withSilentSuspense.tsx ├── types │ ├── babel-plugin-relay.d.ts │ └── react-app-env.d.ts └── variables │ ├── EditVariable.tsx │ ├── NewVariable.tsx │ ├── Variables.tsx │ ├── VariablesList.tsx │ ├── controls │ ├── VariableEditor.tsx │ ├── VariableSelect.tsx │ ├── VariableValueList.tsx │ └── dialogs │ │ └── RenameVariableDialog.tsx │ └── variableSchema.tsx ├── tsconfig.json ├── vite.config.ts └── yarn.lock /.config/dotnet-tools.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 1, 3 | "isRoot": true, 4 | "tools": { 5 | "strawberryshake.tools": { 6 | "version": "13.0.5", 7 | "commands": [ 8 | "dotnet-graphql" 9 | ] 10 | }, 11 | "dotnet-sonarscanner": { 12 | "version": "4.8.0", 13 | "commands": [ 14 | "dotnet-sonarscanner" 15 | ] 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | 5 | --- 6 | 7 | **Describe the bug** 8 | A clear and concise description of what the bug is. 9 | 10 | **To Reproduce** 11 | Steps to reproduce the behavior: 12 | 1. Go to '...' 13 | 2. Click on '....' 14 | 3. Scroll down to '....' 15 | 4. See error 16 | 17 | **Expected behavior** 18 | A clear and concise description of what you expected to happen. 19 | 20 | **Desktop (please complete the following information):** 21 | - OS: [e.g. iOS] 22 | - Version [e.g. 22] 23 | 24 | **Additional context** 25 | Add any other context about the problem here. 26 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/custom.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Custom issue template 3 | about: Describe this issue template's purpose here. 4 | 5 | --- -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | 5 | --- 6 | 7 | **Is your feature request related to a problem? Please describe.** 8 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 9 | 10 | **Describe the solution you'd like** 11 | A clear and concise description of what you want to happen. 12 | 13 | **Describe alternatives you've considered** 14 | A clear and concise description of any alternative solutions or features you've considered. 15 | 16 | **Additional context** 17 | Add any other context or screenshots about the feature request here. 18 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | Summary of the changes (Less than 80 chars) 2 | 3 | - Detail 1 4 | - Detail 2 5 | 6 | Addresses #bugnumber (in this specific format) 7 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "hediet.vscode-drawio" 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Work in Progress 2 | 3 | ## Getting Started 4 | 5 | ## Features 6 | 7 | ## Community 8 | 9 | This project has adopted the code of conduct defined by the [Contributor Covenant](https://contributor-covenant.org/) 10 | to clarify expected behavior in our community. For more information, see the [Swiss Life OSS Code of Conduct](https://swisslife-oss.github.io/coc). 11 | 12 | ### Architecture 13 | ![alt text](./docs/arch.drawio.svg) 14 | -------------------------------------------------------------------------------- /build-ui.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | rm -rf ./src/Backend/src/Authoring.UI/UI/ 3 | yarn --cwd ./src/Frontend 4 | yarn --cwd ./src/Frontend build 5 | cp -R ./src/Frontend/build/* ./src/Backend/src/Authoring.UI/UI 6 | touch ./src/Backend/src/Authoring.UI/UI/.keep 7 | -------------------------------------------------------------------------------- /global.json: -------------------------------------------------------------------------------- 1 | { 2 | "sdk": { 3 | "version": "7.0.203" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /nuget.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/Backend/Directory.Build.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | $([MSBuild]::GetPathOfFileAbove('Directory.Build.props', '$(MSBuildThisFileDirectory)../')) 5 | 6 | 7 | 8 | 9 | net7.0 10 | ConfiX 11 | enable 12 | preview 13 | enable 14 | true 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/Backend/src/Authentication/ApiKey/ApiKey.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Immutable; 2 | using Confix.Authentication.Authorization; 3 | using HotChocolate; 4 | using HotChocolate.Types.Relay; 5 | 6 | namespace Confix.Authentication.ApiKey; 7 | 8 | public record ApiKey( 9 | [property: ID] Guid Id, 10 | string Name, 11 | [property: GraphQLIgnore] string KeyHash, 12 | [property: GraphQLIgnore] string KeyPrefix, 13 | ImmutableHashSet Roles) 14 | { 15 | private const int PrefixLength = 10; 16 | public static readonly int KeyLength = 64; 17 | 18 | 19 | public static string GetPrefix(string key) 20 | { 21 | if (key.Length < PrefixLength) 22 | { 23 | throw new ArgumentException("Provided key is too short", nameof(key)); 24 | } 25 | 26 | return key[..PrefixLength]; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/Backend/src/Authentication/ApiKey/ApiKeyAuthenticationSucceededContext.cs: -------------------------------------------------------------------------------- 1 | using System.Security.Claims; 2 | using Microsoft.AspNetCore.Authentication; 3 | using Microsoft.AspNetCore.Http; 4 | 5 | namespace Confix.Authentication.ApiKey; 6 | 7 | public class ApiKeyAuthenticationSucceededContext : ResultContext 8 | { 9 | public ApiKeyAuthenticationSucceededContext( 10 | HttpContext context, 11 | AuthenticationScheme scheme, 12 | ApiKeyOptions options, 13 | ClaimsPrincipal principal) 14 | : base(context, scheme, options) 15 | { 16 | Principal = principal; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/Backend/src/Authentication/ApiKey/ApiKeyDefaults.cs: -------------------------------------------------------------------------------- 1 | namespace Confix.Authentication.ApiKey; 2 | 3 | public static class ApiKeyDefaults 4 | { 5 | /// 6 | /// Default value for AuthenticationScheme 7 | /// 8 | public const string AuthenticationScheme = "ApiKey"; 9 | 10 | public const string HeaderName = "confix-api-key"; 11 | 12 | public const string ApiKeyIdSerializationType = "N"; 13 | 14 | public const string ApiKeyClaim = "api-key-id"; 15 | } 16 | -------------------------------------------------------------------------------- /src/Backend/src/Authentication/ApiKey/ApiKeyExtensions.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Authentication; 2 | 3 | namespace Confix.Authentication.ApiKey; 4 | 5 | public static class ApiKeyExtensions 6 | { 7 | public static AuthenticationBuilder AddApiKey(this AuthenticationBuilder builder) 8 | { 9 | return builder.AddScheme( 10 | ApiKeyDefaults.AuthenticationScheme, 11 | "Api Key", 12 | null); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/Backend/src/Authentication/ApiKey/ApiKeyOptions.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Authentication; 2 | 3 | namespace Confix.Authentication.ApiKey; 4 | 5 | public class ApiKeyOptions : AuthenticationSchemeOptions 6 | { 7 | } 8 | -------------------------------------------------------------------------------- /src/Backend/src/Authentication/ApiKey/IApiKeyProvider.cs: -------------------------------------------------------------------------------- 1 | namespace Confix.Authentication.ApiKey; 2 | 3 | public interface IApiKeyProvider 4 | { 5 | /// 6 | /// Validates the key and provides with and instance of . 7 | /// 8 | /// 9 | /// 10 | /// 11 | Task ProvideAsync(string key, CancellationToken cancellationToken); 12 | 13 | Task GetByIdAsync(Guid id, CancellationToken cancellationToken); 14 | } 15 | -------------------------------------------------------------------------------- /src/Backend/src/Authentication/Authorization/ClaimRequirement.cs: -------------------------------------------------------------------------------- 1 | using System.Security.Claims; 2 | 3 | namespace Confix.Authentication.Authorization; 4 | 5 | public record ClaimRequirement(string Type, string Value) : Requirement 6 | { 7 | public override bool Validate(ClaimsPrincipal principal) 8 | { 9 | return principal.HasClaim(Type, Value); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/Backend/src/Authentication/Authorization/Extensions/AuthorizationRuleServiceCollectionExtensions.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.DependencyInjection; 2 | using Microsoft.Extensions.DependencyInjection.Extensions; 3 | 4 | namespace Confix.Authentication.Authorization; 5 | 6 | public static class AuthorizationRuleServiceCollectionExtensions 7 | { 8 | public static IServiceCollection AddAuthorizationRule( 9 | this IServiceCollection services) where TRule : class, IAuthorizationRule 10 | { 11 | services.TryAddScoped(); 12 | services.AddScoped(); 13 | services.AddScoped, TRule>(sp => sp.GetRequiredService()); 14 | 15 | return services; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/Backend/src/Authentication/Authorization/Extensions/SessionAccessorExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace Confix.Authentication.Authorization; 2 | 3 | public static class SessionAccessorExtensions 4 | { 5 | public static async Task IsAuthenticated( 6 | this ISessionAccessor accessor, 7 | CancellationToken cancellationToken) 8 | { 9 | var session = await accessor.GetSession(cancellationToken); 10 | 11 | return session is not null; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/Backend/src/Authentication/Authorization/Group.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Immutable; 2 | using HotChocolate.Types.Relay; 3 | 4 | namespace Confix.Authentication.Authorization; 5 | 6 | public record Group( 7 | [property: ID] Guid Id, 8 | string Name, 9 | ImmutableHashSet Requirements, 10 | ImmutableHashSet Roles); 11 | -------------------------------------------------------------------------------- /src/Backend/src/Authentication/Authorization/IAuthorizationRule.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics.CodeAnalysis; 2 | 3 | namespace Confix.Authentication.Authorization; 4 | 5 | public interface IAuthorizationRule 6 | { 7 | ValueTask IsAuthorizedFromAsync( 8 | TOther? resource, 9 | Permissions permissions, 10 | CancellationToken cancellationToken); 11 | 12 | ValueTask IsAuthorizedAsync( 13 | [NotNullWhen(true)]T? resource, 14 | Permissions permissions, 15 | CancellationToken cancellationToken); 16 | } 17 | -------------------------------------------------------------------------------- /src/Backend/src/Authentication/Authorization/IAuthorizationService.cs: -------------------------------------------------------------------------------- 1 | namespace Confix.Authentication.Authorization; 2 | 3 | public interface IAuthorizationService 4 | { 5 | IAuthorizationRule RuleFor(); 6 | 7 | ValueTask IsAuthenticatedAsync(CancellationToken cancellationToken); 8 | 9 | ValueTask EnsureAuthenticated(CancellationToken cancellationToken); 10 | } 11 | -------------------------------------------------------------------------------- /src/Backend/src/Authentication/Authorization/ISession.cs: -------------------------------------------------------------------------------- 1 | namespace Confix.Authentication.Authorization; 2 | 3 | public interface ISession 4 | { 5 | IReadOnlyList Groups { get; } 6 | 7 | UserInfo UserInfo { get; } 8 | 9 | IReadOnlySet GetNamespacesWithAccess(Scope scope, Permissions permission); 10 | IReadOnlySet GetGrantsForScope(Scope scope); 11 | bool HasPermission(string @namespace, Scope scope, Permissions permission); 12 | } 13 | 14 | public readonly record struct Grant(string Namespace, Scope Scope, Permissions Permission); 15 | -------------------------------------------------------------------------------- /src/Backend/src/Authentication/Authorization/ISessionAccessor.cs: -------------------------------------------------------------------------------- 1 | namespace Confix.Authentication.Authorization; 2 | 3 | public interface ISessionAccessor 4 | { 5 | ValueTask GetSession(CancellationToken cancellationToken); 6 | } 7 | -------------------------------------------------------------------------------- /src/Backend/src/Authentication/Authorization/Permission.cs: -------------------------------------------------------------------------------- 1 | namespace Confix.Authentication.Authorization; 2 | 3 | public record Permission(Scope Scope, Permissions Permissions); 4 | -------------------------------------------------------------------------------- /src/Backend/src/Authentication/Authorization/Permissions.cs: -------------------------------------------------------------------------------- 1 | namespace Confix.Authentication.Authorization; 2 | 3 | [Flags] 4 | public enum Permissions 5 | { 6 | Read = 1, 7 | Write = 2, 8 | Claim = 4, 9 | Publish = 8, 10 | Decrypt = 16 11 | } 12 | -------------------------------------------------------------------------------- /src/Backend/src/Authentication/Authorization/Policies.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Authorization; 2 | 3 | namespace Confix.Authentication.Authorization; 4 | 5 | public static class Policies 6 | { 7 | public static class Names 8 | { 9 | public const string VaultManage = nameof(VaultManage); 10 | public const string ConfigurationClaim = nameof(ConfigurationClaim); 11 | } 12 | 13 | public static readonly AuthorizationPolicy VaultManagePolicy = new AuthorizationPolicyBuilder() 14 | .RequireClaim("scope", Scopes.VaultManage) 15 | .Build(); 16 | 17 | public static readonly AuthorizationPolicy ConfigurationClaimPolicy = 18 | new AuthorizationPolicyBuilder() 19 | .RequireClaim("scope", Scopes.ConfigurationClaim) 20 | .Build(); 21 | } 22 | -------------------------------------------------------------------------------- /src/Backend/src/Authentication/Authorization/Providers/IGroupProvider.cs: -------------------------------------------------------------------------------- 1 | using System.Security.Claims; 2 | 3 | namespace Confix.Authentication.Authorization; 4 | 5 | internal interface IGroupProvider 6 | { 7 | ValueTask> GetGroupsOfUserAsync( 8 | ClaimsPrincipal principal, 9 | CancellationToken cancellationToken); 10 | } 11 | -------------------------------------------------------------------------------- /src/Backend/src/Authentication/Authorization/Providers/IRoleProvider.cs: -------------------------------------------------------------------------------- 1 | namespace Confix.Authentication.Authorization; 2 | 3 | internal interface IRoleProvider 4 | { 5 | ValueTask> GetRoleMapAsync(CancellationToken cancellationToken); 6 | } 7 | -------------------------------------------------------------------------------- /src/Backend/src/Authentication/Authorization/Repositories/IGroupStore.cs: -------------------------------------------------------------------------------- 1 | namespace Confix.Authentication.Authorization; 2 | 3 | public interface IGroupStore 4 | { 5 | Task> GetAllAsync(CancellationToken cancellationToken); 6 | 7 | Task GetByIdAsync(Guid id, CancellationToken cancellationToken); 8 | 9 | Task UpsertAsync(Group group, CancellationToken cancellationToken); 10 | 11 | Task DeleteByIdAsync(Guid id, CancellationToken cancellationToken); 12 | 13 | IQueryable Query(); 14 | 15 | Task> GetByIdsAsync( 16 | IEnumerable ids, 17 | CancellationToken cancellationToken); 18 | } 19 | -------------------------------------------------------------------------------- /src/Backend/src/Authentication/Authorization/Repositories/IRoleStore.cs: -------------------------------------------------------------------------------- 1 | namespace Confix.Authentication.Authorization; 2 | 3 | public interface IRoleStore 4 | { 5 | Task> GetAllAsync(CancellationToken cancellationToken); 6 | 7 | Task GetByIdAsync(Guid id, CancellationToken cancellationToken); 8 | 9 | Task> GetByIdsAsync( 10 | IEnumerable ids, 11 | CancellationToken cancellationToken); 12 | 13 | Task UpsertAsync(Role group, CancellationToken cancellationToken); 14 | 15 | Task DeleteByIdAsync(Guid id, CancellationToken cancellationToken); 16 | 17 | IQueryable Query(); 18 | } 19 | -------------------------------------------------------------------------------- /src/Backend/src/Authentication/Authorization/Requirement.cs: -------------------------------------------------------------------------------- 1 | using System.Security.Claims; 2 | using HotChocolate; 3 | using HotChocolate.Types; 4 | 5 | namespace Confix.Authentication.Authorization; 6 | 7 | [UnionType] 8 | public abstract record Requirement 9 | { 10 | [GraphQLIgnore] 11 | public abstract bool Validate(ClaimsPrincipal principal); 12 | } 13 | -------------------------------------------------------------------------------- /src/Backend/src/Authentication/Authorization/Role.cs: -------------------------------------------------------------------------------- 1 | using HotChocolate.Types.Relay; 2 | 3 | namespace Confix.Authentication.Authorization; 4 | 5 | public record Role([property: ID] Guid Id, string Name, IReadOnlyList Permissions); 6 | -------------------------------------------------------------------------------- /src/Backend/src/Authentication/Authorization/RoleScope.cs: -------------------------------------------------------------------------------- 1 | using HotChocolate.Types.Relay; 2 | 3 | namespace Confix.Authentication.Authorization; 4 | 5 | public record RoleScope( 6 | string Namespace, 7 | [property: ID(nameof(Role))] IReadOnlyCollection RoleIds); 8 | -------------------------------------------------------------------------------- /src/Backend/src/Authentication/Authorization/Scope.cs: -------------------------------------------------------------------------------- 1 | namespace Confix.Authentication.Authorization; 2 | 3 | public enum Scope 4 | { 5 | Configuration, 6 | Application, 7 | Variable, 8 | Identity, 9 | Component, 10 | Environment 11 | } 12 | -------------------------------------------------------------------------------- /src/Backend/src/Authentication/Authorization/Scopes.cs: -------------------------------------------------------------------------------- 1 | namespace Confix.Authentication.Authorization; 2 | 3 | public static class Scopes 4 | { 5 | public const string VaultManage = "confix.vault.manage"; 6 | public const string ConfigurationClaim = "confix.configuration.claim"; 7 | } 8 | -------------------------------------------------------------------------------- /src/Backend/src/Authentication/Authorization/UserInfo.cs: -------------------------------------------------------------------------------- 1 | namespace Confix.Authentication.Authorization; 2 | 3 | public record UserInfo( 4 | string Id, 5 | string? Name, 6 | string? Email 7 | ); 8 | -------------------------------------------------------------------------------- /src/Backend/src/Authentication/Authorization/WellKnownNamespaces.cs: -------------------------------------------------------------------------------- 1 | namespace Confix.Authentication.Authorization; 2 | 3 | public static class WellKnownNamespaces 4 | { 5 | public const string Global = nameof(Global); 6 | } 7 | -------------------------------------------------------------------------------- /src/Backend/src/Authentication/ClientCredentials/ClientCredentialsClientOptions.cs: -------------------------------------------------------------------------------- 1 | namespace Confix.Authentication; 2 | 3 | public class ClientCredentialsClientOptions 4 | { 5 | public string ClientId { get; set; } = string.Empty; 6 | public string Secret { get; set; } = string.Empty; 7 | public string Scopes { get; set; } = string.Empty; 8 | public string Authority { get; set; } = string.Empty; 9 | public string Url { get; set; } = string.Empty; 10 | } 11 | -------------------------------------------------------------------------------- /src/Backend/src/Authentication/ClientCredentials/IClientCredentialCache.cs: -------------------------------------------------------------------------------- 1 | namespace Confix.Authentication; 2 | 3 | public interface IClientCredentialCache 4 | { 5 | ValueTask GetAccessTokenAsync( 6 | string authority, 7 | string clientId, 8 | string clientSecret, 9 | string scopes, 10 | CancellationToken cancellationToken); 11 | } 12 | -------------------------------------------------------------------------------- /src/Backend/src/Authentication/Extensions/StringExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace Confix.Authentication; 2 | 3 | internal static class StringExtensions 4 | { 5 | public static string? ValueOrNull(this string? str) 6 | { 7 | if (string.IsNullOrWhiteSpace(str)) 8 | { 9 | return null; 10 | } 11 | 12 | return str; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/Backend/src/Authentication/InternalsVisibleTo.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.CompilerServices; 2 | 3 | [assembly: InternalsVisibleTo("Confix.Authoring.Authentication.Tests")] 4 | [assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")] 5 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.Abstractions/ApiKeys/DataLoaders/IApiKeyById.cs: -------------------------------------------------------------------------------- 1 | using Confix.Authentication.ApiKey; 2 | using GreenDonut; 3 | 4 | namespace Confix.Authoring.ApiKeys.DataLoaders; 5 | 6 | public interface IApiKeyByIdDataLoader : IDataLoader 7 | { 8 | } 9 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.Abstractions/ApiKeys/Models/ApiKeyWithSecret.cs: -------------------------------------------------------------------------------- 1 | using Confix.Authentication.ApiKey; 2 | 3 | namespace Confix.Authoring.ApiKeys; 4 | 5 | public record ApiKeyWithSecret(ApiKey Key, string Secret); 6 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.Abstractions/ApiKeys/Stores/IApiKeyStore.cs: -------------------------------------------------------------------------------- 1 | using Confix.Authentication.ApiKey; 2 | 3 | namespace Confix.Authoring.ApiKeys; 4 | 5 | public interface IApiKeyStore 6 | { 7 | Task> FindPossibleKeysByKeyPrefixAsync( 8 | string key, 9 | CancellationToken cancellationToken); 10 | 11 | Task> FindKeysByIdsAsync( 12 | IEnumerable ids, 13 | CancellationToken cancellationToken); 14 | 15 | Task FindKeyByIdAsync(Guid id, CancellationToken cancellationToken); 16 | 17 | Task DeleteApiKeyByIdAsync( 18 | Guid apiKeyId, 19 | CancellationToken cancellationToken); 20 | 21 | IQueryable Query(); 22 | 23 | Task UpsetApiKeyAsync(ApiKey key, CancellationToken cancellationToken); 24 | } 25 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.Abstractions/Applications/Changes/CreateApplicationChange.cs: -------------------------------------------------------------------------------- 1 | using HotChocolate; 2 | using HotChocolate.Types; 3 | 4 | namespace Confix.Authoring.Store; 5 | 6 | public sealed record CreateApplicationChange : IApplicationChange 7 | { 8 | public CreateApplicationChange( 9 | Guid applicationId, 10 | int applicationVersion, 11 | Application application) 12 | { 13 | ApplicationId = applicationId; 14 | ApplicationVersion = applicationVersion; 15 | Application = application; 16 | } 17 | 18 | public Application Application { get; init; } 19 | 20 | public string Kind => nameof(CreateApplicationChange); 21 | 22 | [GraphQLName("application")] 23 | [UseDataLoader(typeof(IApplicationDataLoader))] 24 | public Guid ApplicationId { get; init; } 25 | 26 | public int ApplicationVersion { get; init; } 27 | } 28 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.Abstractions/Applications/Changes/IApplicationChange.cs: -------------------------------------------------------------------------------- 1 | using HotChocolate; 2 | 3 | namespace Confix.Authoring.Store; 4 | 5 | public interface IApplicationChange : IChange 6 | { 7 | [GraphQLType(typeof(Application))] 8 | [GraphQLName("application")] 9 | Guid ApplicationId { get; } 10 | 11 | int ApplicationVersion { get; } 12 | } 13 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.Abstractions/Applications/Changes/IApplicationPartChange.cs: -------------------------------------------------------------------------------- 1 | using HotChocolate; 2 | 3 | namespace Confix.Authoring.Store; 4 | 5 | public interface IApplicationPartChange : IApplicationChange 6 | { 7 | [GraphQLType(typeof(ApplicationPart))] 8 | [GraphQLName("part")] 9 | Guid PartId { get; } 10 | 11 | int PartVersion { get; } 12 | } 13 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.Abstractions/Applications/Changes/IApplicationPartComponentChange.cs: -------------------------------------------------------------------------------- 1 | using HotChocolate; 2 | 3 | namespace Confix.Authoring.Store; 4 | 5 | public interface IApplicationPartComponentChange : IApplicationPartChange 6 | { 7 | [GraphQLType(typeof(ApplicationPartComponent))] 8 | [GraphQLName("partComponent")] 9 | Guid PartComponentId { get; } 10 | 11 | int PartComponentVersion { get; } 12 | } 13 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.Abstractions/Applications/Changes/RenameApplicationChange.cs: -------------------------------------------------------------------------------- 1 | using HotChocolate; 2 | using HotChocolate.Types; 3 | 4 | namespace Confix.Authoring.Store; 5 | 6 | public sealed record RenameApplicationChange : IApplicationChange 7 | { 8 | public RenameApplicationChange(Guid applicationId, int applicationVersion, string name) 9 | { 10 | ApplicationId = applicationId; 11 | ApplicationVersion = applicationVersion; 12 | Name = name; 13 | } 14 | 15 | public string Name { get; init; } 16 | 17 | public string Kind => nameof(RenameApplicationChange); 18 | 19 | [GraphQLName("application")] 20 | [UseDataLoader(typeof(IApplicationDataLoader))] 21 | public Guid ApplicationId { get; init; } 22 | 23 | public int ApplicationVersion { get; init; } 24 | } 25 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.Abstractions/Applications/DataLoaders/IApplicationByComponentIdDataLoader.cs: -------------------------------------------------------------------------------- 1 | using GreenDonut; 2 | 3 | namespace Confix.Authoring.Store; 4 | 5 | public interface IApplicationByComponentIdDataLoader 6 | : IDataLoader 7 | { 8 | } 9 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.Abstractions/Applications/DataLoaders/IApplicationByPartIdDataLoader.cs: -------------------------------------------------------------------------------- 1 | using GreenDonut; 2 | 3 | namespace Confix.Authoring.Store; 4 | 5 | public interface IApplicationByPartIdDataLoader : IDataLoader 6 | { 7 | } 8 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.Abstractions/Applications/DataLoaders/IApplicationDataLoader.cs: -------------------------------------------------------------------------------- 1 | using GreenDonut; 2 | 3 | namespace Confix.Authoring.Store; 4 | 5 | public interface IApplicationDataLoader : IDataLoader 6 | { 7 | } 8 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.Abstractions/Applications/DataLoaders/IApplicationPartComponentDataLoader.cs: -------------------------------------------------------------------------------- 1 | using GreenDonut; 2 | 3 | namespace Confix.Authoring.Store; 4 | 5 | public interface IApplicationPartComponentDataLoader : IDataLoader 6 | { 7 | } 8 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.Abstractions/Applications/DataLoaders/IApplicationPartDataLoader.cs: -------------------------------------------------------------------------------- 1 | using GreenDonut; 2 | 3 | namespace Confix.Authoring.Store; 4 | 5 | public interface IApplicationPartDataLoader : IDataLoader 6 | { 7 | } 8 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.Abstractions/Applications/Exceptions/ApplicationNotFoundException.cs: -------------------------------------------------------------------------------- 1 | namespace Confix.Authoring; 2 | 3 | public sealed class ApplicationNotFoundException : Exception 4 | { 5 | public ApplicationNotFoundException(Guid applicationId) 6 | { 7 | ApplicationId = applicationId; 8 | } 9 | 10 | public Guid ApplicationId { get; } 11 | } 12 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.Abstractions/Applications/Exceptions/ApplicationPartComponentNotFoundException.cs: -------------------------------------------------------------------------------- 1 | namespace Confix.Authoring; 2 | 3 | public sealed class ApplicationPartComponentNotFoundException : Exception 4 | { 5 | public ApplicationPartComponentNotFoundException(Guid componentPartId) 6 | : base($"The component part with id {componentPartId:N}.") 7 | { 8 | ComponentPartId = componentPartId; 9 | } 10 | 11 | public Guid ComponentPartId { get; set; } 12 | } 13 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.Abstractions/Applications/Exceptions/ApplicationPartNotFoundException.cs: -------------------------------------------------------------------------------- 1 | namespace Confix.Authoring; 2 | 3 | public sealed class ApplicationPartNotFoundException : Exception 4 | { 5 | public ApplicationPartNotFoundException(Guid applicationId) 6 | : base($"The application with id `{applicationId:N}` not found.") 7 | { 8 | ApplicationPartId = applicationId; 9 | } 10 | 11 | public Guid ApplicationPartId { get; } 12 | } 13 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.Abstractions/Applications/Models/Application.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | using HotChocolate.Types.Relay; 3 | 4 | namespace Confix.Authoring.Store; 5 | 6 | public sealed record Application 7 | { 8 | public Application(Guid id, string? name, string @namespace) 9 | { 10 | Id = id; 11 | Name = name; 12 | Namespace = @namespace; 13 | } 14 | 15 | [ID] 16 | public Guid Id { get; init; } 17 | 18 | [Required] 19 | public string? Name { get; init; } 20 | 21 | public string Namespace { get; init; } 22 | 23 | public int Version { get; init; } 24 | 25 | public ICollection Parts { get; init; } = new List(); 26 | } 27 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.Abstractions/Applications/Models/ApplicationPart.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | using HotChocolate.Types.Relay; 3 | 4 | namespace Confix.Authoring.Store; 5 | 6 | public sealed record ApplicationPart 7 | { 8 | public ApplicationPart(Guid id, string? name, int version) 9 | { 10 | Id = id; 11 | Name = name; 12 | Version = version; 13 | } 14 | 15 | public ApplicationPart(Guid id, string? name) 16 | { 17 | Id = id; 18 | Name = name; 19 | } 20 | 21 | [ID] 22 | public Guid Id { get; init; } 23 | 24 | [Required] 25 | public string? Name { get; init; } 26 | 27 | public int Version { get; init; } 28 | 29 | public ICollection Components { get; init; } = 30 | new List(); 31 | } 32 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.Abstractions/Applications/Models/ApplicationPartComponent.cs: -------------------------------------------------------------------------------- 1 | using HotChocolate.Types.Relay; 2 | 3 | namespace Confix.Authoring.Store; 4 | 5 | public sealed record ApplicationPartComponent 6 | { 7 | public ApplicationPartComponent(Guid id, Guid componentId, int version, string? values) 8 | { 9 | Id = id; 10 | ComponentId = componentId; 11 | Version = version; 12 | Values = values; 13 | } 14 | 15 | public ApplicationPartComponent(Guid id, Guid componentId, string? values) 16 | { 17 | Id = id; 18 | ComponentId = componentId; 19 | Values = values; 20 | } 21 | 22 | [ID] 23 | public Guid Id { get; init; } 24 | 25 | public Guid ComponentId { get; init; } 26 | 27 | public int Version { get; init; } 28 | 29 | public string? Values { get; init; } 30 | } 31 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.Abstractions/ChangeLog/Models/ChangeLog.cs: -------------------------------------------------------------------------------- 1 | using Confix.Authentication.Authorization; 2 | using HotChocolate.Types.Relay; 3 | 4 | namespace Confix.Authoring.Store; 5 | 6 | public sealed record ChangeLog 7 | { 8 | public ChangeLog(Guid id, IChange change, UserInfo modifiedBy, DateTime modifiedAt) 9 | { 10 | Id = id; 11 | Change = change; 12 | ModifiedBy = modifiedBy; 13 | ModifiedAt = modifiedAt; 14 | } 15 | 16 | [ID] 17 | public Guid Id { get; init; } 18 | 19 | public IChange Change { get; init; } 20 | 21 | public UserInfo ModifiedBy { get; init; } 22 | 23 | public DateTime ModifiedAt { get; init; } 24 | } 25 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.Abstractions/ChangeLog/Models/IChange.cs: -------------------------------------------------------------------------------- 1 | namespace Confix.Authoring.Store; 2 | 3 | public interface IChange 4 | { 5 | string Kind { get; } 6 | } 7 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.Abstractions/Components/Changes/ComponentValuesChange.cs: -------------------------------------------------------------------------------- 1 | using Confix.Authoring.Store; 2 | using HotChocolate; 3 | using HotChocolate.Types; 4 | 5 | namespace Confix.Authoring.Changes; 6 | 7 | public sealed class ComponentValuesChange : IComponentChange 8 | { 9 | public ComponentValuesChange(Guid componentId, int componentVersion, string values) 10 | { 11 | ComponentId = componentId; 12 | ComponentVersion = componentVersion; 13 | Values = values; 14 | } 15 | 16 | public string Values { get; init; } 17 | 18 | public string Kind => nameof(ComponentValuesChange); 19 | 20 | [GraphQLName("component")] 21 | [UseDataLoader(typeof(IComponentDataLoader))] 22 | public Guid ComponentId { get; init; } 23 | 24 | public int ComponentVersion { get; init; } 25 | } 26 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.Abstractions/Components/Changes/CreateComponentChange.cs: -------------------------------------------------------------------------------- 1 | using Confix.Authoring.Store; 2 | using HotChocolate; 3 | using HotChocolate.Types; 4 | 5 | namespace Confix.Authoring.Changes; 6 | 7 | public sealed class CreateComponentChange : IComponentChange 8 | { 9 | public CreateComponentChange(Guid componentId, int componentVersion, Component component) 10 | { 11 | ComponentId = componentId; 12 | ComponentVersion = componentVersion; 13 | Component = component; 14 | } 15 | 16 | [GraphQLIgnore] 17 | public Component Component { get; init; } 18 | 19 | public string Kind => nameof(ComponentValuesChange); 20 | 21 | [GraphQLName("component")] 22 | [UseDataLoader(typeof(IComponentDataLoader))] 23 | public Guid ComponentId { get; init; } 24 | 25 | public int ComponentVersion { get; init; } 26 | } 27 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.Abstractions/Components/Changes/IComponentChange.cs: -------------------------------------------------------------------------------- 1 | using Confix.Authoring.Store; 2 | using HotChocolate; 3 | 4 | namespace Confix.Authoring.Changes; 5 | 6 | public interface IComponentChange : IChange 7 | { 8 | [GraphQLType(typeof(Component))] 9 | [GraphQLName("component")] 10 | Guid ComponentId { get; } 11 | 12 | int ComponentVersion { get; } 13 | } 14 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.Abstractions/Components/Changes/RemoveComponentChange.cs: -------------------------------------------------------------------------------- 1 | using Confix.Authoring.Store; 2 | using HotChocolate; 3 | using HotChocolate.Types; 4 | 5 | namespace Confix.Authoring.Changes; 6 | 7 | public sealed class RemoveComponentChange : IComponentChange 8 | { 9 | public RemoveComponentChange(Guid componentId, int componentVersion, Component component) 10 | { 11 | ComponentId = componentId; 12 | ComponentVersion = componentVersion; 13 | Component = component; 14 | } 15 | 16 | [GraphQLIgnore] 17 | public Component Component { get; init; } 18 | 19 | public string Kind => nameof(ComponentValuesChange); 20 | 21 | [GraphQLName("component")] 22 | [UseDataLoader(typeof(IComponentDataLoader))] 23 | public Guid ComponentId { get; init; } 24 | 25 | public int ComponentVersion { get; init; } 26 | } 27 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.Abstractions/Components/Changes/RenameComponentChange.cs: -------------------------------------------------------------------------------- 1 | using Confix.Authoring.Store; 2 | using HotChocolate; 3 | using HotChocolate.Types; 4 | 5 | namespace Confix.Authoring.Changes; 6 | 7 | public sealed class RenameComponentChange : IComponentChange 8 | { 9 | public RenameComponentChange(Guid componentId, int componentVersion, string name) 10 | { 11 | ComponentId = componentId; 12 | ComponentVersion = componentVersion; 13 | Name = name; 14 | } 15 | 16 | public string Name { get; init; } 17 | 18 | public string Kind => nameof(RenameComponentChange); 19 | 20 | [GraphQLName("component")] 21 | [UseDataLoader(typeof(IComponentDataLoader))] 22 | public Guid ComponentId { get; init; } 23 | 24 | public int ComponentVersion { get; init; } 25 | } 26 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.Abstractions/Components/DataLoaders/IComponentDataLoader.cs: -------------------------------------------------------------------------------- 1 | using GreenDonut; 2 | 3 | namespace Confix.Authoring.Store; 4 | 5 | public interface IComponentDataLoader : IDataLoader 6 | { 7 | } 8 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.Abstractions/Components/Exceptions/ComponentNotFoundException.cs: -------------------------------------------------------------------------------- 1 | namespace Confix.Authoring; 2 | 3 | public class ComponentNotFoundException : Exception 4 | { 5 | public ComponentNotFoundException(Guid componentId) 6 | : base($"The component with id `{componentId:N}` was not found.") 7 | { 8 | ComponentId = componentId; 9 | } 10 | 11 | public Guid ComponentId { get; } 12 | } 13 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.Abstractions/Components/Models/ApplicationComponentScope.cs: -------------------------------------------------------------------------------- 1 | using Confix.Authoring.Store; 2 | using HotChocolate.Types.Relay; 3 | 4 | namespace Confix.Authoring; 5 | 6 | public sealed record ApplicationComponentScope([property: ID]Guid ApplicationId): ComponentScope(); 7 | 8 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.Abstractions/Components/Models/ApplicationPartComponentScope.cs: -------------------------------------------------------------------------------- 1 | using Confix.Authoring.Store; 2 | using HotChocolate.Types.Relay; 3 | 4 | namespace Confix.Authoring; 5 | 6 | public sealed record ApplicationPartComponentScope([property: ID]Guid ApplicationPartId): ComponentScope(); 7 | 8 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.Abstractions/Components/Models/ComponentScope.cs: -------------------------------------------------------------------------------- 1 | namespace Confix.Authoring; 2 | 3 | public abstract record ComponentScope(); 4 | 5 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.Abstractions/Components/Models/NamespaceComponentScope.cs: -------------------------------------------------------------------------------- 1 | namespace Confix.Authoring; 2 | 3 | public sealed record NamespaceComponentScope(string Namespace): ComponentScope(); 4 | 5 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.Abstractions/Components/Stores/IComponentStore.cs: -------------------------------------------------------------------------------- 1 | namespace Confix.Authoring.Store; 2 | 3 | public interface IComponentStore 4 | { 5 | Task GetByIdAsync(Guid id, CancellationToken cancellationToken); 6 | 7 | Task> GetManyByIdAsync( 8 | IEnumerable ids, 9 | CancellationToken cancellationToken); 10 | 11 | Task> GetByFilterAsync( 12 | IEnumerable namespaces, 13 | IEnumerable scopes, 14 | string? search, 15 | int skip, 16 | int take, 17 | CancellationToken cancellationToken); 18 | 19 | Task AddAsync(Component component, CancellationToken cancellationToken); 20 | 21 | Task UpdateAsync(Component component, CancellationToken cancellationToken); 22 | } 23 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.Abstractions/Configuration/IAuthoringServerBuilder.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.DependencyInjection; 2 | 3 | namespace Confix.Authoring; 4 | 5 | public interface IAuthoringServerBuilder 6 | { 7 | IServiceCollection Services { get; } 8 | } 9 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.Abstractions/Environment/Exceptions/EnvironmentCycleDetectedException.cs: -------------------------------------------------------------------------------- 1 | namespace Confix.Authoring; 2 | 3 | public sealed class EnvironmentCycleDetectedException : Exception 4 | { 5 | public EnvironmentCycleDetectedException(IEnumerable path) 6 | : base("There was a cycle in the parent child relation of environments detected") 7 | { 8 | Path = path.ToArray(); 9 | } 10 | 11 | public IReadOnlyList Path { get; } 12 | 13 | public string Code => "EnvironmentCycleDetected"; 14 | } 15 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.Abstractions/Environment/Exceptions/EnvironmentNameCollisionException.cs: -------------------------------------------------------------------------------- 1 | namespace Confix.Authoring; 2 | 3 | public sealed class EnvironmentNameCollisionException : Exception 4 | { 5 | public EnvironmentNameCollisionException(string name) 6 | { 7 | Name = name; 8 | } 9 | 10 | public string Name { get; } 11 | } 12 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.Abstractions/Environment/Exceptions/EnvironmentNotFoundException.cs: -------------------------------------------------------------------------------- 1 | namespace Confix.Authoring; 2 | 3 | public sealed class EnvironmentNotFoundException : Exception 4 | { 5 | public EnvironmentNotFoundException(Guid environmentId) 6 | { 7 | EnvironmentId = environmentId; 8 | } 9 | 10 | public Guid EnvironmentId { get; } 11 | } 12 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.Abstractions/Environment/Models/Environment.cs: -------------------------------------------------------------------------------- 1 | using HotChocolate.Types.Relay; 2 | 3 | namespace Confix.Authoring; 4 | 5 | public sealed record Environment 6 | { 7 | public Environment(Guid id, string? name = null!) 8 | { 9 | name ??= string.Empty; 10 | Id = id; 11 | Name = name; 12 | } 13 | 14 | [ID] 15 | public Guid Id { get; init; } 16 | 17 | public string Name { get; init; } 18 | 19 | public Guid? ParentId { get; init; } 20 | 21 | public bool AllowDeveloperAccess { get; init; } 22 | } 23 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.Abstractions/Exceptions/EntityIdInvalidException.cs: -------------------------------------------------------------------------------- 1 | namespace Confix.Authoring; 2 | 3 | public sealed class EntityIdInvalidException : Exception 4 | { 5 | public EntityIdInvalidException(string entityName, Guid entityId) 6 | : base($"The {entityName} id `{entityId}` is invalid.") 7 | { 8 | EntityName = entityName; 9 | EntityId = entityId; 10 | } 11 | 12 | public string EntityName { get; } 13 | 14 | public Guid EntityId { get; } 15 | } 16 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.Abstractions/Exceptions/NameTakenException.cs: -------------------------------------------------------------------------------- 1 | namespace Confix.Authoring; 2 | 3 | public sealed class NameTakenException : Exception 4 | { 5 | public NameTakenException(string name) 6 | { 7 | Name = name; 8 | } 9 | 10 | public string Name { get; } 11 | } 12 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.Abstractions/Groups/Dataloaders/IGroupByIdDataLoader.cs: -------------------------------------------------------------------------------- 1 | using Confix.Authentication.Authorization; 2 | using GreenDonut; 3 | 4 | namespace Confix.Authoring.Groups; 5 | 6 | public interface IGroupByIdDataLoader : IDataLoader 7 | { 8 | } 9 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.Abstractions/Publishing/DataLoader/IPublishedApplicationPartByIdDataloader.cs: -------------------------------------------------------------------------------- 1 | using GreenDonut; 2 | 3 | namespace Confix.Authoring.Publishing; 4 | 5 | public interface IPublishedApplicationPartByIdDataloader 6 | : IDataLoader 7 | { 8 | } 9 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.Abstractions/Publishing/DataLoader/IPublishedApplicationPartsByPartIdDataloader.cs: -------------------------------------------------------------------------------- 1 | using GreenDonut; 2 | 3 | namespace Confix.Authoring.Publishing; 4 | 5 | public interface IPublishedApplicationPartsByPartIdDataloader 6 | : IDataLoader 7 | { 8 | } 9 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.Abstractions/Roles/Dataloaders/IRoleByIdDataLoader.cs: -------------------------------------------------------------------------------- 1 | using Confix.Authentication.Authorization; 2 | using GreenDonut; 3 | 4 | namespace Confix.Authoring.Roles; 5 | 6 | public interface IRoleByIdDataLoader : IDataLoader 7 | { 8 | } 9 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.Abstractions/ScalarNames.cs: -------------------------------------------------------------------------------- 1 | namespace Confix.Authoring; 2 | 3 | public static class ScalarNames 4 | { 5 | public const string String = nameof(String); 6 | public const string Int = nameof(Int); 7 | public const string Boolean = nameof(Boolean); 8 | public const string Float = nameof(Float); 9 | } 10 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.Abstractions/Schema/Exceptions/InvalidSchemaException.cs: -------------------------------------------------------------------------------- 1 | namespace Confix.Authoring; 2 | 3 | public sealed class InvalidSchemaException: Exception{ 4 | public InvalidSchemaException(GraphQLSchemaError[] errors) : base("The Provided sdl is not valid") 5 | { 6 | Errors = errors; 7 | } 8 | 9 | public GraphQLSchemaError[] Errors; 10 | } 11 | public record GraphQLSchemaError(string message); 12 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.Abstractions/Schema/Exceptions/SchemaViolationException.cs: -------------------------------------------------------------------------------- 1 | namespace Confix.Authoring; 2 | public sealed class SchemaViolationException : Exception 3 | { 4 | public SchemaViolationException(IReadOnlyList violations) 5 | : base("Values has invalid structure.") 6 | { 7 | Violations = violations; 8 | } 9 | 10 | public IReadOnlyList Violations { get; } 11 | } 12 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.Abstractions/Schema/Models/SchemaViolation.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | 3 | namespace Confix.Authoring; 4 | 5 | public sealed class SchemaViolation 6 | { 7 | public SchemaViolation(IReadOnlyList path, string? code) 8 | { 9 | Path = path; 10 | Code = code; 11 | } 12 | 13 | public IReadOnlyList Path { get; } 14 | 15 | [Required] 16 | public string? Code { get; } 17 | } 18 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.Abstractions/Variables/Changes/CreateVariableChange.cs: -------------------------------------------------------------------------------- 1 | using Confix.Authoring.Store; 2 | using HotChocolate; 3 | using HotChocolate.Types; 4 | 5 | namespace Confix.Authoring.Variables.Changes; 6 | 7 | public sealed class CreateVariableChange : IVariableChange 8 | { 9 | public CreateVariableChange(Guid variableId, int variableVersion, Variable? value) 10 | { 11 | VariableId = variableId; 12 | VariableVersion = variableVersion; 13 | Value = value; 14 | } 15 | 16 | public Variable? Value { get; init; } 17 | 18 | [GraphQLName("variable")] 19 | [UseDataLoader(typeof(IVariableDataLoader))] 20 | public Guid VariableId { get; init; } 21 | 22 | public int VariableVersion { get; init; } 23 | 24 | public string Kind => nameof(CreateVariableChange); 25 | } 26 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.Abstractions/Variables/Changes/IVariableChange.cs: -------------------------------------------------------------------------------- 1 | using Confix.Authoring.Store; 2 | using HotChocolate; 3 | 4 | namespace Confix.Authoring.Variables.Changes; 5 | 6 | public interface IVariableChange : IChange 7 | { 8 | [GraphQLType(typeof(Variable))] 9 | [GraphQLName("variable")] 10 | Guid VariableId { get; } 11 | 12 | int VariableVersion { get; } 13 | } 14 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.Abstractions/Variables/Changes/RenameVariableChange.cs: -------------------------------------------------------------------------------- 1 | using Confix.Authoring.Store; 2 | using HotChocolate; 3 | using HotChocolate.Types; 4 | 5 | namespace Confix.Authoring.Variables.Changes; 6 | 7 | public sealed class RenameVariableChange : IVariableChange 8 | { 9 | public RenameVariableChange(Guid variableId, int variableVersion, string name) 10 | { 11 | VariableId = variableId; 12 | VariableVersion = variableVersion; 13 | Name = name; 14 | } 15 | 16 | public string Name { get; init; } 17 | 18 | [GraphQLName("variable")] 19 | [UseDataLoader(typeof(IVariableDataLoader))] 20 | public Guid VariableId { get; init; } 21 | 22 | public int VariableVersion { get; init; } 23 | 24 | public string Kind => nameof(RenameVariableChange); 25 | } 26 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.Abstractions/Variables/DataLoaders/IVariableDataLoader.cs: -------------------------------------------------------------------------------- 1 | using GreenDonut; 2 | 3 | namespace Confix.Authoring.Store; 4 | 5 | public interface IVariableDataLoader : IDataLoader 6 | { 7 | } 8 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.Abstractions/Variables/Models/ApplicationPartVariableScope.cs: -------------------------------------------------------------------------------- 1 | using HotChocolate.Types.Relay; 2 | using ApplicationPart = Confix.Authoring.Store.ApplicationPart; 3 | 4 | namespace Confix.Authoring; 5 | 6 | public record ApplicationPartVariableValueScope( 7 | Guid? EnvironmentId, 8 | [property: ID] Guid PartId) : VariableValueScope(EnvironmentId); 9 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.Abstractions/Variables/Models/ApplicationVariableValueScope.cs: -------------------------------------------------------------------------------- 1 | using Confix.Authoring.Store; 2 | using HotChocolate.Types.Relay; 3 | 4 | namespace Confix.Authoring; 5 | 6 | public record ApplicationVariableValueScope( 7 | Guid? EnvironmentId, 8 | [property: ID] Guid ApplicationId) : VariableValueScope(EnvironmentId); 9 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.Abstractions/Variables/Models/NamespaceVariableScope.cs: -------------------------------------------------------------------------------- 1 | namespace Confix.Authoring; 2 | 3 | public record NamespaceVariableValueScope( Guid? EnvironmentId, string Namespace) 4 | : VariableValueScope(EnvironmentId); 5 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.Abstractions/Variables/Models/VariableState.cs: -------------------------------------------------------------------------------- 1 | namespace Confix.Authoring; 2 | 3 | public enum VariableState 4 | { 5 | Active, 6 | Deprecated 7 | } 8 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.Abstractions/Variables/Models/VariableValueScope.cs: -------------------------------------------------------------------------------- 1 | using HotChocolate.Types.Relay; 2 | 3 | namespace Confix.Authoring; 4 | 5 | public abstract record VariableValueScope 6 | { 7 | protected VariableValueScope(Guid? environmentId) 8 | { 9 | this.EnvironmentId = environmentId; 10 | } 11 | 12 | [ID] 13 | public Guid? EnvironmentId { get; set; } 14 | } 15 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.Abstractions/Variables/Services/VariableValueScopeInput.cs: -------------------------------------------------------------------------------- 1 | using HotChocolate; 2 | using HotChocolate.Types; 3 | 4 | namespace Confix.Authoring; 5 | 6 | [OneOf] 7 | public record VariableValueScopeInput 8 | { 9 | public ApplicationVariableValueScope? Application { get; init; } 10 | 11 | public ApplicationPartVariableValueScope? ApplicationPart { get; init; } 12 | 13 | public NamespaceVariableValueScope? Namespace { get; init; } 14 | 15 | public VariableValueScope GetValueScope() 16 | => Application as VariableValueScope ?? 17 | ApplicationPart as VariableValueScope ?? 18 | Namespace as VariableValueScope ?? 19 | throw new GraphQLException("Invalid filter"); 20 | } 21 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.Abstractions/Variables/Stores/IVariableStore.cs: -------------------------------------------------------------------------------- 1 | namespace Confix.Authoring.Store; 2 | 3 | public interface IVariableStore 4 | { 5 | Task CreateAsync(Variable variable, CancellationToken cancellationToken); 6 | 7 | Task GetByIdAsync(Guid id, CancellationToken cancellationToken); 8 | 9 | Task> GetByNamesAsync( 10 | IEnumerable names, 11 | CancellationToken cancellationToken); 12 | 13 | Task> GetManyAsync( 14 | IEnumerable ids, 15 | CancellationToken cancellationToken); 16 | 17 | Task UpdateAsync(Variable variable, CancellationToken cancellationToken); 18 | 19 | IQueryable Query(); 20 | } 21 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.Abstractions/Variables/Stores/IVariableValueStore.cs: -------------------------------------------------------------------------------- 1 | namespace Confix.Authoring.Store.Mongo; 2 | 3 | public interface IVariableValueStore 4 | { 5 | Task DeleteAsync(Guid id, CancellationToken cancellationToken); 6 | 7 | Task> GetByFilterAsync( 8 | IEnumerable? ids, 9 | IEnumerable? filter, 10 | CancellationToken cancellationToken); 11 | 12 | Task GetByIdAsync(Guid id, CancellationToken cancellationToken); 13 | 14 | Task SaveAsync(VariableValue value, CancellationToken cancellationToken); 15 | } 16 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.Core/ApiKey/ApiKeyRequestExecutorBuilderExtensions.cs: -------------------------------------------------------------------------------- 1 | using Confix.Authentication.ApiKey; 2 | using Confix.Authentication.Authorization; 3 | using Confix.Authoring.ApiKeys.Authorization; 4 | using Confix.Common.Token; 5 | using Microsoft.Extensions.DependencyInjection; 6 | 7 | namespace Confix.Authoring.ApiKeys; 8 | 9 | public static class ApiKeyRequestExecutorBuilderExtensions 10 | { 11 | public static IServiceCollection AddApiKeys(this IServiceCollection services) 12 | { 13 | services.AddAuthorizationRule(); 14 | services.AddTokenProvider(); 15 | services.AddScoped(); 16 | services.AddScoped(); 17 | 18 | return services; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.Core/Applications/ApplicationServiceCollectionExtensions.cs: -------------------------------------------------------------------------------- 1 | using Confix.Authentication.Authorization; 2 | using Confix.Authoring.Store; 3 | using Microsoft.Extensions.DependencyInjection; 4 | 5 | namespace Confix.Authoring.Applications; 6 | 7 | public static class ApplicationRequestExecutorBuilderExtensions 8 | { 9 | public static IServiceCollection AddApplications(this IServiceCollection services) 10 | { 11 | services.AddAuthorizationRule(); 12 | services.AddAuthorizationRule(); 13 | services.AddAuthorizationRule(); 15 | 16 | services.AddScoped(); 17 | 18 | return services; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.Core/Authentication/IAuthoringServerAuthenticationBuilder.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Authentication; 2 | using Microsoft.Extensions.DependencyInjection; 3 | 4 | namespace Confix.Authoring; 5 | 6 | public interface IAuthoringServerAuthenticationBuilder 7 | { 8 | IServiceCollection Services { get; } 9 | 10 | IAuthoringServerAuthenticationBuilder ConfigureAuthentication( 11 | Action configure); 12 | 13 | IAuthoringServerAuthenticationBuilder ConfigureBuilder(Action configure); 14 | } 15 | 16 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.Core/ChangeLog/ChangeLogServiceCollectionExtensions.cs: -------------------------------------------------------------------------------- 1 | using Confix.Authentication.Authorization; 2 | using Confix.Authoring.Store; 3 | using Microsoft.Extensions.DependencyInjection; 4 | 5 | namespace Confix.Authoring.ChangeLogs; 6 | 7 | public static class ChangeLogServiceCollectionExtensions 8 | { 9 | public static IServiceCollection AddChangeLog(this IServiceCollection services) 10 | { 11 | services.AddScoped(); 12 | services.AddAuthorizationRule(); 13 | 14 | return services; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.Core/Components/ComponentServiceCollectionExtensions.cs: -------------------------------------------------------------------------------- 1 | using Confix.Authentication.Authorization; 2 | using Confix.Authoring.Components.Authorization; 3 | using Microsoft.Extensions.DependencyInjection; 4 | 5 | namespace Confix.Authoring.Components; 6 | 7 | public static class ComponentServiceCollectionExtensions 8 | { 9 | public static IServiceCollection AddComponents(this IServiceCollection services) 10 | { 11 | services.AddAuthorizationRule(); 12 | services.AddScoped(); 13 | 14 | return services; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.Core/Components/Services/ComponentValidationFailed.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics.CodeAnalysis; 2 | 3 | namespace Confix.Authoring; 4 | 5 | public sealed class ComponentValidationFailed : Exception 6 | { 7 | public ComponentValidationFailed(string message) : base(message) { } 8 | 9 | public string Code { get; } = "COMPONENT_VALIDATION_FAILED"; 10 | 11 | public static ComponentValidationFailed AtLeastOneScopeIsRequired() => 12 | new("At least one scope is required."); 13 | public static ComponentValidationFailed NameRequired() => 14 | new("Name is required."); 15 | } 16 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.Core/Environement/EnvironmentServiceCollectionExtensions.cs: -------------------------------------------------------------------------------- 1 | using Confix.Authentication.Authorization; 2 | using Confix.Authoring.Environement.Authorization; 3 | using Microsoft.Extensions.DependencyInjection; 4 | 5 | namespace Confix.Authoring.Environement; 6 | 7 | public static class EnvironmentServiceCollectionExtensions 8 | { 9 | public static IServiceCollection AddEnvironments(this IServiceCollection services) 10 | { 11 | services.AddAuthorizationRule(); 12 | services.AddScoped(); 13 | 14 | return services; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.Core/Extensions/CollectionExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace Confix.Authoring.Extensions; 2 | 3 | internal static class CollectionExtensions 4 | { 5 | public static ICollection Replace(this ICollection collection, T item, Func factory) 6 | where T : class 7 | { 8 | return collection 9 | .Select(x => item == x ? factory() : x) 10 | .ToArray(); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.Core/Extensions/PathExtensions.cs: -------------------------------------------------------------------------------- 1 | using HotChocolate.Execution; 2 | using Path = HotChocolate.Path; 3 | 4 | namespace Confix.Authoring.Internal; 5 | 6 | public static class PathExtensions 7 | { 8 | public static Path Append(this Path path, string name) 9 | => PathFactory.Instance.Append(path, name); 10 | 11 | public static Path Append(this Path path, int number) 12 | => PathFactory.Instance.Append(path, number); 13 | } 14 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.Core/Groups/GroupServiceCollectionExtensions.cs: -------------------------------------------------------------------------------- 1 | using Confix.Authoring.Groups.Authorization; 2 | using Microsoft.Extensions.DependencyInjection; 3 | 4 | namespace Confix.Authentication.Authorization; 5 | 6 | public static class GroupServiceCollectionExtensions 7 | { 8 | public static IServiceCollection AddGroups(this IServiceCollection services) 9 | { 10 | services.AddAuthorizationRule(); 11 | services.AddScoped(); 12 | 13 | return services; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.Core/InternalsVisibleTo.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.CompilerServices; 2 | using Confix.Authentication.ApiKey; 3 | 4 | [assembly: InternalsVisibleTo("Confix.Authoring.GraphQL")] 5 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.Core/Publishing/Authorization/DeveloperAccessRequest.cs: -------------------------------------------------------------------------------- 1 | using Confix.Authoring.Store; 2 | 3 | namespace Confix.Authoring.Publishing.Authorization; 4 | 5 | public record DeveloperAccessRequest(Environment Environment, Application Application); 6 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.Core/Publishing/Exceptions/ClaimVersionFailedException.cs: -------------------------------------------------------------------------------- 1 | namespace Confix.Authoring.Publishing; 2 | 3 | internal sealed class ClaimVersionFailedException : Exception 4 | { 5 | public ClaimVersionFailedException(string? message) : base(message) 6 | { 7 | } 8 | 9 | public string Code => "ClaimVersionError"; 10 | } 11 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.Core/Publishing/Exceptions/PublishingException.cs: -------------------------------------------------------------------------------- 1 | namespace Confix.Authoring.Publishing; 2 | 3 | internal sealed class PublishingException : Exception 4 | { 5 | public PublishingException(string? message) : base(message) 6 | { 7 | } 8 | 9 | public string Code => "PublishingError"; 10 | } 11 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.Core/Publishing/PublishingServiceCollectionExtensions.cs: -------------------------------------------------------------------------------- 1 | using Confix.Authentication.Authorization; 2 | using Confix.Authoring.Publishing.Authorization; 3 | using Microsoft.Extensions.DependencyInjection; 4 | 5 | namespace Confix.Authoring.Publishing; 6 | 7 | public static class PublishingServiceCollectionExtensions 8 | { 9 | public static IServiceCollection AddPublishing(this IServiceCollection services) 10 | { 11 | services.AddAuthorizationRule(); 13 | services.AddAuthorizationRule(); 14 | 15 | services.AddScoped(); 16 | 17 | return services; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.Core/Publishing/Services/JsonVariableVisitorContext.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Nodes; 2 | 3 | namespace Confix.Authoring.Publishing; 4 | 5 | internal sealed class JsonVariableVisitorContext 6 | { 7 | public Stack> SetValue { get; } = new(); 8 | 9 | public IList Variables { get; } = new List(); 10 | } 11 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.Core/Publishing/Services/VariableMatch.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Nodes; 2 | 3 | namespace Confix.Authoring.Publishing; 4 | 5 | internal sealed record VariableMatch(string VariableName, Action SetValue); 6 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.Core/Roles/Services/RoleServiceCollectionExtensions.cs: -------------------------------------------------------------------------------- 1 | using Confix.Authoring.Roles.Authorization; 2 | using Microsoft.Extensions.DependencyInjection; 3 | 4 | namespace Confix.Authentication.Authorization; 5 | 6 | public static class RoleServiceCollectionExtensions 7 | { 8 | public static IServiceCollection AddRoles(this IServiceCollection services) 9 | { 10 | services.AddAuthorizationRule(); 11 | services.AddScoped(); 12 | 13 | return services; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.Core/Schema/SchemaServiceCollectionExtensions.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.DependencyInjection; 2 | 3 | namespace Confix.Authoring.Internal; 4 | 5 | public static class SchemaServiceCollectionExtensions 6 | { 7 | public static IServiceCollection AddSchemas(this IServiceCollection services) 8 | { 9 | services.AddScoped(); 10 | 11 | return services; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.Core/Schema/Services/ISchemaValidator.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json; 2 | 3 | namespace Confix.Authoring.Internal; 4 | 5 | public interface ISchemaValidator 6 | { 7 | void ValidateSchema(string schemaSdl); 8 | void ValidateValues(JsonElement values, string schemaSdl); 9 | IReadOnlyList GetSchemaViolations(JsonElement values, string schemaSdl); 10 | } 11 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.Core/Variables/VariableServiceCollectionExtensions.cs: -------------------------------------------------------------------------------- 1 | using Confix.Authentication.Authorization; 2 | using Confix.Authoring.Variables; 3 | using Microsoft.Extensions.DependencyInjection; 4 | 5 | namespace Confix.Authoring; 6 | 7 | public static class VariableServiceCollectionExtensions 8 | { 9 | public static IServiceCollection AddVariables(this IServiceCollection services) 10 | { 11 | services.AddAuthorizationRule(); 12 | services.AddAuthorizationRule(); 13 | services.AddScoped(); 14 | 15 | return services; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.GraphQL/ApiKeys/ApiKeyQueries.cs: -------------------------------------------------------------------------------- 1 | using Confix.Authentication.ApiKey; 2 | using Confix.Authoring.ApiKeys; 3 | 4 | namespace Confix.Authoring.GraphQL.ApiKeys; 5 | 6 | [ExtendObjectType(OperationTypeNames.Query)] 7 | public class ApiKeyQueries 8 | { 9 | [UsePaging] 10 | public async Task> GetApiKeysAsync( 11 | [Service] IApiKeyService apiKeyService, 12 | CancellationToken cancellationToken) 13 | { 14 | return await apiKeyService.PageAsync(cancellationToken); 15 | } 16 | 17 | public async Task GetApiKeyByIdAsync( 18 | [Service] IApiKeyService apiKeyService, 19 | [ID(nameof(ApiKey))] Guid id, 20 | CancellationToken cancellationToken) 21 | { 22 | return await apiKeyService.GetByIdAsync(id, cancellationToken); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.GraphQL/ApiKeys/Configuration/ApplicationRequestExecutorBuilderExtensions.cs: -------------------------------------------------------------------------------- 1 | using Confix.Authoring.ApiKeys.DataLoaders; 2 | using Confix.Authoring.GraphQL.ApiKeys; 3 | using HotChocolate.Execution.Configuration; 4 | using Microsoft.Extensions.DependencyInjection; 5 | 6 | namespace Confix.Authoring.GraphQL; 7 | 8 | public static class ApiKeyRequestExecutorBuilderExtensions 9 | { 10 | public static IRequestExecutorBuilder AddApiKeys(this IRequestExecutorBuilder builder) 11 | { 12 | // dataloaders 13 | builder.AddDataLoader(); 14 | 15 | // nodes 16 | 17 | // types 18 | builder.AddTypeExtension().AddTypeExtension(); 19 | 20 | return builder; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.GraphQL/Applications/Errors/ApplicationNameTaken.cs: -------------------------------------------------------------------------------- 1 | namespace Confix.Authoring.GraphQL.Applications; 2 | 3 | public sealed class ApplicationNameTaken : UserError 4 | { 5 | public ApplicationNameTaken(string applicationName) 6 | : base($"The application name `{applicationName}` is already taken.") 7 | { 8 | ApplicationName = applicationName; 9 | } 10 | 11 | public ApplicationNameTaken(NameTakenException exception) 12 | : this(exception.Name) 13 | { 14 | } 15 | 16 | public string ApplicationName { get; } 17 | } 18 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.GraphQL/Applications/Errors/ApplicationNotFoundError.cs: -------------------------------------------------------------------------------- 1 | using Confix.Authoring.Store; 2 | 3 | namespace Confix.Authoring.GraphQL.Applications; 4 | 5 | public sealed class ApplicationNotFoundError : UserError 6 | { 7 | public ApplicationNotFoundError(Guid applicationId) : base( 8 | $"The application with id `{applicationId:N}` not found.") 9 | { 10 | ApplicationId = applicationId; 11 | } 12 | 13 | public ApplicationNotFoundError(ApplicationNotFoundException exception) : this(exception 14 | .ApplicationId) 15 | { 16 | } 17 | 18 | [ID(nameof(Application))] 19 | public Guid ApplicationId { get; } 20 | } 21 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.GraphQL/Applications/Errors/ApplicationPartComponentNotFoundError.cs: -------------------------------------------------------------------------------- 1 | using Confix.Authoring.Store; 2 | 3 | namespace Confix.Authoring.GraphQL.Applications; 4 | 5 | public sealed class ApplicationPartComponentNotFoundError : UserError 6 | { 7 | public ApplicationPartComponentNotFoundError(Guid componentPartId) 8 | : base($"The component part with id {componentPartId:N}.") 9 | { 10 | ComponentPartId = componentPartId; 11 | } 12 | 13 | public ApplicationPartComponentNotFoundError( 14 | ApplicationPartComponentNotFoundException exception) 15 | : this(exception.ComponentPartId) 16 | { 17 | } 18 | 19 | [ID(nameof(ApplicationPartComponent))] 20 | public Guid ComponentPartId { get; set; } 21 | } 22 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.GraphQL/Applications/Errors/ApplicationPartNameTaken.cs: -------------------------------------------------------------------------------- 1 | namespace Confix.Authoring.GraphQL.Applications; 2 | 3 | public sealed class ApplicationPartNameTaken : UserError 4 | { 5 | public ApplicationPartNameTaken(string applicationName) 6 | : base($"The application part name `{applicationName}` is already taken.") 7 | { 8 | ApplicationName = applicationName; 9 | } 10 | 11 | public ApplicationPartNameTaken(NameTakenException exception) 12 | : this(exception.Name) 13 | { 14 | } 15 | 16 | public string ApplicationName { get; } 17 | } 18 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.GraphQL/Applications/Errors/ApplicationPartNotFoundError.cs: -------------------------------------------------------------------------------- 1 | using Confix.Authoring.Store; 2 | 3 | namespace Confix.Authoring.GraphQL.Applications; 4 | 5 | public sealed class ApplicationPartNotFoundError : UserError 6 | { 7 | public ApplicationPartNotFoundError(Guid applicationId) 8 | : base($"The application part with id `{applicationId:N}` not found.") 9 | { 10 | ApplicationPartId = applicationId; 11 | } 12 | 13 | public ApplicationPartNotFoundError(ApplicationPartNotFoundException exception) 14 | : this(exception.ApplicationPartId) 15 | { 16 | } 17 | 18 | [ID(nameof(ApplicationPart))] 19 | 20 | public Guid ApplicationPartId { get; } 21 | } 22 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.GraphQL/Applications/Errors/ComponentNotFoundError.cs: -------------------------------------------------------------------------------- 1 | namespace Confix.Authoring.GraphQL.Applications; 2 | 3 | public sealed class ComponentNotFoundError : UserError 4 | { 5 | public ComponentNotFoundError(Guid componentId) 6 | : base($"The component with id `{componentId:N}` was not found.") 7 | { 8 | ComponentId = componentId; 9 | } 10 | 11 | public ComponentNotFoundError(ComponentNotFoundException exception) 12 | : this(exception.ComponentId) 13 | { 14 | } 15 | 16 | [ID(nameof(Component))] 17 | public Guid ComponentId { get; } 18 | } 19 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.GraphQL/Applications/Errors/EnvironmentNameCollisionError.cs: -------------------------------------------------------------------------------- 1 | namespace Confix.Authoring.GraphQL.Applications; 2 | 3 | public sealed class EnvironmentNameCollisionError : UserError 4 | { 5 | public EnvironmentNameCollisionError(string name) 6 | : base($"There is already a environment with name `{name}`") 7 | { 8 | Name = name; 9 | } 10 | 11 | public EnvironmentNameCollisionError(EnvironmentNameCollisionException exception) 12 | : this(exception.Name) 13 | { 14 | } 15 | 16 | public string Name { get; } 17 | } -------------------------------------------------------------------------------- /src/Backend/src/Authoring.GraphQL/Applications/Errors/EnvironmentPartNotFoundError.cs: -------------------------------------------------------------------------------- 1 | namespace Confix.Authoring.GraphQL.Applications; 2 | 3 | public sealed class EnvironmentNotFoundError : UserError 4 | { 5 | public EnvironmentNotFoundError(Guid envId) 6 | : base($"The environment with id `{envId:N}` not found.") 7 | { 8 | EnvironmentId = envId; 9 | } 10 | 11 | public EnvironmentNotFoundError(EnvironmentNotFoundException exception) 12 | : this(exception.EnvironmentId) 13 | { 14 | } 15 | 16 | [ID(nameof(Environment))] 17 | public Guid EnvironmentId { get; } 18 | } 19 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.GraphQL/Applications/Extensions/ApplicationApplicationPartExtensions.cs: -------------------------------------------------------------------------------- 1 | using Confix.Authoring.Store; 2 | 3 | namespace Confix.Authoring.GraphQL.Applications; 4 | 5 | [ExtendObjectType(typeof(ApplicationPart))] 6 | public sealed class ApplicationApplicationPartExtensions 7 | { 8 | public Task GetApplicationAsync( 9 | [Service] IApplicationService service, 10 | [Parent] ApplicationPart part) => 11 | service.GetByPartIdAsync(part.Id); 12 | } 13 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.GraphQL/Applications/Extensions/ApplicationPartComponentChangeLogExtensions.cs: -------------------------------------------------------------------------------- 1 | using Confix.Authoring.Store; 2 | 3 | namespace Confix.Authoring.GraphQL; 4 | 5 | [ExtendObjectType(typeof(ApplicationPartComponent))] 6 | public sealed class ApplicationPartComponentChangeLogExtensions 7 | { 8 | public async Task> GetChangeLogAsync( 9 | [Service] IChangeLogService service, 10 | [Parent] ApplicationPartComponent partComponent, 11 | CancellationToken cancellationToken) 12 | { 13 | return await service.GetByApplicationPartComponentId(partComponent.Id, cancellationToken); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.GraphQL/Applications/Relay/ApplicationNode.cs: -------------------------------------------------------------------------------- 1 | using Confix.Authoring.Store; 2 | 3 | namespace Confix.Authoring.GraphQL.Applications; 4 | 5 | [Node] 6 | [ExtendObjectType(typeof(Application))] 7 | public sealed class ApplicationNode 8 | { 9 | [NodeResolver] 10 | public static Task GetApplicationAsync( 11 | [Service] IApplicationService service, 12 | Guid id, 13 | CancellationToken cancellationToken) 14 | { 15 | return service.GetByIdAsync(id, cancellationToken); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.GraphQL/Applications/Relay/ApplicationPartNode.cs: -------------------------------------------------------------------------------- 1 | using Confix.Authoring.Store; 2 | 3 | namespace Confix.Authoring.GraphQL.Applications; 4 | 5 | [Node] 6 | [ExtendObjectType(typeof(ApplicationPart))] 7 | public sealed class ApplicationPartNode 8 | { 9 | [NodeResolver] 10 | public static Task GetApplicationPartAsync( 11 | [Service] IApplicationService service, 12 | Guid id, 13 | CancellationToken cancellationToken) 14 | { 15 | return service.GetPartByIdAsync(id, cancellationToken); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.GraphQL/ChangeLog/ChangeLogQueries.cs: -------------------------------------------------------------------------------- 1 | using Confix.Authoring.Store; 2 | 3 | namespace Confix.Authoring.GraphQL.Applications; 4 | 5 | [ExtendObjectType(OperationTypeNames.Query)] 6 | public sealed class ChangeLogQueries 7 | { 8 | public Task GetChangeLogByIdAsync( 9 | [Service] IChangeLogService changeLogService, 10 | [ID(nameof(ChangeLog))] Guid id, 11 | CancellationToken cancellationToken) 12 | { 13 | return changeLogService.GetById(id, cancellationToken); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.GraphQL/ChangeLog/Relay/ChangeLogNode.cs: -------------------------------------------------------------------------------- 1 | using Confix.Authoring.Store; 2 | 3 | namespace Confix.Authoring.GraphQL.Applications; 4 | 5 | [Node] 6 | [ExtendObjectType(typeof(ChangeLogNode))] 7 | public sealed class ChangeLogNode 8 | { 9 | [NodeResolver] 10 | public static Task GetApplicationAsync( 11 | Guid id, 12 | [Service] IChangeLogService changeLogService, 13 | CancellationToken cancellationToken) 14 | { 15 | return changeLogService.GetById(id, cancellationToken); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.GraphQL/Components/Errors/ComponentNameTaken.cs: -------------------------------------------------------------------------------- 1 | using Confix.Authoring.GraphQL.Applications; 2 | 3 | namespace Confix.Authoring.GraphQL.Components; 4 | 5 | public sealed class ComponentNameTaken : UserError 6 | { 7 | public ComponentNameTaken(string componentName) 8 | : base("The component name is already used by a different component.") 9 | { 10 | ComponentName = componentName; 11 | } 12 | 13 | public string ComponentName { get; } 14 | 15 | public static ComponentNameTaken CreateErrorFrom(Exception exception) 16 | { 17 | throw new Exception(); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.GraphQL/Components/Errors/SchemaInvalidError.cs: -------------------------------------------------------------------------------- 1 | using Confix.Authoring.GraphQL.Applications; 2 | 3 | namespace Confix.Authoring.GraphQL.Components; 4 | 5 | public class SchemaInvalidError : UserError 6 | { 7 | public SchemaInvalidError(InvalidSchemaException exception): base(exception.Message) 8 | { 9 | Errors = exception.Errors; 10 | } 11 | 12 | public GraphQLSchemaError[] Errors {get;} 13 | } 14 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.GraphQL/Components/Errors/ValueSchemaViolation.cs: -------------------------------------------------------------------------------- 1 | using Confix.Authoring.GraphQL.Applications; 2 | 3 | namespace Confix.Authoring.GraphQL.Components; 4 | 5 | public sealed class ValueSchemaViolation : UserError 6 | { 7 | public ValueSchemaViolation(SchemaViolationException exception) : base(exception.Message) 8 | { 9 | Violations = exception.Violations; 10 | } 11 | 12 | public IReadOnlyList Violations { get; } 13 | } 14 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.GraphQL/Components/Relay/ComponentNode.cs: -------------------------------------------------------------------------------- 1 | namespace Confix.Authoring.GraphQL.Components; 2 | 3 | [Node] 4 | [ExtendObjectType(typeof(Component))] 5 | public sealed class ComponentNode 6 | { 7 | [NodeResolver] 8 | public static async Task GetComponentAsync( 9 | Guid id, 10 | [Service] IComponentService service, 11 | CancellationToken cancellationToken) 12 | { 13 | return await service.GetByIdAsync(id, cancellationToken); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.GraphQL/Components/Types/ComponentScopeInput.cs: -------------------------------------------------------------------------------- 1 | namespace Confix.Authoring.GraphQL.Components; 2 | 3 | [OneOf] 4 | public record ComponentScopeInput 5 | { 6 | public ApplicationComponentScope? Application { get; init; } 7 | 8 | public ApplicationPartComponentScope? ApplicationPart { get; init; } 9 | 10 | public NamespaceComponentScope? Namespace { get; init; } 11 | 12 | public ComponentScope GetScope() 13 | => Application as ComponentScope ?? 14 | ApplicationPart as ComponentScope ?? 15 | Namespace as ComponentScope ?? 16 | throw new GraphQLException("Invalid filter"); 17 | } 18 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.GraphQL/Components/Types/ComponentScopeType.cs: -------------------------------------------------------------------------------- 1 | namespace Confix.Authoring.GraphQL.Components; 2 | 3 | public class ComponentScopeType : UnionType 4 | { 5 | protected override void Configure(IUnionTypeDescriptor descriptor) 6 | { 7 | descriptor.Name(nameof(ComponentScope)); 8 | 9 | // The object types that belong to this union 10 | descriptor.Type>(); 11 | descriptor.Type>(); 12 | descriptor.Type>(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.GraphQL/Environment/EnvironmentQueries.cs: -------------------------------------------------------------------------------- 1 | namespace Confix.Authoring.GraphQL; 2 | 3 | [ExtendObjectType(OperationTypeNames.Query)] 4 | public sealed class EnvironmentQueries 5 | { 6 | [UsePaging] 7 | public Task> SearchEnvironments( 8 | [Service] IEnvironmentService environmentService, 9 | string? search, 10 | CancellationToken cancellationToken) 11 | { 12 | return environmentService.SearchAsync(search, cancellationToken); 13 | } 14 | 15 | public async Task GetEnvironmentByIdAsync( 16 | [Service] IEnvironmentService environmentService, 17 | [ID(nameof(Environment))] Guid id, 18 | CancellationToken cancellationToken) 19 | { 20 | return await environmentService.GetByIdAsync(id, cancellationToken); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.GraphQL/Environment/Extensions/EnvironementExtenstions.cs: -------------------------------------------------------------------------------- 1 | using HotChocolate.Resolvers; 2 | 3 | namespace Confix.Authoring; 4 | 5 | [ExtendObjectType(typeof(Environment))] 6 | public sealed class EnvironmentExtensions 7 | { 8 | [BindMember(nameof(Environment.ParentId))] 9 | public async Task GetParentAsync( 10 | IResolverContext context, 11 | [Parent] Environment environment, 12 | [Service] IEnvironmentService service) 13 | { 14 | if (environment.ParentId is { } parentId) 15 | { 16 | return await service.GetByIdAsync(parentId); 17 | } 18 | 19 | return null; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.GraphQL/Environment/Relay/EnvironmentNode.cs: -------------------------------------------------------------------------------- 1 | namespace Confix.Authoring.GraphQL.Relay; 2 | 3 | [Node] 4 | [ExtendObjectType(typeof(Environment))] 5 | public sealed class EnvironmentNode 6 | { 7 | [NodeResolver] 8 | public static async Task GetEnvironmentAsync( 9 | Guid id, 10 | [Service] IEnvironmentService service, 11 | CancellationToken cancellationToken) 12 | { 13 | return await service.GetByIdAsync(id, cancellationToken); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.GraphQL/Groups/GroupQueries.cs: -------------------------------------------------------------------------------- 1 | using Confix.Authentication.Authorization; 2 | 3 | namespace Confix.Authoring.GraphQL; 4 | 5 | [ExtendObjectType(OperationTypeNames.Query)] 6 | public sealed class GroupQueries 7 | { 8 | [UsePaging] 9 | public Task> SearchGroups( 10 | [Service] IGroupService groupService, 11 | string? search, 12 | CancellationToken cancellationToken) 13 | { 14 | return groupService.SearchGroupAsync(search, cancellationToken); 15 | } 16 | 17 | public Task GetGroupByIdAsync( 18 | [Service] IGroupService groupService, 19 | [ID(nameof(Group))] Guid id, 20 | CancellationToken cancellationToken) 21 | { 22 | return groupService.GetByIdAsync(id, cancellationToken); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.GraphQL/Groups/RoleScopeExtensions.cs: -------------------------------------------------------------------------------- 1 | using Confix.Authentication.Authorization; 2 | 3 | namespace Confix.Authoring.GraphQL; 4 | 5 | [ExtendObjectType(typeof(RoleScope))] 6 | public sealed class RoleScopeExtensions 7 | { 8 | [BindMember(nameof(RoleScope.RoleIds))] 9 | public async Task> GetRolesAsync( 10 | [Service] IRoleService roleService, 11 | [Parent] RoleScope parent, 12 | CancellationToken cancellationToken) 13 | { 14 | return await roleService.GetByIdsAsync(parent.RoleIds, cancellationToken); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.GraphQL/Groups/Transport/ClaimRequirementInput.cs: -------------------------------------------------------------------------------- 1 | using Confix.Authentication.Authorization; 2 | 3 | namespace Confix.Authoring.GraphQL.Transport; 4 | 5 | public sealed record ClaimRequirementInput(string Type, string Value) : IRequirementInput 6 | { 7 | public Requirement Get() 8 | { 9 | return new ClaimRequirement(Type, Value); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.GraphQL/Groups/Transport/IRequirementInput.cs: -------------------------------------------------------------------------------- 1 | using Confix.Authentication.Authorization; 2 | 3 | namespace Confix.Authoring.GraphQL.Transport; 4 | 5 | public interface IRequirementInput 6 | { 7 | Requirement Get(); 8 | } 9 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.GraphQL/Groups/Transport/RequirementInput.cs: -------------------------------------------------------------------------------- 1 | using Confix.Authentication.Authorization; 2 | 3 | namespace Confix.Authoring.GraphQL.Transport; 4 | 5 | [OneOf] 6 | public sealed record RequirementInput(ClaimRequirementInput? ClaimRequirement) : IRequirementInput 7 | { 8 | public Requirement Get() 9 | { 10 | IRequirementInput input = ClaimRequirement ?? 11 | throw new InvalidOperationException("At least one requirement is required"); 12 | 13 | return input.Get(); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.GraphQL/InternalsVisibleTo.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.CompilerServices; 2 | 3 | [assembly: InternalsVisibleTo("Confix.Authoring.GraphQL.Tests")] 4 | [assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")] 5 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.GraphQL/Publishing/ApplicationPartPublishingExtensions.cs: -------------------------------------------------------------------------------- 1 | using Confix.Authoring.Publishing; 2 | using Confix.Authoring.Store; 3 | 4 | namespace Confix.Authoring.GraphQL.Publishing; 5 | 6 | [ExtendObjectType(typeof(ApplicationPart))] 7 | public sealed class ApplicationPartPublishingExtensions 8 | { 9 | [UsePaging] 10 | public async Task> PublishApplicationPartByIdAsync( 11 | [Service] IPublishingService service, 12 | [Parent] ApplicationPart part, 13 | CancellationToken cancellationToken) 14 | { 15 | return await service.GetPublishedByPartId(part.Id, cancellationToken); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.GraphQL/Publishing/ClaimVersionResult.cs: -------------------------------------------------------------------------------- 1 | using Confix.Authoring.Publishing; 2 | 3 | namespace Confix.Authoring.GraphQL.Publishing; 4 | 5 | public record ClaimVersionResult(ClaimedVersion Version); 6 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.GraphQL/Publishing/Extensions/PublishedApplicationPartExtensions.cs: -------------------------------------------------------------------------------- 1 | using Confix.Authoring.Publishing; 2 | 3 | namespace Confix.Authoring.GraphQL; 4 | 5 | [ExtendObjectType(typeof(PublishedApplicationPart))] 6 | public sealed class PublishedApplicationPartExtensions 7 | { 8 | public Task> GetClaimsVersions( 9 | [Service] IPublishingService service, 10 | [Parent] PublishedApplicationPart parent, 11 | CancellationToken cancellationToken) 12 | { 13 | return service.GetClaimedVersionByPublishedPartIdAsync(parent.Id, cancellationToken); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.GraphQL/Publishing/LatestPublishedVersion.cs: -------------------------------------------------------------------------------- 1 | namespace Confix.Authoring.GraphQL.Publishing; 2 | 3 | public record LatestPublishedVersion(string Configuration); 4 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.GraphQL/Publishing/LatestPublishedVersionResultType.cs: -------------------------------------------------------------------------------- 1 | using Confix.Authoring.Publishing; 2 | 3 | namespace Confix.Authoring.GraphQL.Publishing; 4 | 5 | public sealed class LatestPublishedVersionResultType : UnionType 6 | { 7 | protected override void Configure(IUnionTypeDescriptor descriptor) 8 | { 9 | descriptor.Name("LatestPublishedVersionResult"); 10 | 11 | descriptor 12 | .Type>() 13 | .Type>(); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.GraphQL/Publishing/PublishedApplicationPartNode.cs: -------------------------------------------------------------------------------- 1 | using Confix.Authoring.Publishing; 2 | 3 | namespace Confix.Authoring.GraphQL.Publishing; 4 | 5 | [Node] 6 | [ExtendObjectType(typeof(PublishedApplicationPart))] 7 | public sealed class PublishedApplicationPartNode 8 | { 9 | [NodeResolver] 10 | public static async Task GetApplicationAsync( 11 | Guid id, 12 | IPublishingService publishingService, 13 | CancellationToken cancellationToken) 14 | { 15 | return await publishingService.GetPublishedById(id, cancellationToken); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.GraphQL/Roles/RoleQueries.cs: -------------------------------------------------------------------------------- 1 | using Confix.Authentication.Authorization; 2 | 3 | namespace Confix.Authoring.GraphQL; 4 | 5 | [ExtendObjectType(OperationTypeNames.Query)] 6 | public sealed class RoleQueries 7 | { 8 | [UsePaging] 9 | public Task> SearchRoles( 10 | [Service] IRoleService roleService, 11 | string? search, 12 | CancellationToken cancellationToken) 13 | { 14 | return roleService.SearchRoleAsync(search, cancellationToken); 15 | } 16 | 17 | public Task GetRoleByIdAsync( 18 | [Service] IRoleService roleService, 19 | [ID(nameof(Role))] Guid id, 20 | CancellationToken cancellationToken) 21 | { 22 | return roleService.GetByIdAsync(id, cancellationToken); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.GraphQL/Shared/IUserError.cs: -------------------------------------------------------------------------------- 1 | namespace Confix.Authoring.GraphQL; 2 | 3 | [InterfaceType("UserError")] 4 | public interface IUserError 5 | { 6 | string Code { get; } 7 | 8 | string Message { get; } 9 | } 10 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.GraphQL/Shared/SchemaViolationType.cs: -------------------------------------------------------------------------------- 1 | namespace Confix.Authoring.GraphQL; 2 | 3 | public class SchemaViolationType : ObjectType 4 | { 5 | protected override void Configure(IObjectTypeDescriptor descriptor) 6 | { 7 | descriptor.Field(t => t.Path).Type>(); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.GraphQL/Shared/SdlType.cs: -------------------------------------------------------------------------------- 1 | namespace Confix.Authoring.GraphQL; 2 | 3 | public class SdlType : StringType 4 | { 5 | public SdlType() : base("SDL", bind: BindingBehavior.Explicit) 6 | { 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.GraphQL/Shared/UserError.cs: -------------------------------------------------------------------------------- 1 | namespace Confix.Authoring.GraphQL.Applications; 2 | 3 | public class UserError : IUserError 4 | { 5 | public UserError(string message) 6 | { 7 | Message = message; 8 | } 9 | 10 | public string Code => GetType().Name; 11 | 12 | public string Message { get; } 13 | } 14 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.GraphQL/Variable/Extensions/VariableExtensions.cs: -------------------------------------------------------------------------------- 1 | using Confix.Authoring.Store; 2 | 3 | namespace Confix.Authoring.GraphQL; 4 | 5 | [ExtendObjectType(typeof(Variable))] 6 | public sealed class VariableExtensions 7 | { 8 | public async Task> GetChangeLogAsync( 9 | [Service] IChangeLogService service, 10 | [Parent] Variable application, 11 | CancellationToken cancellationToken) 12 | { 13 | return await service.GetByVariableId(application.Id, cancellationToken); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.GraphQL/Variable/Relay/VariableNode.cs: -------------------------------------------------------------------------------- 1 | namespace Confix.Authoring.GraphQL; 2 | 3 | [Node] 4 | [ExtendObjectType(typeof(Variable))] 5 | public sealed class VariableNode 6 | { 7 | [NodeResolver] 8 | public static Task GetVariableAsync( 9 | [Service] IVariableService service, 10 | Guid id, 11 | CancellationToken cancellationToken) 12 | { 13 | return service.GetByIdAsync(id, cancellationToken); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.GraphQL/Variable/VariableValueScopeType.cs: -------------------------------------------------------------------------------- 1 | namespace Confix.Authoring.GraphQL; 2 | 3 | public class VariableValueScopeType : UnionType 4 | { 5 | protected override void Configure(IUnionTypeDescriptor descriptor) 6 | { 7 | descriptor.Name(nameof(VariableValueScope)); 8 | 9 | // The object types that belong to this union 10 | descriptor.Type>(); 11 | descriptor.Type>(); 12 | descriptor.Type>(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.GraphQL/Viewer/Configuration/RolesRequestExecutorBuilderExtensions.cs: -------------------------------------------------------------------------------- 1 | using Confix.Authoring.GraphQL.Viewer; 2 | using HotChocolate.Execution.Configuration; 3 | using Microsoft.Extensions.DependencyInjection; 4 | 5 | namespace Confix.Authoring.GraphQL; 6 | 7 | public static class ViewerRequestExecutorBuilderExtensions 8 | { 9 | public static IRequestExecutorBuilder AddViewer(this IRequestExecutorBuilder builder) 10 | { 11 | // types 12 | builder.AddTypeExtension(); 13 | 14 | return builder; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.GraphQL/Viewer/Viewer.cs: -------------------------------------------------------------------------------- 1 | using Confix.Authentication.Authorization; 2 | 3 | namespace Confix.Authoring.GraphQL.Viewer; 4 | 5 | public sealed class Viewer 6 | { 7 | private readonly ISession _session; 8 | 9 | public Viewer(ISession session) 10 | { 11 | _session = session; 12 | } 13 | 14 | public string Name => _session.UserInfo.Name ?? _session.UserInfo.Email ?? _session.UserInfo.Id; 15 | 16 | public IEnumerable NamespaceGrants(Scope scope) 17 | => _session.GetGrantsForScope(scope); 18 | } 19 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.GraphQL/Viewer/ViewerQueries.cs: -------------------------------------------------------------------------------- 1 | using Confix.Authentication.Authorization; 2 | 3 | namespace Confix.Authoring.GraphQL.Viewer; 4 | 5 | [ExtendObjectType(OperationTypeNames.Query)] 6 | public sealed class ViewerQueries 7 | { 8 | public async ValueTask GetMe( 9 | [Service] ISessionAccessor accessor, 10 | CancellationToken cancellationToken) 11 | { 12 | return await accessor.GetSession(cancellationToken) is { } session 13 | ? new Viewer(session) 14 | : null; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.Host/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true 5 | }, 6 | "profiles": { 7 | "Authoring.Host": { 8 | "commandName": "Project", 9 | "launchUrl": "graphql", 10 | "environmentVariables": { 11 | "ASPNETCORE_ENVIRONMENT": "Development" 12 | }, 13 | "applicationUrl": "https://localhost:5000" 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.Host/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft": "Warning", 6 | "Microsoft.Hosting.Lifetime": "Information" 7 | } 8 | }, 9 | "ReverseProxy": { 10 | "Routes": { 11 | "route1": { 12 | "ClusterId": "cluster1", 13 | "Match": { 14 | "Path": "{**catch-all}" 15 | } 16 | } 17 | }, 18 | "Clusters": { 19 | "cluster1": { 20 | "Destinations": { 21 | "cluster1/destination1": { 22 | "Address": "http://localhost:3000" 23 | } 24 | } 25 | } 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.Messaging/Authoring.Messaging.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Confix.Authoring.Messaging 5 | Confix.Authoring.Messaging 6 | true 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.Messaging/AuthoringServerBuilderMessagingExtensions.cs: -------------------------------------------------------------------------------- 1 | using Confix.Messaging; 2 | using Microsoft.Extensions.DependencyInjection; 3 | 4 | namespace Confix.Authoring.Messaging; 5 | 6 | public static class AuthoringServerBuilderMessagingExtensions 7 | { 8 | public static IAuthoringServerBuilder ConfigureMessaging( 9 | this IAuthoringServerBuilder builder, 10 | Action configure) 11 | { 12 | builder.Services.AddSingleton(); 13 | builder.Services.ConfigureMessaging(Configure); 14 | 15 | return builder; 16 | 17 | void Configure(IMessagingBuilder messagingBuilder) 18 | { 19 | messagingBuilder.Configurator.AddRequestClient(); 20 | configure(messagingBuilder); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.Messaging/ICreateVaultConfigClient.cs: -------------------------------------------------------------------------------- 1 | using Confix.Messaging; 2 | 3 | namespace Confix.Authoring.Messaging; 4 | 5 | public interface ICreateVaultConfigClient 6 | { 7 | Task ExecuteAsync( 8 | CreateVaultConfigRequest request, 9 | CancellationToken cancellationToken); 10 | } 11 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.Store.Mongo/Applications/ApplicationCollectionConfiguration.cs: -------------------------------------------------------------------------------- 1 | using MongoDB.Driver; 2 | using MongoDB.Extensions.Context; 3 | 4 | namespace Confix.Authoring.Store.Mongo.Configuration; 5 | 6 | internal sealed class ApplicationCollectionConfiguration : 7 | IMongoCollectionConfiguration 8 | { 9 | public void OnConfiguring( 10 | IMongoCollectionBuilder builder) 11 | { 12 | builder 13 | .WithCollectionName("application") 14 | .AddBsonClassMap( 15 | cm => 16 | { 17 | cm.AutoMap(); 18 | cm.MapIdMember(c => c.Id); 19 | }) 20 | .WithCollectionSettings(s => s.ReadConcern = ReadConcern.Majority) 21 | .WithCollectionSettings(s => s.ReadPreference = ReadPreference.Nearest); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.Store.Mongo/Authoring.Store.Mongo.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Confix.Authoring.Store.Mongo 5 | Confix.Authoring.Store.Mongo 6 | true 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.Store.Mongo/Environments/EnvironmentCollectionConfiguration.cs: -------------------------------------------------------------------------------- 1 | using MongoDB.Driver; 2 | using MongoDB.Extensions.Context; 3 | 4 | namespace Confix.Authoring.Store.Mongo.Configuration; 5 | 6 | internal sealed class EnvironmentCollectionConfiguration 7 | : IMongoCollectionConfiguration 8 | { 9 | public void OnConfiguring(IMongoCollectionBuilder builder) 10 | { 11 | builder 12 | .WithCollectionName("environment") 13 | .AddBsonClassMap( 14 | cm => 15 | { 16 | cm.AutoMap(); 17 | cm.MapIdMember(c => c.Id); 18 | }) 19 | .WithCollectionSettings(s => s.ReadConcern = ReadConcern.Majority) 20 | .WithCollectionSettings(s => s.ReadPreference = ReadPreference.Nearest); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.Store.Mongo/Groups/GroupCollectionConfiguration.cs: -------------------------------------------------------------------------------- 1 | using Confix.Authentication.Authorization; 2 | using MongoDB.Driver; 3 | using MongoDB.Extensions.Context; 4 | 5 | namespace Confix.Authoring.Store.Mongo.Configuration; 6 | 7 | internal sealed class GroupCollectionConfiguration : IMongoCollectionConfiguration 8 | { 9 | public void OnConfiguring(IMongoCollectionBuilder builder) 10 | { 11 | builder 12 | .WithCollectionName("groups") 13 | .AddBsonClassMap( 14 | cm => 15 | { 16 | cm.AutoMap(); 17 | cm.MapIdMember(c => c.Id); 18 | }) 19 | .WithCollectionSettings(s => s.ReadConcern = ReadConcern.Majority) 20 | .WithCollectionSettings(s => s.ReadPreference = ReadPreference.Nearest); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.Store.Mongo/ImmutableHashSetSerializer.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Immutable; 2 | using MongoDB.Bson.Serialization.Serializers; 3 | 4 | namespace Confix.Authoring.Store.Mongo; 5 | 6 | internal sealed class ImmutableHashSetSerializer 7 | : EnumerableInterfaceImplementerSerializerBase, TValue> 8 | { 9 | protected override object CreateAccumulator() 10 | { 11 | return ImmutableHashSet.CreateBuilder(); 12 | } 13 | 14 | protected override ImmutableHashSet FinalizeResult(object accumulator) 15 | { 16 | return ((ImmutableHashSet.Builder)accumulator).ToImmutable(); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.Store.Mongo/SerializerHelpers.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Immutable; 2 | using MongoDB.Bson.Serialization; 3 | 4 | namespace Confix.Authoring.Store.Mongo; 5 | 6 | internal static class SerializerHelpers 7 | { 8 | private static bool _isConfigured; 9 | 10 | public static void RegisterSerializers() 11 | { 12 | if (_isConfigured) 13 | { 14 | return; 15 | } 16 | 17 | ConfigureSerializers(); 18 | 19 | _isConfigured = true; 20 | } 21 | 22 | private static void ConfigureSerializers() 23 | { 24 | BsonSerializer.RegisterGenericSerializerDefinition( 25 | typeof(ImmutableHashSet<>), 26 | typeof(ImmutableHashSetSerializer<>)); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.Store.Mongo/Variables/VariableCollectionConfiguration.cs: -------------------------------------------------------------------------------- 1 | using MongoDB.Driver; 2 | using MongoDB.Extensions.Context; 3 | 4 | namespace Confix.Authoring.Store.Mongo.Configuration; 5 | 6 | internal sealed class VariableCollectionConfiguration : IMongoCollectionConfiguration 7 | { 8 | public void OnConfiguring(IMongoCollectionBuilder builder) 9 | { 10 | builder 11 | .WithCollectionName("variable") 12 | .AddBsonClassMap( 13 | cm => 14 | { 15 | cm.AutoMap(); 16 | cm.MapIdMember(c => c.Id); 17 | }) 18 | .WithCollectionSettings(s => s.ReadConcern = ReadConcern.Majority) 19 | .WithCollectionSettings(s => s.ReadPreference = ReadPreference.Nearest); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.UI/.gitignore: -------------------------------------------------------------------------------- 1 | UI/ 2 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.UI/Authoring.UI.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Confix.Authoring.UI 5 | Confix.Authoring.UI 6 | true 7 | $(NoWarn);1591 8 | true 9 | 7f119445-764d-4a74-8955-7cbfc802d0ab 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.UI/EmbeddedUIMiddlewareExtensions.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Builder; 2 | 3 | namespace Confix.Authoring.UI; 4 | 5 | public static class EmbeddedUiMiddlewareExtensions 6 | { 7 | public static IApplicationBuilder UseConfixUi(this IApplicationBuilder builder) 8 | { 9 | return builder.UseMiddleware(); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring.UI/UI/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SwissLife-OSS/Confix-Unloaded/8be52f1ee677d49c7fa515db42ad51aa448dfc8b/src/Backend/src/Authoring.UI/UI/.keep -------------------------------------------------------------------------------- /src/Backend/src/Authoring/Authoring.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Confix.Authoring 5 | Confix.Authoring 6 | true 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring/Configuration/AuthoringApplicationBuilderExtensions.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Builder; 2 | 3 | namespace Confix.Authoring; 4 | 5 | public static class AuthoringApplicationBuilderExtensions 6 | { 7 | public static IApplicationBuilder UseAuthoringServer(this IApplicationBuilder builder) 8 | { 9 | builder.UseRouting(); 10 | builder.UseAuthentication(); 11 | builder.UseAuthorization(); 12 | builder.UseCors(); 13 | builder.UseEndpoints(endpoints => 14 | { 15 | endpoints.AddSessionManagement(); 16 | endpoints.MapGraphQL(); 17 | }); 18 | 19 | return builder; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring/Configuration/AuthoringServerBuilder.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.DependencyInjection; 2 | 3 | namespace Confix.Authoring; 4 | 5 | internal sealed class AuthoringServerBuilder : IAuthoringServerBuilder 6 | { 7 | public AuthoringServerBuilder(IServiceCollection services) 8 | { 9 | Services = services; 10 | } 11 | 12 | public IServiceCollection Services { get; } 13 | } 14 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring/Configuration/ConfixServerBuilderExtensions.cs: -------------------------------------------------------------------------------- 1 | using Confix.Authentication.Authorization; 2 | using Confix.Authoring.GraphQL; 3 | using Microsoft.Extensions.DependencyInjection; 4 | 5 | namespace Confix.Authoring; 6 | 7 | public static class ConfixAuthoringServerBuilderExtensions 8 | { 9 | public static IAuthoringServerBuilder AddConfixAuthoringServer(this IServiceCollection services) 10 | { 11 | services.AddMemoryCache(); 12 | 13 | services.AddSeedWorker(); 14 | services.AddAuthoringGraphQl(); 15 | services.AddSessionAccessor(); 16 | services.AddAuthorizationAndPolicies(); 17 | services.AddAuthoringCore(); 18 | 19 | var builder = new AuthoringServerBuilder(services); 20 | 21 | return builder; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring/Seed/AdminRequirementOptions.cs: -------------------------------------------------------------------------------- 1 | namespace Confix.Authoring; 2 | 3 | public sealed class AdminRequirementOptions 4 | { 5 | public string Type { get; set; } = string.Empty; 6 | 7 | public string Value { get; set; } = string.Empty; 8 | } 9 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring/Seed/SeedExtensions.cs: -------------------------------------------------------------------------------- 1 | using Confix.Common; 2 | using Microsoft.Extensions.DependencyInjection; 3 | 4 | namespace Confix.Authoring; 5 | 6 | public static class SeedExtensions 7 | { 8 | public static IServiceCollection AddSeedWorker( 9 | this IServiceCollection services, 10 | string pathToConfig = Settings.Confix.Authoring.Seed.AdminRequirement.Section) 11 | { 12 | services.AddOptions().BindConfiguration(pathToConfig); 13 | 14 | services.AddHostedService(); 15 | 16 | return services; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/Backend/src/Authoring/Seed/SeedOptions.cs: -------------------------------------------------------------------------------- 1 | namespace Confix.Authoring; 2 | 3 | public class SeedOptions 4 | { 5 | public AdminRequirementOptions? AdminRequirement { get; set; } = null; 6 | } 7 | -------------------------------------------------------------------------------- /src/Backend/src/Common/Common.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Confix.Common 5 | Confix.Common 6 | true 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/Backend/src/Common/Exceptions/UnauthorizedOperationException.cs: -------------------------------------------------------------------------------- 1 | namespace Confix.Common.Exceptions; 2 | 3 | public class UnauthorizedOperationException : Exception 4 | { 5 | public UnauthorizedOperationException() : base("You are not allowed to perform this operation") 6 | { 7 | } 8 | 9 | public string Code { get; set; } = "UNAUTHORIZED_OPERATION_EXCEPTION"; 10 | } 11 | -------------------------------------------------------------------------------- /src/Backend/src/Common/TaskHelper.cs: -------------------------------------------------------------------------------- 1 | namespace Confix.Common; 2 | 3 | public static class TaskHelper 4 | { 5 | public static async Task<(T1, T2)> WhenAll(Task t1, Task t2) 6 | { 7 | return (await t1, await t2); 8 | } 9 | 10 | public static async Task<(T1, T2, T3)> WhenAll( 11 | Task t1, 12 | Task t2, 13 | Task t3) 14 | { 15 | return (await t1, await t2, await t3); 16 | } 17 | 18 | public static async Task<(T1, T2, T3, T4)> WhenAll( 19 | Task t1, 20 | Task t2, 21 | Task t3, 22 | Task t4) 23 | { 24 | return (await t1, await t2, await t3, await t4); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/Backend/src/Common/Token/ITokenProvider.cs: -------------------------------------------------------------------------------- 1 | namespace Confix.Common.Token; 2 | 3 | public interface ITokenProvider 4 | { 5 | string GetPrefix(string token); 6 | 7 | Token GenerateToken(); 8 | 9 | bool ValidateToken(string token, string plainText); 10 | } 11 | -------------------------------------------------------------------------------- /src/Backend/src/Common/Token/Token.cs: -------------------------------------------------------------------------------- 1 | namespace Confix.Common.Token; 2 | 3 | public readonly record struct Token(string PlainText, string Hashed); 4 | -------------------------------------------------------------------------------- /src/Backend/src/Common/Token/TokenProviderServiceCollectionExtensions.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Identity; 2 | using Microsoft.Extensions.DependencyInjection; 3 | 4 | namespace Confix.Common.Token; 5 | 6 | public static class TokenProviderServiceCollectionExtensions 7 | { 8 | public static IServiceCollection AddTokenProvider(this IServiceCollection services) 9 | { 10 | services.AddSingleton, PasswordHasher>(); 11 | services.AddSingleton(); 12 | 13 | return services; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/Backend/src/Common/TransactionHelper.cs: -------------------------------------------------------------------------------- 1 | using System.Transactions; 2 | 3 | namespace Confix.Common; 4 | 5 | public static class Transactions 6 | { 7 | public static TransactionScope Create( 8 | TransactionScopeOption options = TransactionScopeOption.Required, 9 | TransactionScopeAsyncFlowOption asyncFlowOption = TransactionScopeAsyncFlowOption.Enabled) 10 | { 11 | return new TransactionScope(options, asyncFlowOption); 12 | } 13 | } 14 | 15 | -------------------------------------------------------------------------------- /src/Backend/src/CryptoProviders.Abstractions/CryptoProviderDescriptor.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.DependencyInjection; 2 | 3 | namespace Confix.CryptoProviders; 4 | 5 | public sealed class CryptoProviderDescriptor : ICryptoProviderDescriptor 6 | { 7 | public CryptoProviderDescriptor(IServiceCollection services) 8 | { 9 | Services = services; 10 | } 11 | 12 | public IServiceCollection Services { get; } 13 | } 14 | -------------------------------------------------------------------------------- /src/Backend/src/CryptoProviders.Abstractions/CryptoProviders.Abstractions.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Confix.CryptoProvider.Abstractions 5 | Confix.CryptoProvider.Abstractions 6 | true 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/Backend/src/CryptoProviders.Abstractions/Encryption/EncryptedValue.cs: -------------------------------------------------------------------------------- 1 | namespace Confix.CryptoProviders; 2 | 3 | public sealed record EncryptedValue(string Value, string Iv, string Topic); 4 | -------------------------------------------------------------------------------- /src/Backend/src/CryptoProviders.Abstractions/Encryption/IDecryptor.cs: -------------------------------------------------------------------------------- 1 | namespace Confix.CryptoProviders; 2 | 3 | public interface IDecryptor 4 | { 5 | ValueTask DecryptAsync( 6 | EncryptedValue encryptedValue, 7 | CancellationToken cancellationToken); 8 | } 9 | -------------------------------------------------------------------------------- /src/Backend/src/CryptoProviders.Abstractions/Encryption/IEncryptor.cs: -------------------------------------------------------------------------------- 1 | namespace Confix.CryptoProviders; 2 | 3 | public interface IEncryptor 4 | { 5 | ValueTask EncryptAsync( 6 | string topic, 7 | string value, 8 | CancellationToken cancellationToken); 9 | } 10 | -------------------------------------------------------------------------------- /src/Backend/src/CryptoProviders.Abstractions/Extensions/EncryptorExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace Confix.CryptoProviders; 2 | 3 | public static class EncryptorExtensions 4 | { 5 | public static async Task EncryptAsync( 6 | this IEncryptor encryptor, 7 | string topic, 8 | string value, 9 | Guid environmentId, 10 | CancellationToken cancellationToken) 11 | { 12 | return await encryptor.EncryptAsync($"{topic}-{environmentId:N}", value, cancellationToken); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/Backend/src/CryptoProviders.Abstractions/ICryptoProviderDescriptor.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.DependencyInjection; 2 | 3 | namespace Confix.CryptoProviders; 4 | 5 | public interface ICryptoProviderDescriptor 6 | { 7 | IServiceCollection Services { get; } 8 | } 9 | 10 | -------------------------------------------------------------------------------- /src/Backend/src/CryptoProviders.Abstractions/IEncryptionKeyProvider.cs: -------------------------------------------------------------------------------- 1 | namespace Confix.CryptoProviders; 2 | 3 | public interface IEncryptionKeyProvider 4 | { 5 | ValueTask GetKeyAsync(string topic, CancellationToken cancellationToken); 6 | } 7 | -------------------------------------------------------------------------------- /src/Backend/src/CryptoProviders.Abstractions/Secrets/DataEncryptionKey.cs: -------------------------------------------------------------------------------- 1 | namespace Confix.CryptoProviders; 2 | 3 | public sealed class DataEncryptionKey 4 | { 5 | public DataEncryptionKey( 6 | Guid id, 7 | DateTime updatedAt, 8 | string topic, 9 | string key, 10 | string encryptionAlgorithm) 11 | { 12 | Id = id; 13 | UpdatedAt = updatedAt; 14 | Topic = topic; 15 | Key = key; 16 | EncryptionAlgorithm = encryptionAlgorithm; 17 | } 18 | 19 | public Guid Id { get; init; } 20 | 21 | public DateTime UpdatedAt { get; init; } 22 | 23 | public string Topic { get; init; } 24 | 25 | public string EncryptionAlgorithm { get; init; } 26 | 27 | public string Key { get; init; } 28 | } 29 | -------------------------------------------------------------------------------- /src/Backend/src/CryptoProviders.Abstractions/Secrets/IDataEncryptionKeyRepository.cs: -------------------------------------------------------------------------------- 1 | namespace Confix.CryptoProviders; 2 | 3 | public interface IDataEncryptionKeyRepository 4 | { 5 | Task GetSecretByTopicAsync( 6 | string topic, 7 | CancellationToken cancellationToken); 8 | 9 | Task GetOrCreateByTopicAsync( 10 | DataEncryptionKey dataEncryptionKey, 11 | CancellationToken cancellationToken); 12 | } 13 | -------------------------------------------------------------------------------- /src/Backend/src/CryptoProviders.AzureKeyVault/Configuration/AzureKeyVaultOptions.cs: -------------------------------------------------------------------------------- 1 | namespace Confix.CryptoProviders.AzureKeyVault; 2 | 3 | public sealed class AzureKeyVaultOptions 4 | { 5 | public string Url { get; set; } = default!; 6 | 7 | public string Algorithm { get; set; } = "RSA-OAEP-256"; 8 | 9 | public string TenantId { get; set; } = default!; 10 | 11 | public string ClientId { get; set; } = default!; 12 | 13 | public string ClientSecret { get; set; } = default!; 14 | } 15 | -------------------------------------------------------------------------------- /src/Backend/src/CryptoProviders.AzureKeyVault/ICryptographyClientFactory.cs: -------------------------------------------------------------------------------- 1 | using Azure.Security.KeyVault.Keys; 2 | using Azure.Security.KeyVault.Keys.Cryptography; 3 | 4 | namespace Confix.CryptoProviders.AzureKeyVault; 5 | 6 | internal interface ICryptographyClientFactory 7 | { 8 | CryptographyClient CreateCryptoClient(string keyId); 9 | 10 | KeyClient CreateKeyClient(string keyId); 11 | } 12 | -------------------------------------------------------------------------------- /src/Backend/src/CryptoProviders.AzureKeyVault/IKeyEncryptionKeyCache.cs: -------------------------------------------------------------------------------- 1 | namespace Confix.CryptoProviders.AzureKeyVault; 2 | 3 | internal interface IKeyEncryptionKeyCache 4 | { 5 | ValueTask GetOrCreateAsync(string topic, Func> fetchKey); 6 | } 7 | -------------------------------------------------------------------------------- /src/Backend/src/CryptoProviders.Mongo/CryptoProviders.Mongo.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Confix.CryptoProvider.Mongo 5 | Confix.CryptoProvider.Mongo 6 | true 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /src/Backend/src/CryptoProviders.Mongo/ICryptoDbContext.cs: -------------------------------------------------------------------------------- 1 | using MongoDB.Driver; 2 | 3 | namespace Confix.CryptoProviders.Mongo; 4 | 5 | public interface ICryptoDbContext 6 | { 7 | IMongoCollection Secrets { get; } 8 | } 9 | -------------------------------------------------------------------------------- /src/Backend/src/CryptoProviders/CryptoProviders.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Confix.CryptoProvider 5 | Confix.CryptoProvider 6 | true 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/Backend/src/CryptoProviders/CypherAndIv.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json; 2 | 3 | namespace Confix.CryptoProviders; 4 | 5 | public record struct CypherAndIv(string Cypher, string Iv) 6 | { 7 | public string Serialize() => JsonSerializer.Serialize(this); 8 | 9 | public static CypherAndIv Deserialize(string value) 10 | => JsonSerializer.Deserialize(value); 11 | } 12 | -------------------------------------------------------------------------------- /src/Backend/src/Messaging.RabbitMQ/Messaging.RabbitMQ.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Confix.Messaging.RabbitMQ 5 | Confix.Messaging.RabbitMQ 6 | true 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /src/Backend/src/Messaging.RabbitMQ/RabbitMqMessagingUrlFactory.cs: -------------------------------------------------------------------------------- 1 | namespace Confix.Messaging.RabbitMQ; 2 | 3 | internal class RabbitMqMessagingUrlFactory : IMessagingUrlFactory 4 | { 5 | public Uri CreateRequestClientUrl(string name, string environment) 6 | { 7 | return new Uri($"exchange:{name}-{environment}"); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/Backend/src/Messaging.RabbitMQ/RabbitMqOptions.cs: -------------------------------------------------------------------------------- 1 | namespace Confix.Messaging.RabbitMQ; 2 | 3 | public class RabbitMqOptions 4 | { 5 | public string HostUrl { get; set; } = string.Empty; 6 | 7 | public string Path { get; set; } = "/"; 8 | 9 | public string Username { get; set; } = string.Empty; 10 | 11 | public string Password { get; set; } = string.Empty; 12 | } 13 | -------------------------------------------------------------------------------- /src/Backend/src/Messaging.ServiceBus/Messaging.ServiceBus.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Confix.Messaging.ServiceBus 5 | Confix.Messaging.ServiceBus 6 | true 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /src/Backend/src/Messaging.ServiceBus/ServiceBusMessagingUrlFactory.cs: -------------------------------------------------------------------------------- 1 | namespace Confix.Messaging.ServiceBus; 2 | 3 | internal class ServiceBusMessagingUrlFactory : IMessagingUrlFactory 4 | { 5 | public Uri CreateRequestClientUrl(string name, string environment) 6 | { 7 | return new Uri($"queue:{name}-{environment}"); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/Backend/src/Messaging.ServiceBus/ServiceBusOptions.cs: -------------------------------------------------------------------------------- 1 | namespace Confix.Messaging.ServiceBus; 2 | 3 | public class ServiceBusOptions 4 | { 5 | public string ConnectionString { get; set; } = string.Empty; 6 | } 7 | -------------------------------------------------------------------------------- /src/Backend/src/Messaging/IMessagingBuilder.cs: -------------------------------------------------------------------------------- 1 | using MassTransit; 2 | using Microsoft.Extensions.DependencyInjection; 3 | 4 | namespace Confix.Messaging; 5 | 6 | public interface IMessagingBuilder 7 | { 8 | IBusRegistrationConfigurator Configurator { get; } 9 | 10 | IServiceCollection ServiceCollection { get; } 11 | } 12 | -------------------------------------------------------------------------------- /src/Backend/src/Messaging/IMessagingUrlFactory.cs: -------------------------------------------------------------------------------- 1 | namespace Confix.Messaging; 2 | 3 | public interface IMessagingUrlFactory 4 | { 5 | Uri CreateRequestClientUrl(string name, string environment); 6 | } 7 | -------------------------------------------------------------------------------- /src/Backend/src/Messaging/Messages/CreateVaultConfigRequest.cs: -------------------------------------------------------------------------------- 1 | namespace Confix.Messaging; 2 | 3 | public record CreateVaultConfigRequest( 4 | string ApplicationName, 5 | string ApplicationPartName, 6 | string EnvironmentName, 7 | string Configuration); 8 | -------------------------------------------------------------------------------- /src/Backend/src/Messaging/Messages/CreateVaultConfigResponse.cs: -------------------------------------------------------------------------------- 1 | namespace Confix.Messaging; 2 | 3 | public record CreateVaultConfigResponse( 4 | string ApplicationName, 5 | string ApplicationPartName, 6 | string EnvironmentName, 7 | string AccessToken, 8 | string RefreshToken); 9 | -------------------------------------------------------------------------------- /src/Backend/src/Messaging/Messaging.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Confix.Messaging 5 | Confix.Messaging 6 | true 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/Backend/src/Messaging/MessagingBuilder.cs: -------------------------------------------------------------------------------- 1 | using MassTransit; 2 | using Microsoft.Extensions.DependencyInjection; 3 | 4 | namespace Confix.Messaging; 5 | 6 | public sealed class MessagingBuilder 7 | : IMessagingBuilder 8 | { 9 | public MessagingBuilder( 10 | IBusRegistrationConfigurator configurator, IServiceCollection serviceCollection) 11 | { 12 | Configurator = configurator; 13 | ServiceCollection = serviceCollection; 14 | } 15 | 16 | public IBusRegistrationConfigurator Configurator { get; } 17 | 18 | public IServiceCollection ServiceCollection { get; } 19 | } 20 | -------------------------------------------------------------------------------- /src/Backend/src/Messaging/MessagingServiceCollectionConfigurationExtensions.cs: -------------------------------------------------------------------------------- 1 | using MassTransit; 2 | using Microsoft.Extensions.DependencyInjection; 3 | 4 | namespace Confix.Messaging; 5 | 6 | public static class MessagingServiceCollectionConfigurationExtensions 7 | { 8 | public static IServiceCollection ConfigureMessaging( 9 | this IServiceCollection services, 10 | Action configure) 11 | { 12 | services.AddMassTransit(x => 13 | { 14 | configure(new MessagingBuilder(x, services)); 15 | }); 16 | return services; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/Backend/src/Messaging/RequestClient.cs: -------------------------------------------------------------------------------- 1 | namespace Confix.Messaging; 2 | 3 | public static class RequestClients 4 | { 5 | public static readonly string CreateVaultConfig = "create-vault-config"; 6 | } 7 | -------------------------------------------------------------------------------- /src/Backend/src/Samples.Host/Program.cs: -------------------------------------------------------------------------------- 1 | var builder = WebApplication.CreateBuilder(args); 2 | 3 | builder.Configuration.AddVaultConfiguration("Test-App", "Test-Part"); 4 | 5 | var app = builder.Build(); 6 | 7 | app.MapGet("/", () => "Hello World!"); 8 | 9 | app.Run(); 10 | -------------------------------------------------------------------------------- /src/Backend/src/Samples.Host/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true 5 | }, 6 | "profiles": { 7 | "Authoring.Host": { 8 | "commandName": "Project", 9 | "launchUrl": "graphql", 10 | "environmentVariables": { 11 | "ASPNETCORE_ENVIRONMENT": "Development" 12 | }, 13 | "applicationUrl": "http://localhost:5000" 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /src/Backend/src/Samples.Host/Samples.Host.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Confix.Samples.Host 5 | Confix.Samples 6 | false 7 | FFA5BA86-B890-4329-B7A5-ABEC3DAC9C53 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/Backend/src/Samples.Host/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft": "Warning", 6 | "Microsoft.Hosting.Lifetime": "Information" 7 | } 8 | }, 9 | "ReverseProxy": { 10 | "Routes": { 11 | "route1": { 12 | "ClusterId": "cluster1", 13 | "Match": { 14 | "Path": "{**catch-all}" 15 | } 16 | } 17 | }, 18 | "Clusters": { 19 | "cluster1": { 20 | "Destinations": { 21 | "cluster1/destination1": { 22 | "Address": "http://localhost:3000" 23 | } 24 | } 25 | } 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/Backend/src/Tooling/.graphqlrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "schema": "schema.graphql", 3 | "documents": "**/*.graphql", 4 | "extensions": { 5 | "strawberryShake": { 6 | "name": "ConfixClient", 7 | "url": "http://localhost:5000/graphql/", 8 | "dependencyInjection": true, 9 | "strictSchemaValidation": true, 10 | "noStore": true 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/Backend/src/Tooling/Bind.cs: -------------------------------------------------------------------------------- 1 | using System.CommandLine.Binding; 2 | using Microsoft.Extensions.DependencyInjection; 3 | 4 | internal static class Bind 5 | { 6 | public static ServiceProviderBinder FromServiceProvider() where T : notnull 7 | => ServiceProviderBinder.Instance; 8 | 9 | internal sealed class ServiceProviderBinder : BinderBase where T : notnull 10 | { 11 | public static ServiceProviderBinder Instance { get; } = new(); 12 | 13 | protected override T GetBoundValue(BindingContext bindingContext) 14 | => bindingContext.GetRequiredService(); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/Backend/src/Tooling/ClaimCommand.graphql: -------------------------------------------------------------------------------- 1 | mutation ClaimApplicationPart($input: ClaimVersionInput!) { 2 | claimVersion(input: $input){ 3 | errors { 4 | ...Error 5 | } 6 | result { 7 | version { 8 | ...ClaimedVersion 9 | } 10 | decryptionKey 11 | token 12 | } 13 | } 14 | } 15 | 16 | fragment ClaimedVersion on ClaimedVersion { 17 | id 18 | tag 19 | claimedAt 20 | publishedApplicationPart { 21 | version 22 | } 23 | } 24 | 25 | fragment Error on UserError { 26 | message 27 | code 28 | } 29 | -------------------------------------------------------------------------------- /src/Backend/src/Tooling/ConfixRootCommand.cs: -------------------------------------------------------------------------------- 1 | using System.CommandLine; 2 | using Confix.Tooling.Option; 3 | 4 | namespace Confix.Tooling; 5 | 6 | internal sealed class ConfixRootCommand : Command 7 | { 8 | public ConfixRootCommand() : base("confix") 9 | { 10 | AddGlobalOption(Required.Instance); 11 | AddGlobalOption(Required.Instance); 12 | AddGlobalOption(Optional.Instance); 13 | AddCommand(new ClaimCommand()); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/Backend/src/Tooling/Extensions/ExitException.cs: -------------------------------------------------------------------------------- 1 | internal sealed class ExitException : Exception 2 | { 3 | public ExitException() : base("") 4 | { 5 | } 6 | 7 | public ExitException(string message) : base(message) 8 | { 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/Backend/src/Tooling/Helpers/ExitCodes.cs: -------------------------------------------------------------------------------- 1 | public static class ExitCodes 2 | { 3 | public const int Success = 0; 4 | public const int Error = 1; 5 | } 6 | -------------------------------------------------------------------------------- /src/Backend/src/Tooling/Options/ApiKeyOption.cs: -------------------------------------------------------------------------------- 1 | using System.CommandLine; 2 | 3 | internal sealed class ApiKeyOption : Option 4 | { 5 | public ApiKeyOption() : base("--api-key") 6 | { 7 | Description = "The api key for authorization on confix"; 8 | AddAlias("-k"); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/Backend/src/Tooling/Options/AppOption.cs: -------------------------------------------------------------------------------- 1 | using System.CommandLine; 2 | 3 | internal sealed class AppOption : Option 4 | { 5 | public AppOption() : base("--app") 6 | { 7 | Description = "Specifies the name of the published application"; 8 | AddAlias("-a"); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/Backend/src/Tooling/Options/EnvironmentOption.cs: -------------------------------------------------------------------------------- 1 | using System.CommandLine; 2 | 3 | internal sealed class EnvironmentOption : Option 4 | { 5 | public EnvironmentOption() : base("--environment") 6 | { 7 | Description = "Specifies the name of the environment"; 8 | AddAlias("-e"); 9 | AddAlias("-env"); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/Backend/src/Tooling/Options/JsonOption.cs: -------------------------------------------------------------------------------- 1 | using System.CommandLine; 2 | 3 | internal sealed class JsonOption : Option 4 | { 5 | public JsonOption() : base("--json") 6 | { 7 | Description = "The output will be rendered as json"; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/Backend/src/Tooling/Options/Optional.cs: -------------------------------------------------------------------------------- 1 | namespace Confix.Tooling.Option; 2 | 3 | internal static class Optional where TOption : System.CommandLine.Option, new() 4 | { 5 | private static TOption? _instance; 6 | 7 | public static TOption Instance { get => _instance ??= new() { IsRequired = false }; } 8 | } 9 | -------------------------------------------------------------------------------- /src/Backend/src/Tooling/Options/PartOption.cs: -------------------------------------------------------------------------------- 1 | using System.CommandLine; 2 | 3 | internal sealed class PartOption : Option 4 | { 5 | public PartOption() : base("--part") 6 | { 7 | Description = "Specifies the name of the published application part"; 8 | AddAlias("-p"); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/Backend/src/Tooling/Options/Required.cs: -------------------------------------------------------------------------------- 1 | namespace Confix.Tooling.Option; 2 | 3 | internal static class Required where TOption : System.CommandLine.Option, new() 4 | { 5 | private static TOption? _instance; 6 | 7 | public static TOption Instance { get => _instance ??= new() { IsRequired = true }; } 8 | } 9 | -------------------------------------------------------------------------------- /src/Backend/src/Tooling/Options/TagOption.cs: -------------------------------------------------------------------------------- 1 | using System.CommandLine; 2 | 3 | internal sealed class TagOption : Option 4 | { 5 | public TagOption() : base("--tag") 6 | { 7 | Description = "Specifies the tag"; 8 | AddAlias("-t"); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/Backend/src/Tooling/Options/UrlOption.cs: -------------------------------------------------------------------------------- 1 | using System.CommandLine; 2 | 3 | internal sealed class UrlOption : Option 4 | { 5 | public UrlOption() : base("--url") 6 | { 7 | Description = "The url of the Confix service."; 8 | AddAlias("-u"); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/Backend/src/Tooling/Program.cs: -------------------------------------------------------------------------------- 1 | // See https://aka.ms/new-console-template for more information 2 | 3 | using System.CommandLine.Parsing; 4 | using Confix.Tooling; 5 | 6 | return await new ConfixCommandLine().Build().InvokeAsync(args); 7 | -------------------------------------------------------------------------------- /src/Backend/src/Tooling/persisted/queries.json: -------------------------------------------------------------------------------- 1 | {"a3239eccea76f7eaa99c3e4bf24d3722":"mutation ClaimApplicationPart($input: ClaimVersionInput!) { claimVersion(input: $input) { __typename errors { __typename ... Error } result { __typename version { __typename ... ClaimedVersion } decryptionKey token } } } fragment Error on UserError { message code } fragment ClaimedVersion on ClaimedVersion { id tag claimedAt publishedApplicationPart { __typename version } }"} -------------------------------------------------------------------------------- /src/Backend/src/Tooling/schema.extensions.graphql: -------------------------------------------------------------------------------- 1 | scalar _KeyFieldSet 2 | 3 | directive @key(fields: _KeyFieldSet!) on SCHEMA | OBJECT 4 | 5 | directive @serializationType(name: String!) on SCALAR 6 | 7 | directive @runtimeType(name: String!) on SCALAR 8 | 9 | directive @enumValue(value: String!) on ENUM_VALUE 10 | 11 | directive @rename(name: String!) on INPUT_FIELD_DEFINITION | INPUT_OBJECT | ENUM | ENUM_VALUE 12 | 13 | extend schema @key(fields: "id") 14 | -------------------------------------------------------------------------------- /src/Backend/src/Vault.Abstractions/Configuration/TokenPair.cs: -------------------------------------------------------------------------------- 1 | namespace Confix.Vault.Abstractions; 2 | 3 | public record TokenPair(string AccessToken, string RefreshToken); 4 | -------------------------------------------------------------------------------- /src/Backend/src/Vault.Abstractions/Configuration/Transport/GetConfigurationResponse.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json; 2 | 3 | namespace Vault.Host.Configuration.Transport; 4 | 5 | public record GetConfigurationResponse(JsonDocument? Configuration, string? Error) 6 | { 7 | public static GetConfigurationResponse FromError(string error) 8 | { 9 | return new GetConfigurationResponse(null, error); 10 | } 11 | 12 | public static GetConfigurationResponse FromSuccess(JsonDocument content) 13 | { 14 | return new GetConfigurationResponse(content, null); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/Backend/src/Vault.Abstractions/Configuration/Transport/PutConfigurationRequest.cs: -------------------------------------------------------------------------------- 1 | namespace Vault.Host.Configuration.Transport; 2 | 3 | public record PutConfigurationRequest( 4 | string ApplicationName, 5 | string ApplicationPartName, 6 | string EnvironmentName, 7 | string Configuration); 8 | -------------------------------------------------------------------------------- /src/Backend/src/Vault.Abstractions/Configuration/Transport/PutConfigurationResponse.cs: -------------------------------------------------------------------------------- 1 | namespace Vault.Host.Configuration.Transport; 2 | 3 | public record PutConfigurationResponse(string Token, string RefreshToken); 4 | -------------------------------------------------------------------------------- /src/Backend/src/Vault.Abstractions/Configuration/Transport/RefreshConfigurationRequest.cs: -------------------------------------------------------------------------------- 1 | namespace Vault.Host.Configuration.Transport; 2 | 3 | public record RefreshConfigurationRequest( 4 | string ApplicationName, 5 | string ApplicationPartName, 6 | string EnvironmentName, 7 | string Configuration, 8 | string RefreshToken); 9 | -------------------------------------------------------------------------------- /src/Backend/src/Vault.Abstractions/Configuration/Transport/RefreshConfigurationResponse.cs: -------------------------------------------------------------------------------- 1 | namespace Vault.Host.Configuration.Transport; 2 | 3 | public record RefreshConfigurationResponse; 4 | -------------------------------------------------------------------------------- /src/Backend/src/Vault.Abstractions/IVaultServerBuilder.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.DependencyInjection; 2 | 3 | namespace Confix.Vault; 4 | 5 | public interface IVaultServerBuilder 6 | { 7 | IServiceCollection Services { get; } 8 | } 9 | -------------------------------------------------------------------------------- /src/Backend/src/Vault.Abstractions/Vault.Abstractions.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Confix.Vault.Abstractions 5 | Confix.Vault 6 | true 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/Backend/src/Vault.Abstractions/WellKnown.cs: -------------------------------------------------------------------------------- 1 | namespace Confix.Vault; 2 | 3 | public static class WellKnown 4 | { 5 | public static class Headers 6 | { 7 | public const string TokenHeader = "x-confix-token"; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/Backend/src/Vault.Authentication/AuthenticationExtensions.cs: -------------------------------------------------------------------------------- 1 | using Confix.Common; 2 | using Confix.Vault; 3 | using Microsoft.AspNetCore.Authentication.JwtBearer; 4 | using Microsoft.Extensions.DependencyInjection; 5 | 6 | namespace Confix.Authoring.Authentication; 7 | 8 | public static class AuthenticationExtensions 9 | { 10 | public static IVaultServerBuilder UseAuthentication( 11 | this IVaultServerBuilder builder, 12 | string pathToConfig = Settings.Confix.Vault.Authentication.JwtBearer.Section) 13 | { 14 | builder.Services 15 | .AddAuthentication(JwtBearerDefaults.AuthenticationScheme) 16 | .AddJwtBearer(); 17 | 18 | builder.Services 19 | .AddOptions(JwtBearerDefaults.AuthenticationScheme) 20 | .BindConfiguration(pathToConfig); 21 | 22 | return builder; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Backend/src/Vault.Authentication/Vault.Authentication.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Confix.Vault.Authentication 5 | Confix.Vault.Authentication 6 | true 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /src/Backend/src/Vault.Client/ConfigurationClientOptions.cs: -------------------------------------------------------------------------------- 1 | namespace Confix.Vault.Client; 2 | 3 | public sealed class VaultClientOptions 4 | { 5 | public string Url { get; set; } = string.Empty; 6 | } 7 | -------------------------------------------------------------------------------- /src/Backend/src/Vault.Client/QueryBuilderExtensions.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Http.Extensions; 2 | 3 | namespace Confix.Vault.Client; 4 | 5 | public static class QueryBuilderExtensions 6 | { 7 | public static QueryBuilder AddParameter(this QueryBuilder builder, string name, string value) 8 | { 9 | builder.Add(name, value); 10 | 11 | return builder; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/Backend/src/Vault.Client/Vault.Client.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Confix.Vault.Client 5 | Confix.Vault 6 | true 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /src/Backend/src/Vault.Client/VaultClientServiceCollectionExtensions.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.DependencyInjection; 2 | 3 | namespace Confix.Vault.Client; 4 | 5 | public static class VaultClientServiceCollectionExtensions 6 | { 7 | public static IServiceCollection AddVaultClient(this IServiceCollection services) 8 | { 9 | services.AddSingleton(); 10 | 11 | return services; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/Backend/src/Vault.Configuration/.graphqlrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "schema": "schema.graphql", 3 | "documents": "**/*.graphql", 4 | "extensions": { 5 | "strawberryShake": { 6 | "name": "AuthoringClient", 7 | "url": "http://localhost:5000/graphql/", 8 | "dependencyInjection": true, 9 | "noStore": true 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/Backend/src/Vault.Configuration/ApplicationPart.cs: -------------------------------------------------------------------------------- 1 | namespace Confix.Value.Configuration; 2 | 3 | public sealed record ApplicationPart(string Name, string PartName); 4 | -------------------------------------------------------------------------------- /src/Backend/src/Vault.Configuration/ConfixConfigurationBuilderExtensions.cs: -------------------------------------------------------------------------------- 1 | using Confix.Value.Configuration; 2 | 3 | namespace Microsoft.Extensions.Configuration; 4 | 5 | public static class ConfixConfigurationBuilderExtensions 6 | { 7 | public static IConfigurationBuilder AddVaultConfiguration( 8 | this IConfigurationBuilder builder, 9 | string appName, 10 | string partName) 11 | => builder.AddVaultConfiguration(new ApplicationPart(appName, partName)); 12 | 13 | private static IConfigurationBuilder AddVaultConfiguration( 14 | this IConfigurationBuilder builder, 15 | ApplicationPart part) 16 | { 17 | builder.Add(new VaultConfigurationSource(part)); 18 | 19 | return builder; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/Backend/src/Vault.Configuration/VaultConfiguration.graphql: -------------------------------------------------------------------------------- 1 | query GetLatestPublishedVersion( 2 | $applicationName: String!, 3 | $applicationPartName: String!, 4 | $environmentName: String!) { 5 | latestPublishedVersion( 6 | applicationName: $applicationName, 7 | applicationPartName: $applicationPartName, 8 | environmentName: $environmentName) { 9 | ...GetLatestPublishedVersion_LatestPublishedVersion 10 | ...GetLatestPublishedVersion_UserError 11 | } 12 | } 13 | 14 | fragment GetLatestPublishedVersion_LatestPublishedVersion on LatestPublishedVersion { 15 | configuration 16 | } 17 | 18 | fragment GetLatestPublishedVersion_UserError on UserError { 19 | message 20 | } 21 | -------------------------------------------------------------------------------- /src/Backend/src/Vault.Configuration/VaultConfigurationSource.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.Configuration; 2 | 3 | namespace Confix.Value.Configuration; 4 | 5 | public sealed class VaultConfigurationSource : IConfigurationSource 6 | { 7 | public ApplicationPart Part { get; } 8 | 9 | public VaultConfigurationSource(ApplicationPart part) 10 | { 11 | Part = part; 12 | } 13 | 14 | public IConfigurationProvider Build(IConfigurationBuilder builder) 15 | => new VaultConfigurationProvider(this); 16 | } 17 | -------------------------------------------------------------------------------- /src/Backend/src/Vault.Configuration/persisted/queries.json: -------------------------------------------------------------------------------- 1 | {"6f42b63696e015b96982e76d5a854ceb":"query GetLatestPublishedVersion($applicationName: String!, $applicationPartName: String!, $environmentName: String!) { latestPublishedVersion(applicationName: $applicationName, applicationPartName: $applicationPartName, environmentName: $environmentName) { __typename ... GetLatestPublishedVersion_LatestPublishedVersion ... GetLatestPublishedVersion_UserError } } fragment GetLatestPublishedVersion_LatestPublishedVersion on LatestPublishedVersion { configuration } fragment GetLatestPublishedVersion_UserError on UserError { message }"} -------------------------------------------------------------------------------- /src/Backend/src/Vault.Configuration/schema.extensions.graphql: -------------------------------------------------------------------------------- 1 | scalar _KeyFieldSet 2 | 3 | directive @key(fields: _KeyFieldSet!) on SCHEMA | OBJECT 4 | 5 | directive @serializationType(name: String!) on SCALAR 6 | 7 | directive @runtimeType(name: String!) on SCALAR 8 | 9 | directive @enumValue(value: String!) on ENUM_VALUE 10 | 11 | directive @rename(name: String!) on INPUT_FIELD_DEFINITION | INPUT_OBJECT | ENUM | ENUM_VALUE 12 | 13 | extend schema @key(fields: "id") 14 | -------------------------------------------------------------------------------- /src/Backend/src/Vault.Console/Vault.Console.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | false 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/Backend/src/Vault.Core/Exceptions/ConfigurationNotFoundException.cs: -------------------------------------------------------------------------------- 1 | namespace Confix.Vault.Core; 2 | 3 | public sealed class ConfigurationNotFoundException : Exception 4 | { 5 | public ConfigurationNotFoundException() : base("The configuration could not be found") 6 | { 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/Backend/src/Vault.Core/VaultCoreServiceCollectionExtensions.cs: -------------------------------------------------------------------------------- 1 | using Confix.Authentication.Authorization; 2 | using Confix.Common.Token; 3 | using Confix.Vault.Abstractions; 4 | using Confix.Vault.Core; 5 | 6 | namespace Microsoft.Extensions.DependencyInjection; 7 | 8 | public static class VaultCoreServiceCollectionExtensions 9 | { 10 | public static IServiceCollection AddVaultCore(this IServiceCollection services) 11 | { 12 | services.AddSingleton(); 13 | services.AddTokenProvider(); 14 | services.AddAuthorizationAndPolicies(); 15 | services.AddControllers(); 16 | 17 | return services; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/Backend/src/Vault.Messaging/Vault.Messaging.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Confix.Vault.Messaging 5 | Confix.Vault.Messaging 6 | enable 7 | true 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /src/Backend/src/Vault.Store.Mongo/IVaultDbContext.cs: -------------------------------------------------------------------------------- 1 | using Confix.Vault.Abstractions; 2 | using MongoDB.Driver; 3 | 4 | namespace Confix.Vault.Store.Mongo; 5 | 6 | public interface IVaultDbContext 7 | { 8 | IMongoCollection Configurations { get; } 9 | } 10 | -------------------------------------------------------------------------------- /src/Backend/src/Vault/EndpointRouteBuilderExtensions.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Builder; 2 | 3 | namespace Microsoft.Extensions.DependencyInjection; 4 | 5 | public static class EndpointRouteBuilderExtensions 6 | { 7 | public static T UseConfixVault(this T builder) where T : IApplicationBuilder 8 | { 9 | builder.UseRouting(); 10 | builder.UseAuthentication(); 11 | builder.UseAuthorization(); 12 | builder.UseEndpoints(x => x.MapControllers()); 13 | 14 | return builder; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/Backend/src/Vault/VaultServerBuilder.cs: -------------------------------------------------------------------------------- 1 | using Confix.Vault; 2 | 3 | namespace Microsoft.Extensions.DependencyInjection; 4 | 5 | internal sealed class VaultServerBuilder : IVaultServerBuilder 6 | { 7 | public VaultServerBuilder(IServiceCollection services) 8 | { 9 | Services = services; 10 | } 11 | 12 | public IServiceCollection Services { get; } 13 | } 14 | -------------------------------------------------------------------------------- /src/Backend/src/Vault/VaultServerBuilderExtensions.cs: -------------------------------------------------------------------------------- 1 | using Confix.CryptoProviders; 2 | using Confix.Vault; 3 | 4 | namespace Microsoft.Extensions.DependencyInjection; 5 | 6 | public static class VaultServerBuilderExtensions 7 | { 8 | public static IVaultServerBuilder ConfigureEncryption( 9 | this IVaultServerBuilder builder, 10 | Action configure) 11 | { 12 | configure(new CryptoProviderDescriptor(builder.Services)); 13 | 14 | return builder; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/Backend/src/Vault/VaultServiceCollectionExtensions.cs: -------------------------------------------------------------------------------- 1 | using Confix.Vault; 2 | 3 | namespace Microsoft.Extensions.DependencyInjection; 4 | 5 | public static class VaultServiceCollectionExtensions 6 | { 7 | public static IVaultServerBuilder AddConfixVaultServer(this IServiceCollection services) 8 | { 9 | var builder = new VaultServerBuilder(services); 10 | builder.Services.AddVaultCore(); 11 | 12 | return builder; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/Backend/test/Authoring.Authentication.Tests/Authoring.Authentication.Tests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Confix.Authoring.Authentication.Tests 5 | Confix.Authoring.Authentication.Tests 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/Backend/test/Authoring.Authentication.Tests/__snapshots__/SessionAccessorTests.GetSession_WithValidAPIToken_ReturnsSession.snap: -------------------------------------------------------------------------------- 1 | { 2 | "UserInfo": { 3 | "Id": "some-sub", 4 | "Name": "some-sub", 5 | "Email": null 6 | }, 7 | "Groups": [ 8 | { 9 | "Id": "00000000-0000-0000-0000-000000000000", 10 | "Name": "Api Key Auth", 11 | "Requirements": [], 12 | "Roles": [ 13 | { 14 | "Namespace": "NameSpace", 15 | "RoleIds": [] 16 | } 17 | ] 18 | } 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /src/Backend/test/Authoring.Authentication.Tests/__snapshots__/SessionAccessorTests.GetSession_WithValidUserClaims_ReturnsSession.snap: -------------------------------------------------------------------------------- 1 | { 2 | "UserInfo": { 3 | "Id": "some-sub", 4 | "Name": "John", 5 | "Email": "john@example.com" 6 | }, 7 | "Groups": [ 8 | { 9 | "Id": "00000000-0000-0000-0000-000000000000", 10 | "Name": "Some Group", 11 | "Requirements": [], 12 | "Roles": [] 13 | } 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /src/Backend/test/Authoring.Authentication.Tests/__snapshots__/SessionTests.GetGrantsForScope_ForScope_MatchSnapshot_Application.snap: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "Namespace": "CompanyNamespace", 4 | "Scope": "Application", 5 | "Permission": "Read, Write, Claim, Publish" 6 | }, 7 | { 8 | "Namespace": "Project1Namespace", 9 | "Scope": "Application", 10 | "Permission": "Read, Write, Claim, Publish" 11 | }, 12 | { 13 | "Namespace": "Project2Namespace", 14 | "Scope": "Application", 15 | "Permission": "Read, Write, Claim, Publish" 16 | }, 17 | { 18 | "Namespace": "SuperImportant", 19 | "Scope": "Application", 20 | "Permission": "Read, Write, Claim, Publish" 21 | } 22 | ] 23 | -------------------------------------------------------------------------------- /src/Backend/test/Authoring.Authentication.Tests/__snapshots__/SessionTests.GetGrantsForScope_ForScope_MatchSnapshot_Component.snap: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "Namespace": "CompanyNamespace", 4 | "Scope": "Component", 5 | "Permission": "Read, Write" 6 | }, 7 | { 8 | "Namespace": "Project1Namespace", 9 | "Scope": "Component", 10 | "Permission": "Read, Write" 11 | }, 12 | { 13 | "Namespace": "Project2Namespace", 14 | "Scope": "Component", 15 | "Permission": "Read, Write" 16 | }, 17 | { 18 | "Namespace": "SuperImportant", 19 | "Scope": "Component", 20 | "Permission": "Read, Write" 21 | } 22 | ] 23 | -------------------------------------------------------------------------------- /src/Backend/test/Authoring.Authentication.Tests/__snapshots__/SessionTests.GetGrantsForScope_ForScope_MatchSnapshot_Configuration.snap: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "Namespace": "CompanyNamespace", 4 | "Scope": "Configuration", 5 | "Permission": "Read, Write" 6 | }, 7 | { 8 | "Namespace": "Project1Namespace", 9 | "Scope": "Configuration", 10 | "Permission": "Read, Write" 11 | }, 12 | { 13 | "Namespace": "Project2Namespace", 14 | "Scope": "Configuration", 15 | "Permission": "Read, Write" 16 | }, 17 | { 18 | "Namespace": "SuperImportant", 19 | "Scope": "Configuration", 20 | "Permission": "Read, Write" 21 | } 22 | ] 23 | -------------------------------------------------------------------------------- /src/Backend/test/Authoring.Authentication.Tests/__snapshots__/SessionTests.GetGrantsForScope_ForScope_MatchSnapshot_Identity.snap: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "Namespace": "CompanyNamespace", 4 | "Scope": "Identity", 5 | "Permission": "Read, Write" 6 | }, 7 | { 8 | "Namespace": "Project1Namespace", 9 | "Scope": "Identity", 10 | "Permission": "Read, Write" 11 | }, 12 | { 13 | "Namespace": "Project2Namespace", 14 | "Scope": "Identity", 15 | "Permission": "Read, Write" 16 | }, 17 | { 18 | "Namespace": "SuperImportant", 19 | "Scope": "Identity", 20 | "Permission": "Read, Write" 21 | } 22 | ] 23 | -------------------------------------------------------------------------------- /src/Backend/test/Authoring.Authentication.Tests/__snapshots__/SessionTests.GetGrantsForScope_ForScope_MatchSnapshot_Variable.snap: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "Namespace": "CompanyNamespace", 4 | "Scope": "Variable", 5 | "Permission": "Read, Write, Decrypt" 6 | }, 7 | { 8 | "Namespace": "Project1Namespace", 9 | "Scope": "Variable", 10 | "Permission": "Read, Write, Decrypt" 11 | }, 12 | { 13 | "Namespace": "Project2Namespace", 14 | "Scope": "Variable", 15 | "Permission": "Read, Write, Decrypt" 16 | }, 17 | { 18 | "Namespace": "SuperImportant", 19 | "Scope": "Variable", 20 | "Permission": "Read, Write, Decrypt" 21 | } 22 | ] 23 | -------------------------------------------------------------------------------- /src/Backend/test/Authoring.GraphQL.Tests/Authoring.GraphQL.Tests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Confix.Authoring.GraphQL.Tests 5 | Confix.Authoring.GraphQL.Tests 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/Backend/test/Authoring.GraphQL.Tests/SchemaTests.cs: -------------------------------------------------------------------------------- 1 | using HotChocolate.Execution; 2 | using Microsoft.Extensions.DependencyInjection; 3 | 4 | namespace Confix.Authoring.GraphQL.Tests; 5 | 6 | public class SchemaTests 7 | { 8 | [Fact] 9 | public async Task PrintSchema() 10 | { 11 | var schema = await new ServiceCollection() 12 | .AddGraphQLServer() 13 | .AddConfixSchema() 14 | .BuildSchemaAsync(); 15 | 16 | schema.Print().MatchSnapshot(); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/Backend/test/Authoring.Integration.Tests/.graphqlrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "schema": "schema.graphql", 3 | "documents": "*.graphql", 4 | "extensions": { 5 | "strawberryShake": { 6 | "name": "TestClient", 7 | "url": "https://localhost", 8 | "records": { 9 | "inputs": false, 10 | "entities": false 11 | }, 12 | "transportProfiles": [ 13 | { 14 | "default": "InMemory" 15 | } 16 | ] 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/Backend/test/Authoring.Integration.Tests/ApplicationTests.graphql: -------------------------------------------------------------------------------- 1 | query GetApplications 2 | { 3 | applications { 4 | nodes { 5 | ...Application 6 | } 7 | } 8 | } 9 | 10 | query GetApplicationById($id: ID!) 11 | { 12 | applicationById(id: $id) { 13 | ...Application 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/Backend/test/Authoring.Integration.Tests/__snapshots__/ComponentTests.ComponentById_ValidId_ReturnsComponent.snap: -------------------------------------------------------------------------------- 1 | { 2 | "Id": "Q29tcG9uZW50CmcwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMw==", 3 | "Version": 1, 4 | "Name": "Test Component", 5 | "Schema": "type Configuration {\n field: String!\n nestedField: NestedConfiguration!\n}\n\ntype NestedConfiguration {\n field: String!\n}", 6 | "Values": { 7 | "field": "default", 8 | "nestedField": { 9 | "field": "defaultNested" 10 | } 11 | }, 12 | "Scopes": [ 13 | { 14 | "__typename": "NamespaceComponentScope", 15 | "Namespace": "Test" 16 | } 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /src/Backend/test/Authoring.Integration.Tests/__snapshots__/ComponentTests.CreateComponent_BrokenSchema_ReturnsError.snap: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "__typename": "SchemaInvalidError", 4 | "Code": "SchemaInvalidError", 5 | "Message": "The Provided sdl is not valid" 6 | } 7 | ] 8 | -------------------------------------------------------------------------------- /src/Backend/test/Authoring.Integration.Tests/__snapshots__/ComponentTests.CreateComponent_ReadPermission_Fail.snap: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "__typename": "UnauthorizedOperationError", 4 | "Code": "UNAUTHORIZED_OPERATION_EXCEPTION", 5 | "Message": "You are not allowed to perform this operation" 6 | } 7 | ] 8 | -------------------------------------------------------------------------------- /src/Backend/test/Authoring.Integration.Tests/__snapshots__/ComponentTests.CreateComponent_ValidInput_CreatesComponent.snap: -------------------------------------------------------------------------------- 1 | { 2 | "Id": "Q29tcG9uZW50CmdjMmViZDU5ZWYwMGU0NjQwYTc1N2Y1NmQ5NTdiNzVjZQ==", 3 | "Version": 1, 4 | "Name": "My New Component", 5 | "Schema": "type Configuration {\n someTestField: String!\n}", 6 | "Values": { 7 | "someTestField": "foo" 8 | }, 9 | "Scopes": [ 10 | { 11 | "__typename": "NamespaceComponentScope", 12 | "Namespace": "Test" 13 | } 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /src/Backend/test/Authoring.Integration.Tests/__snapshots__/ComponentTests.RenameComponent_ReadPermission_Fails.snap: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "__typename": "UnauthorizedOperationError", 4 | "Code": "UNAUTHORIZED_OPERATION_EXCEPTION", 5 | "Message": "You are not allowed to perform this operation" 6 | } 7 | ] 8 | -------------------------------------------------------------------------------- /src/Backend/test/Authoring.Integration.Tests/__snapshots__/ComponentTests.UpdateComponentSchema_InvalidSchema_Error.snap: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "__typename": "SchemaInvalidError", 4 | "Code": "SchemaInvalidError", 5 | "Message": "The Provided sdl is not valid" 6 | } 7 | ] 8 | -------------------------------------------------------------------------------- /src/Backend/test/Authoring.Integration.Tests/__snapshots__/ComponentTests.UpdateComponentSchema_NewValuesDontMatchSchema_Error.snap: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "__typename": "ValueSchemaViolation", 4 | "Code": "ValueSchemaViolation", 5 | "Message": "Values has invalid structure." 6 | } 7 | ] 8 | -------------------------------------------------------------------------------- /src/Backend/test/Authoring.Integration.Tests/__snapshots__/ComponentTests.UpdateComponentSchema_ValidValues_UpdatesComponent.snap: -------------------------------------------------------------------------------- 1 | { 2 | "Id": "Q29tcG9uZW50CmcwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMw==", 3 | "Version": 2, 4 | "Name": "Test Component", 5 | "Schema": "type Configuration {\n updatedField: String!\n}", 6 | "Values": { 7 | "updatedField": "foo" 8 | }, 9 | "Scopes": [ 10 | { 11 | "__typename": "NamespaceComponentScope", 12 | "Namespace": "Test" 13 | } 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /src/Backend/test/Authoring.Integration.Tests/__snapshots__/ComponentTests.UpdateComponentSchema_WithoutWritePermission_Fails.snap: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "__typename": "UnauthorizedOperationError", 4 | "Code": "UNAUTHORIZED_OPERATION_EXCEPTION", 5 | "Message": "You are not allowed to perform this operation" 6 | } 7 | ] 8 | -------------------------------------------------------------------------------- /src/Backend/test/Authoring.Integration.Tests/__snapshots__/ComponentTests.UpdateComponentScopes_ValidScopes_UpdatesComponent.snap: -------------------------------------------------------------------------------- 1 | { 2 | "Id": "Q29tcG9uZW50CmcwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMw==", 3 | "Version": 1, 4 | "Name": "Test Component", 5 | "Schema": "type Configuration {\n field: String!\n nestedField: NestedConfiguration!\n}\n\ntype NestedConfiguration {\n field: String!\n}", 6 | "Values": { 7 | "field": "default", 8 | "nestedField": { 9 | "field": "defaultNested" 10 | } 11 | }, 12 | "Scopes": [ 13 | { 14 | "__typename": "NamespaceComponentScope", 15 | "Namespace": "Other" 16 | } 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /src/Backend/test/Authoring.Integration.Tests/__snapshots__/ComponentTests.UpdateComponentScopes_WithoutWritePermission_Fails.snap: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "__typename": "UnauthorizedOperationError", 4 | "Code": "UNAUTHORIZED_OPERATION_EXCEPTION", 5 | "Message": "You are not allowed to perform this operation" 6 | } 7 | ] 8 | -------------------------------------------------------------------------------- /src/Backend/test/Authoring.Integration.Tests/__snapshots__/ComponentTests.UpdateComponentValues_NewValuesDontMatchSchema_Error.snap: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "__typename": "ValueSchemaViolation", 4 | "Code": "ValueSchemaViolation", 5 | "Message": "Values has invalid structure." 6 | } 7 | ] 8 | -------------------------------------------------------------------------------- /src/Backend/test/Authoring.Integration.Tests/__snapshots__/ComponentTests.UpdateComponentValues_ValidValues_UpdatesComponent.snap: -------------------------------------------------------------------------------- 1 | { 2 | "Id": "Q29tcG9uZW50CmcwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMw==", 3 | "Version": 2, 4 | "Name": "Test Component", 5 | "Schema": "type Configuration {\n field: String!\n nestedField: NestedConfiguration!\n}\n\ntype NestedConfiguration {\n field: String!\n}", 6 | "Values": { 7 | "field": "updatedNested", 8 | "nestedField": { 9 | "field": "updatedNested" 10 | } 11 | }, 12 | "Scopes": [ 13 | { 14 | "__typename": "NamespaceComponentScope", 15 | "Namespace": "Test" 16 | } 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /src/Backend/test/Authoring.Integration.Tests/__snapshots__/ComponentTests.UpdateComponentValues_WithoutWritePermission_Fails.snap: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "__typename": "UnauthorizedOperationError", 4 | "Code": "UNAUTHORIZED_OPERATION_EXCEPTION", 5 | "Message": "You are not allowed to perform this operation" 6 | } 7 | ] 8 | -------------------------------------------------------------------------------- /src/Backend/test/Authoring.Integration.Tests/schema.extensions.graphql: -------------------------------------------------------------------------------- 1 | scalar _KeyFieldSet 2 | 3 | directive @key(fields: _KeyFieldSet!) on SCHEMA | OBJECT 4 | 5 | directive @serializationType(name: String!) on SCALAR 6 | 7 | directive @runtimeType(name: String!) on SCALAR 8 | 9 | directive @enumValue(value: String!) on ENUM_VALUE 10 | 11 | directive @rename(name: String!) on INPUT_FIELD_DEFINITION | INPUT_OBJECT | ENUM | ENUM_VALUE 12 | 13 | extend schema @key(fields: "id") 14 | 15 | extend scalar SDL 16 | @serializationType(name: "global::System.String") 17 | @runtimeType(name: "global::System.String") 18 | 19 | extend scalar JSON 20 | @serializationType(name: "global::System.Text.Json.JsonElement") 21 | @runtimeType(name: "global::System.Text.Json.JsonDocument") 22 | -------------------------------------------------------------------------------- /src/Backend/test/Authoring.Store.Mongo.Tests/Authoring.Store.Mongo.Tests.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Confix.Authoring.Store.Mongo.Tests 5 | Confix.Authoring.Store.Mongo.Tests 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/Backend/test/Authoring.Store.Mongo.Tests/__snapshots__/VariableValueStoreTests.GetByKeyAsync_GetAllKeyFieldsNullVariable_ReturnsRightVariable.snap: -------------------------------------------------------------------------------- 1 | { 2 | "Id": "ddf1670c-b4ff-4926-ac39-f6a7bdd3d341", 3 | "Key": { 4 | "VariableId": "00000000-0000-0000-0000-000000000000", 5 | "ApplicationId": null, 6 | "PartId": null, 7 | "EnvironmentId": null 8 | }, 9 | "Value": "This is a insertion test value 0.", 10 | "Encryption": null, 11 | "Version": 0 12 | } 13 | -------------------------------------------------------------------------------- /src/Backend/test/Authoring.Store.Mongo.Tests/__snapshots__/VariableValueStoreTests.GetByKeyAsync_GetAllKeyFieldsSetVariable_ReturnsRightVariable.snap: -------------------------------------------------------------------------------- 1 | { 2 | "Id": "f39140e5-b24c-48f3-aacd-9864f76f53a6", 3 | "Key": { 4 | "VariableId": "98047cea-e467-4d7a-8eb1-73f617bdcf75", 5 | "ApplicationId": "53055060-7173-4839-8a16-ef7845a0d1b9", 6 | "PartId": "9442bff1-6aa9-4416-8c89-ba58ec2a1aa4", 7 | "EnvironmentId": "04e057a5-0140-404c-9c94-92ad7702a63c" 8 | }, 9 | "Value": "This is a insertion test value 3.", 10 | "Encryption": null, 11 | "Version": 0 12 | } 13 | -------------------------------------------------------------------------------- /src/Backend/test/Authoring.Store.Mongo.Tests/__snapshots__/VariableValueStoreTests.GetByKeyAsync_GetOneKeyFieldSetVariable_ReturnsRightVariable.snap: -------------------------------------------------------------------------------- 1 | { 2 | "Id": "4674d60d-7f3e-4b54-8bfb-b484303f62b0", 3 | "Key": { 4 | "VariableId": "98047cea-e467-4d7a-8eb1-73f617bdcf75", 5 | "ApplicationId": null, 6 | "PartId": null, 7 | "EnvironmentId": null 8 | }, 9 | "Value": "This is a insertion test value 1.", 10 | "Encryption": null, 11 | "Version": 0 12 | } 13 | -------------------------------------------------------------------------------- /src/Backend/test/Authoring.Store.Mongo.Tests/__snapshots__/VariableValueStoreTests.GetByKeyAsync_GetTwoKeyFieldsSetVariable_ReturnsRightVariable.snap: -------------------------------------------------------------------------------- 1 | { 2 | "Id": "6b9fc641-988e-4182-a870-037aff5cfc1f", 3 | "Key": { 4 | "VariableId": "98047cea-e467-4d7a-8eb1-73f617bdcf75", 5 | "ApplicationId": null, 6 | "PartId": null, 7 | "EnvironmentId": "04e057a5-0140-404c-9c94-92ad7702a63c" 8 | }, 9 | "Value": "This is a insertion test value 2.", 10 | "Encryption": null, 11 | "Version": 0 12 | } 13 | -------------------------------------------------------------------------------- /src/Backend/test/Authoring.Store.Mongo.Tests/__snapshots__/VariableValueStoreTests.UpsertAsync_SaveNewVariableValueEmptyValues_SuccessfullyInserted.snap: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "Id": "4674d60d-7f3e-4b54-8bfb-b484303f62b0", 4 | "Key": { 5 | "VariableId": "00000000-0000-0000-0000-000000000000", 6 | "ApplicationId": null, 7 | "PartId": null, 8 | "EnvironmentId": null 9 | }, 10 | "Value": "", 11 | "Encryption": null, 12 | "Version": 0 13 | } 14 | ] 15 | -------------------------------------------------------------------------------- /src/Backend/test/Authoring.Store.Mongo.Tests/__snapshots__/VariableValueStoreTests.UpsertAsync_SaveNewVariableValue_SuccessfullyInserted.snap: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "Id": "4674d60d-7f3e-4b54-8bfb-b484303f62b0", 4 | "Key": { 5 | "VariableId": "98047cea-e467-4d7a-8eb1-73f617bdcf75", 6 | "ApplicationId": null, 7 | "PartId": null, 8 | "EnvironmentId": null 9 | }, 10 | "Value": "This is a insertion test.", 11 | "Encryption": null, 12 | "Version": 0 13 | } 14 | ] 15 | -------------------------------------------------------------------------------- /src/Backend/test/Authoring.Store.Mongo.Tests/__snapshots__/VariableValueStoreTests.UpsertAsync_UpdateVariableByExistingKey_SuccessfullyUpdated.snap: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "Id": "4674d60d-7f3e-4b54-8bfb-b484303f62b0", 4 | "Key": { 5 | "VariableId": "98047cea-e467-4d7a-8eb1-73f617bdcf75", 6 | "ApplicationId": null, 7 | "PartId": null, 8 | "EnvironmentId": null 9 | }, 10 | "Value": "Updated variable Value", 11 | "Encryption": { 12 | "KeyProvider": "AzureKeyVault", 13 | "Key": "xyz", 14 | "Algorithm": "AES256" 15 | }, 16 | "Version": 0 17 | } 18 | ] 19 | -------------------------------------------------------------------------------- /src/Backend/test/CryptoProviders.AzureKeyVault.Tests/CryptoProviders.AzureKeyVault.Tests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Confix.CryptoProviders.AzureKeyVault.Tests 5 | Confix.CryptoProviders.AzureKeyVault.Tests 6 | df82c6c1-95f3-4b5c-941d-ead60aa8198d 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | Always 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /src/Backend/test/CryptoProviders.AzureKeyVault.Tests/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Confix": { 3 | "AzureKeyVault": { 4 | "Url": "https://xxx.vault.azure.net/", 5 | "EncryptionKeyId": "variable-encryption-01", 6 | "Algorithm": "RSA-OAEP-256", 7 | "TenantId": "xx" 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/Frontend/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /src/Frontend/.graphqlrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "schema": ["./schema.graphql", "./schema-extensions/*.graphql"] 3 | } 4 | -------------------------------------------------------------------------------- /src/Frontend/.prettierignore: -------------------------------------------------------------------------------- 1 | # dependencies 2 | node_modules/ 3 | 4 | # generated 5 | __generated__/ 6 | __snapshots__/ 7 | reports/ 8 | coverage/ 9 | build/ 10 | lib/ 11 | dist/ 12 | 13 | # temporary 14 | tmp/ 15 | temp/ 16 | *.tmp 17 | 18 | # misc 19 | .DS_Store 20 | .*/ 21 | -------------------------------------------------------------------------------- /src/Frontend/.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 80, 3 | "tabWidth": 2, 4 | "useTabs": false, 5 | "semi": true, 6 | "singleQuote": true, 7 | "trailingComma": "all", 8 | "bracketSpacing": false, 9 | "bracketSameLine": false, 10 | "arrowParens": "always" 11 | } 12 | -------------------------------------------------------------------------------- /src/Frontend/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Confix 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/Frontend/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SwissLife-OSS/Confix-Unloaded/8be52f1ee677d49c7fa515db42ad51aa448dfc8b/src/Frontend/public/favicon.ico -------------------------------------------------------------------------------- /src/Frontend/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SwissLife-OSS/Confix-Unloaded/8be52f1ee677d49c7fa515db42ad51aa448dfc8b/src/Frontend/public/logo192.png -------------------------------------------------------------------------------- /src/Frontend/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SwissLife-OSS/Confix-Unloaded/8be52f1ee677d49c7fa515db42ad51aa448dfc8b/src/Frontend/public/logo512.png -------------------------------------------------------------------------------- /src/Frontend/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /src/Frontend/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /src/Frontend/relay.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | schema: './schema.graphql', 3 | schemaExtensions: [], 4 | src: './src', 5 | eagerEsModules: true, 6 | noFutureProofEnums: true, 7 | language: 'typescript', 8 | artifactDirectory: 'src/__generated__', 9 | persistConfig: { 10 | file: './persisted_queries.json', 11 | }, 12 | }; 13 | -------------------------------------------------------------------------------- /src/Frontend/src/App.css: -------------------------------------------------------------------------------- 1 | #components-layout-demo-side .logo { 2 | height: 32px; 3 | margin: 16px; 4 | background: rgba(255, 255, 255, 0.3); 5 | } 6 | 7 | .ant-menu-dark .ant-menu-sub, 8 | .ant-menu.ant-menu-dark, 9 | .ant-menu.ant-menu-dark .ant-menu-sub, 10 | .ant-layout-sider { 11 | background-color: #1d1e1d !important; 12 | } 13 | .ant-layout-sider-trigger { 14 | background-color: #2c2c2c !important; 15 | } 16 | 17 | .site-layout .site-layout-background { 18 | background: #fff; 19 | } 20 | -------------------------------------------------------------------------------- /src/Frontend/src/Connections.ts: -------------------------------------------------------------------------------- 1 | import {graphql} from 'babel-plugin-relay/macro'; 2 | 3 | const applicationFragment = graphql` 4 | fragment Connections_applications on Application @relay(plural: true) { 5 | id 6 | name 7 | namespace 8 | parts { 9 | name 10 | } 11 | } 12 | `; 13 | 14 | const componentFragment = graphql` 15 | fragment Connections_components on Component @relay(plural: true) { 16 | id 17 | name 18 | } 19 | `; 20 | 21 | export const Connections = { 22 | applications: { 23 | name: 'Query_applications', 24 | fragment: applicationFragment, 25 | }, 26 | components: { 27 | name: 'Query_components', 28 | fragment: componentFragment, 29 | }, 30 | }; 31 | -------------------------------------------------------------------------------- /src/Frontend/src/RelayEnvironment.ts: -------------------------------------------------------------------------------- 1 | // your-app-name/src/RelayEnvironment.js 2 | import {Environment, Network, RecordSource, Store} from 'relay-runtime'; 3 | 4 | import {fetchGraphQL} from './fetchGraphQL'; 5 | 6 | // Export a singleton instance of Relay Environment configured with our network function: 7 | export default new Environment({ 8 | network: Network.create(fetchGraphQL), 9 | store: new Store(new RecordSource()), 10 | }); 11 | -------------------------------------------------------------------------------- /src/Frontend/src/applications/validation/applicationSchema.tsx: -------------------------------------------------------------------------------- 1 | import * as yup from 'yup'; 2 | 3 | export const applicationSchema = yup.object({ 4 | name: yup.string().required('Name is required.'), 5 | namespace: yup.string().required('Namespace is required.'), 6 | }); 7 | -------------------------------------------------------------------------------- /src/Frontend/src/components/componentSchema.tsx: -------------------------------------------------------------------------------- 1 | import * as yup from 'yup'; 2 | 3 | export const componentSchema = yup.object({ 4 | name: yup.string().required('Name is required.'), 5 | schema: yup.string().required('Namespace is required.'), 6 | }); 7 | -------------------------------------------------------------------------------- /src/Frontend/src/config.ts: -------------------------------------------------------------------------------- 1 | export const config = { 2 | graphql: { 3 | api: '/graphql', 4 | }, 5 | identity: { 6 | signInPath: '/login', 7 | }, 8 | appBar: { 9 | height: 72, 10 | }, 11 | page: { 12 | padding: 16, 13 | }, 14 | pagination: { 15 | pageSize: 30, 16 | }, 17 | }; 18 | -------------------------------------------------------------------------------- /src/Frontend/src/environment/environmentSchema.tsx: -------------------------------------------------------------------------------- 1 | import * as yup from 'yup'; 2 | 3 | export const environmentSchema = yup.object({ 4 | name: yup.string().required('Name is required.'), 5 | }); 6 | -------------------------------------------------------------------------------- /src/Frontend/src/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SwissLife-OSS/Confix-Unloaded/8be52f1ee677d49c7fa515db42ad51aa448dfc8b/src/Frontend/src/images/logo.png -------------------------------------------------------------------------------- /src/Frontend/src/images/logo_small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SwissLife-OSS/Confix-Unloaded/8be52f1ee677d49c7fa515db42ad51aa448dfc8b/src/Frontend/src/images/logo_small.png -------------------------------------------------------------------------------- /src/Frontend/src/index.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SwissLife-OSS/Confix-Unloaded/8be52f1ee677d49c7fa515db42ad51aa448dfc8b/src/Frontend/src/index.css -------------------------------------------------------------------------------- /src/Frontend/src/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {createRoot} from 'react-dom/client'; 3 | import './index.css'; 4 | import App from './App'; 5 | import reportWebVitals from './reportWebVitals'; 6 | import {Wrapper} from './shared/Wrapper'; 7 | 8 | const container = document.getElementById('root')!; 9 | const root = createRoot(container); 10 | root.render( 11 | 12 | 13 | , 14 | ); 15 | 16 | // If you want to start measuring performance in your app, pass a function 17 | // to log results (for example: reportWebVitals(console.log)) 18 | // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals 19 | reportWebVitals(); 20 | -------------------------------------------------------------------------------- /src/Frontend/src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /src/Frontend/src/reportWebVitals.ts: -------------------------------------------------------------------------------- 1 | import {ReportHandler} from 'web-vitals'; 2 | 3 | const reportWebVitals = (onPerfEntry?: ReportHandler) => { 4 | if (onPerfEntry && onPerfEntry instanceof Function) { 5 | import('web-vitals').then(({getCLS, getFID, getFCP, getLCP, getTTFB}) => { 6 | getCLS(onPerfEntry); 7 | getFID(onPerfEntry); 8 | getFCP(onPerfEntry); 9 | getLCP(onPerfEntry); 10 | getTTFB(onPerfEntry); 11 | }); 12 | } 13 | }; 14 | 15 | export default reportWebVitals; 16 | -------------------------------------------------------------------------------- /src/Frontend/src/settings/groups/groupSchema.tsx: -------------------------------------------------------------------------------- 1 | import * as yup from 'yup'; 2 | 3 | export const groupSchema = yup.object({ 4 | name: yup.string().required('Name is required.'), 5 | }); 6 | -------------------------------------------------------------------------------- /src/Frontend/src/settings/roles/roleSchema.tsx: -------------------------------------------------------------------------------- 1 | import * as yup from 'yup'; 2 | 3 | export const roleSchema = yup.object({ 4 | name: yup.string().required('Name is required.'), 5 | }); 6 | -------------------------------------------------------------------------------- /src/Frontend/src/setupTests.ts: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom'; 6 | -------------------------------------------------------------------------------- /src/Frontend/src/shared/ButtonBar.tsx: -------------------------------------------------------------------------------- 1 | import React, {ReactNode} from 'react'; 2 | import {css} from '@emotion/react'; 3 | 4 | export const ButtonBar: React.FC<{children: ReactNode}> = ({children}) => ( 5 |
12 | {children} 13 |
14 | ); 15 | -------------------------------------------------------------------------------- /src/Frontend/src/shared/ColorTag.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {Tag, TagProps} from 'antd'; 3 | import {hashCode} from './hashCode'; 4 | import styled from '@emotion/styled'; 5 | 6 | const colors = [ 7 | 'pink', 8 | 'red', 9 | 'yellow', 10 | 'orange', 11 | 'cyan', 12 | 'green', 13 | 'blue', 14 | 'purple', 15 | 'geekblue', 16 | 'magenta', 17 | 'volcano', 18 | 'gold', 19 | 'lime', 20 | ]; 21 | 22 | export const ColorTag: React.FC<{value: string} & TagProps> = ({ 23 | children, 24 | value, 25 | ...rest 26 | }) => { 27 | return ( 28 | 29 | {children} 30 | 31 | ); 32 | }; 33 | 34 | export const TagBar = styled('div')` 35 | display: flex; 36 | flex-direction: row; 37 | `; 38 | -------------------------------------------------------------------------------- /src/Frontend/src/shared/DefaultSuspense.tsx: -------------------------------------------------------------------------------- 1 | import React, {Suspense, SuspenseProps} from 'react'; 2 | import {PageLoader} from './DetailView'; 3 | 4 | export const DefaultSuspense: React.FC> = ({ 5 | children, 6 | ...props 7 | }) => ( 8 | }> 9 | {children} 10 | 11 | ); 12 | -------------------------------------------------------------------------------- /src/Frontend/src/shared/FullSizeBox.tsx: -------------------------------------------------------------------------------- 1 | import styled from '@emotion/styled'; 2 | import {Card, Space} from 'antd'; 3 | 4 | export const FullSizeBox = styled(Card)<{grow?: boolean}>` 5 | display: flex; 6 | overflow: auto; 7 | .ant-card-body { 8 | flex: 1; 9 | display: flex; 10 | flex-direction: column; 11 | } 12 | `; 13 | 14 | export const Content = styled(FullSizeBox)` 15 | display: flex; 16 | flex: 1; 17 | padding-left: 10px; 18 | margin-left: 10px; 19 | `; 20 | 21 | export const SidebarHeader = styled(Space)` 22 | flex: 0; 23 | `; 24 | -------------------------------------------------------------------------------- /src/Frontend/src/shared/InlinePage.tsx: -------------------------------------------------------------------------------- 1 | import {config} from '../config'; 2 | import styled from '@emotion/styled'; 3 | 4 | export const InlinePage = styled.div` 5 | max-height: calc( 6 | 100vh - ${config.appBar.height}px - ${config.page.padding}px 7 | ); 8 | min-height: 500px; 9 | display: flex; 10 | flex: 1 1 auto; 11 | `; 12 | -------------------------------------------------------------------------------- /src/Frontend/src/shared/QueryOptions.ts: -------------------------------------------------------------------------------- 1 | import {FetchPolicy} from 'react-relay'; 2 | import {CacheConfig, RenderPolicy} from 'relay-runtime'; 3 | 4 | export type QueryOptions = { 5 | fetchKey?: string | number | undefined; 6 | fetchPolicy?: FetchPolicy | undefined; 7 | networkCacheConfig?: CacheConfig | undefined; 8 | UNSTABLE_renderPolicy?: RenderPolicy | undefined; 9 | }; 10 | -------------------------------------------------------------------------------- /src/Frontend/src/shared/SearchBar.tsx: -------------------------------------------------------------------------------- 1 | import {Input} from 'antd'; 2 | import React from 'react'; 3 | import {SearchIcon} from '../icons/icons'; 4 | import {debounce} from './debounce'; 5 | import {useStringEventHanlder as useStringEventHandler} from './useEventListener'; 6 | 7 | export const SearchBar: React.FC<{ 8 | onSearch: (item: string) => void; 9 | }> = ({onSearch}) => { 10 | const handleSearch = useStringEventHandler(debounce(onSearch)); 11 | return ( 12 | } 15 | onChange={handleSearch} 16 | /> 17 | ); 18 | }; 19 | -------------------------------------------------------------------------------- /src/Frontend/src/shared/TabRow.tsx: -------------------------------------------------------------------------------- 1 | import styled from '@emotion/styled'; 2 | 3 | export const TabRow = styled.div` 4 | display: flex; 5 | flex-direction: column; 6 | flex-grow: 1; 7 | .ant-tabs-content-holder { 8 | display: flex; 9 | } 10 | .ant-tabs { 11 | flex-grow: 1; 12 | } 13 | .ant-tabs-tabpane { 14 | min-height: 100%; 15 | display: flex; 16 | flex-direction: column; 17 | } 18 | `; 19 | -------------------------------------------------------------------------------- /src/Frontend/src/shared/UseFormik.ts: -------------------------------------------------------------------------------- 1 | import {FormikConfig, FormikValues, useFormik} from 'formik'; 2 | 3 | class Wrapper { 4 | // wrapped has no explicit return type so we can infer it 5 | wrapped(v: FormikConfig) { 6 | // eslint-disable-next-line react-hooks/rules-of-hooks 7 | return useFormik(v); 8 | } 9 | } 10 | 11 | export type UseFormik = ReturnType< 12 | Wrapper['wrapped'] 13 | >; 14 | -------------------------------------------------------------------------------- /src/Frontend/src/shared/chunkBy.ts: -------------------------------------------------------------------------------- 1 | import {groupBy} from './groupBy'; 2 | 3 | export const chunkBy = ( 4 | xs: T[], 5 | chunkBy: (a: T) => TKey, 6 | ): T[][] => { 7 | return Object.values(groupBy(xs, chunkBy)); 8 | }; 9 | -------------------------------------------------------------------------------- /src/Frontend/src/shared/debounce.ts: -------------------------------------------------------------------------------- 1 | import {useCallback} from 'react'; 2 | 3 | export function debounce any>( 4 | cb: T, 5 | wait = 20, 6 | ): T { 7 | let h: NodeJS.Timeout | undefined = undefined; 8 | let callable = (...args: any): any => { 9 | if (h) { 10 | clearTimeout(h); 11 | } 12 | h = setTimeout(() => cb(...args), wait); 13 | }; 14 | return callable as any; 15 | } 16 | 17 | export function useDebounce any>( 18 | cb: T, 19 | wait = 20, 20 | ): T { 21 | // eslint-disable-next-line react-hooks/exhaustive-deps 22 | return useCallback(debounce(cb, wait), [debounce, cb]); 23 | } 24 | -------------------------------------------------------------------------------- /src/Frontend/src/shared/distinct.ts: -------------------------------------------------------------------------------- 1 | export const distinct = (xs: T[]): T[] => Array.from(new Set(xs).values()); 2 | -------------------------------------------------------------------------------- /src/Frontend/src/shared/editor/defaultEditorOptions.tsx: -------------------------------------------------------------------------------- 1 | import {editor} from 'monaco-editor'; 2 | 3 | export const defaultEditorOptions: editor.IStandaloneEditorConstructionOptions = 4 | { 5 | glyphMargin: false, 6 | folding: false, 7 | lineNumbers: 'off', 8 | lineDecorationsWidth: 0, 9 | lineNumbersMinChars: 0, 10 | selectOnLineNumbers: true, 11 | roundedSelection: false, 12 | readOnly: false, 13 | cursorStyle: 'line', 14 | formatOnPaste: true, 15 | formatOnType: true, 16 | automaticLayout: true, 17 | minimap: {enabled: false}, 18 | }; 19 | -------------------------------------------------------------------------------- /src/Frontend/src/shared/ensureDate.ts: -------------------------------------------------------------------------------- 1 | import parseISO from 'date-fns/parseISO'; 2 | 3 | export const ensureDate = (date?: unknown): Date => { 4 | if (!date) { 5 | } 6 | if (date instanceof Date) { 7 | return date; 8 | } 9 | if (typeof date === 'number') { 10 | return new Date(date); 11 | } 12 | if (typeof date === 'string') { 13 | return parseISO(date); 14 | } 15 | return new Date(); 16 | }; 17 | -------------------------------------------------------------------------------- /src/Frontend/src/shared/formatDate.ts: -------------------------------------------------------------------------------- 1 | import format from 'date-fns/format'; 2 | import parseISO from 'date-fns/parseISO'; 3 | 4 | export const formatDate = (date?: unknown): string => { 5 | const formatpattern = 'HH:mm dd.MM.yyyy'; 6 | if (!date) { 7 | } 8 | if (date instanceof Date || typeof date === 'number') { 9 | return format(date, formatpattern); 10 | } 11 | if (typeof date === 'string') { 12 | return format(parseISO(date), formatpattern); 13 | } 14 | return '-'; 15 | }; 16 | -------------------------------------------------------------------------------- /src/Frontend/src/shared/groupBy.ts: -------------------------------------------------------------------------------- 1 | export const groupBy = ( 2 | xs: T[], 3 | groupBy: (a: T) => TKey, 4 | ) => { 5 | return xs.reduce>((reduced, current) => { 6 | (reduced[groupBy(current)] = reduced[groupBy(current)] || []).push(current); 7 | return reduced; 8 | }, {} as any); 9 | }; 10 | -------------------------------------------------------------------------------- /src/Frontend/src/shared/hashCode.ts: -------------------------------------------------------------------------------- 1 | export const hashCode = (str: string): number => { 2 | if (str.length === 0) { 3 | return 0; 4 | } 5 | let hash = 0; 6 | let i; 7 | let chr; 8 | 9 | for (i = 0; i < str.length; i++) { 10 | chr = str.charCodeAt(i); 11 | hash = (hash << 5) - hash + chr; 12 | hash |= 0; // Convert to 32bit integer 13 | } 14 | return hash; 15 | }; 16 | -------------------------------------------------------------------------------- /src/Frontend/src/shared/id.tsx: -------------------------------------------------------------------------------- 1 | export const id = () => { 2 | const gen8 = () => 3 | Math.floor((1 + Math.random()) * 0x100000000) 4 | .toString(16) 5 | .substring(1); 6 | return gen8() + '_' + gen8(); 7 | }; 8 | -------------------------------------------------------------------------------- /src/Frontend/src/shared/noop.ts: -------------------------------------------------------------------------------- 1 | export const noop = () => {}; 2 | -------------------------------------------------------------------------------- /src/Frontend/src/shared/useConnectionId.ts: -------------------------------------------------------------------------------- 1 | import {ConnectionHandler} from 'relay-runtime'; 2 | 3 | export const useConnectionId = ( 4 | connectionKey: string, 5 | resourceId: string = 'root', 6 | ) => ConnectionHandler.getConnectionID(resourceId, connectionKey); 7 | -------------------------------------------------------------------------------- /src/Frontend/src/shared/useDelay.ts: -------------------------------------------------------------------------------- 1 | import {useEffect} from 'react'; 2 | 3 | export const useDelay = (cb: () => void, delay: number) => { 4 | useEffect(() => { 5 | (async () => { 6 | await new Promise((x) => setTimeout(x, delay)); 7 | cb(); 8 | })(); 9 | // eslint-disable-next-line react-hooks/exhaustive-deps 10 | }, []); 11 | }; 12 | -------------------------------------------------------------------------------- /src/Frontend/src/shared/useLoadNextChain.ts: -------------------------------------------------------------------------------- 1 | import {useCallback, useRef} from 'react'; 2 | import {LoadMoreFn} from 'react-relay'; 3 | import {OperationType} from 'relay-runtime'; 4 | 5 | export const useLoadNextChain = ( 6 | loadNext: LoadMoreFn, 7 | count: number = 20, 8 | ) => { 9 | const promiseRef = useRef(Promise.resolve()); 10 | return useCallback(() => { 11 | promiseRef.current = promiseRef.current.then(() => { 12 | return new Promise((res, rej) => { 13 | loadNext(count, { 14 | onComplete: (e) => { 15 | if (e) { 16 | rej(e.message); 17 | } else { 18 | res(); 19 | } 20 | }, 21 | }); 22 | }); 23 | }); 24 | }, [loadNext, count]); 25 | }; 26 | -------------------------------------------------------------------------------- /src/Frontend/src/shared/useMultiplexer.ts: -------------------------------------------------------------------------------- 1 | import {useCallback, DependencyList} from 'react'; 2 | 3 | export const useMultiplexer = ( 4 | fns: ((...a: TArgs[]) => void)[], 5 | deps: DependencyList, 6 | ): ((...a: TArgs[]) => void) => { 7 | return useCallback((...a) => { 8 | fns.forEach((x) => x(...a)); 9 | // eslint-disable-next-line react-hooks/exhaustive-deps 10 | }, deps); 11 | }; 12 | -------------------------------------------------------------------------------- /src/Frontend/src/shared/useQuery.ts: -------------------------------------------------------------------------------- 1 | import {useMemo} from 'react'; 2 | import {useLocation} from 'react-router'; 3 | 4 | export const useSearchQuery = () => { 5 | const {search} = useLocation(); 6 | 7 | return useMemo(() => new URLSearchParams(search), [search]); 8 | }; 9 | -------------------------------------------------------------------------------- /src/Frontend/src/shared/useTabSwitcher.ts: -------------------------------------------------------------------------------- 1 | import {useCallback} from 'react'; 2 | import {useLocation} from 'react-router'; 3 | import {useParams, useNavigate} from 'react-router-dom'; 4 | 5 | export const useTabSwitcher = () => { 6 | const {tab} = useParams(); 7 | const navigate = useNavigate(); 8 | const location = useLocation(); 9 | const navigateToTab = useCallback( 10 | (tab: string) => { 11 | navigate( 12 | location.pathname.substring(0, location.pathname.lastIndexOf('/') + 1) + 13 | tab, 14 | ); 15 | }, 16 | [location, navigate], 17 | ); 18 | return {tab, navigateToTab}; 19 | }; 20 | -------------------------------------------------------------------------------- /src/Frontend/src/shared/useToggle.ts: -------------------------------------------------------------------------------- 1 | import {useCallback, useState} from 'react'; 2 | 3 | export const useToggle = ( 4 | initialState = false, 5 | ): [boolean, () => void, () => void, () => void] => { 6 | const [value, setValue] = useState(initialState); 7 | const handleToggle = useCallback(() => setValue(value), [value, setValue]); 8 | const enable = useCallback(() => setValue(true), [setValue]); 9 | const disable = useCallback(() => setValue(false), [setValue]); 10 | return [value, handleToggle, enable, disable]; 11 | }; 12 | -------------------------------------------------------------------------------- /src/Frontend/src/shared/withSilentSuspense.tsx: -------------------------------------------------------------------------------- 1 | import React, {Suspense} from 'react'; 2 | 3 | export const withSilentSuspense = 4 |

(Component: React.ComponentType

): React.FC

=> 5 | (props) => 6 | ( 7 | }> 8 | 9 | 10 | ); 11 | -------------------------------------------------------------------------------- /src/Frontend/src/types/babel-plugin-relay.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'babel-plugin-relay/macro' { 2 | export {graphql} from 'react-relay'; 3 | } 4 | -------------------------------------------------------------------------------- /src/Frontend/src/types/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /src/Frontend/src/variables/variableSchema.tsx: -------------------------------------------------------------------------------- 1 | import * as yup from 'yup'; 2 | 3 | export const variableSchema = yup.object({ 4 | name: yup.string().required('Name is required.'), 5 | isSecret: yup.bool().required('Is secret is required.'), 6 | namespace: yup.string(), 7 | defaultValue: yup.string(), 8 | }); 9 | -------------------------------------------------------------------------------- /src/Frontend/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": ["dom", "dom.iterable", "esnext"], 5 | "allowJs": true, 6 | "skipLibCheck": true, 7 | "esModuleInterop": true, 8 | "allowSyntheticDefaultImports": true, 9 | "strict": true, 10 | "forceConsistentCasingInFileNames": true, 11 | "noFallthroughCasesInSwitch": true, 12 | "module": "esnext", 13 | "moduleResolution": "node", 14 | "resolveJsonModule": true, 15 | "isolatedModules": true, 16 | "noEmit": true, 17 | "jsx": "react-jsx", 18 | "jsxImportSource": "@emotion/react", 19 | "baseUrl": ".", 20 | "paths": { 21 | "@generated/*": ["./src/__generated__/*"] 22 | } 23 | }, 24 | "include": ["src"] 25 | } 26 | -------------------------------------------------------------------------------- /src/Frontend/vite.config.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | import {defineConfig} from 'vite'; 4 | import path from 'path'; 5 | import react from '@vitejs/plugin-react'; 6 | import relay from 'vite-plugin-relay'; 7 | 8 | // https://vitejs.dev/config/ 9 | export default defineConfig({ 10 | plugins: [ 11 | react({ 12 | jsxRuntime: 'automatic', 13 | jsxImportSource: '@emotion/react', 14 | babel: { 15 | plugins: ['@emotion/babel-plugin', 'babel-plugin-relay'], 16 | }, 17 | }), 18 | relay, 19 | ], 20 | resolve: { 21 | alias: { 22 | '@': path.resolve(__dirname, './src'), 23 | '@generated': path.resolve(__dirname, './src/__generated__'), 24 | }, 25 | }, 26 | build: { 27 | outDir: 'build', 28 | chunkSizeWarningLimit: 3000, 29 | }, 30 | server: { 31 | strictPort: true, 32 | port: 3000, 33 | }, 34 | }); 35 | --------------------------------------------------------------------------------