diff --git a/.github/workflows/unstable-release.yaml b/.github/workflows/unstable-release.yaml new file mode 100644 index 000000000..c258f9555 --- /dev/null +++ b/.github/workflows/unstable-release.yaml @@ -0,0 +1,297 @@ +name: Unstable Release + +on: + push: + branches: + # - feature/php-linting # Disabled - now building beta releases instead + - fix/backward-compatibility # Workflow disabled + +jobs: + release-management: + runs-on: ubuntu-latest + steps: + + # Step 1: Checkout Code + - name: Checkout Code + uses: actions/checkout@v3 + with: + fetch-depth: 0 + ssh-key: ${{ secrets.DEPLOY_KEY }} + + # Step 2: Set the app name (use the repo name) + - name: Set app env + run: | + echo "APP_NAME=${GITHUB_REPOSITORY##*/}" >> $GITHUB_ENV + + # Step 3: Get current version from info.xml, increment patch and add unstable suffix + - name: Get current version and append unstable suffix + id: increment_version + run: | + # Get version from main branch + git fetch origin main + main_version=$(git show origin/main:appinfo/info.xml | grep -oP '(?<=)[^<]+' || echo "") + + # Get current version from feature/php-linting branch + current_version=$(grep -oP '(?<=)[^<]+' appinfo/info.xml || echo "") + + # Split main version into parts + IFS='.' read -ra main_version_parts <<< "$main_version" + + # Increment patch version by 1 from main + next_patch=$((main_version_parts[2] + 1)) + + # Extract unstable counter from current version if it exists + unstable_counter=1 + if [[ $current_version =~ -unstable\.([0-9]+)$ ]]; then + # If current patch version is still ahead of main, increment counter + current_patch=$(echo $current_version | grep -oP '^[0-9]+\.[0-9]+\.(\d+)' | cut -d. -f3) + if [ "$current_patch" -eq "$next_patch" ]; then + unstable_counter=$((BASH_REMATCH[1] + 1)) + fi + fi + + unstable_version="${main_version_parts[0]}.${main_version_parts[1]}.${next_patch}-unstable.${unstable_counter}" + + echo "NEW_VERSION=$unstable_version" >> $GITHUB_ENV + echo "new_version=$unstable_version" >> $GITHUB_OUTPUT + echo "Main version: $main_version" + echo "Current version: $current_version" + echo "Using unstable version: $unstable_version" + + # Step 4: Update the version in info.xml + - name: Update version in info.xml + run: | + sed -i "s|.*|${{ env.NEW_VERSION }}|" appinfo/info.xml + + # Step 5: Commit the new version + - name: Commit version update + run: | + git config --local user.email "action@github.com" + git config --local user.name "GitHub Action" + + # Check if there are changes to commit + if git diff --quiet && git diff --cached --quiet; then + echo "No changes to commit" + else + git add appinfo/info.xml + git commit -m "Bump unstable version to ${{ env.NEW_VERSION }} [skip ci]" + git push + fi + + # Step 6: Prepare the signing certificates + - name: Prepare Signing Certificate and Key + run: | + echo "${{ secrets.NEXTCLOUD_SIGNING_CERT }}" > signing-cert.crt + echo "${{ secrets.NEXTCLOUD_SIGNING_KEY }}" > signing-key.key + + # Step 7: Install npm dependencies + - name: Install npm dependencies + uses: actions/setup-node@v3 + with: + node-version: '18.x' + + # Step 8: Set up PHP and install required extensions + - name: Set up PHP and install extensions + uses: shivammathur/setup-php@v2 + with: + php-version: '8.2' + extensions: zip, gd + + # Step 9: Run npm install, build and composer install + - run: npm ci + - run: npm run build + - run: composer install --no-dev --optimize-autoloader --classmap-authoritative + + # Step 9a: Verify vendor dependencies are installed + - name: Verify vendor dependencies + run: | + echo "Checking critical dependencies..." + + # Check that vendor directory exists and has content + if [ ! -d "vendor" ] || [ -z "$(ls -A vendor 2>/dev/null)" ]; then + echo "ERROR: vendor directory is missing or empty" + exit 1 + fi + + # Check specific critical dependencies + missing_deps=0 + + if [ ! -d "vendor/openai-php/client/src" ]; then + echo "ERROR: openai-php/client source files not found" + missing_deps=1 + fi + + if [ ! -d "vendor/theodo-group/llphant/src" ]; then + echo "ERROR: theodo-group/llphant source files not found" + missing_deps=1 + fi + + if [ $missing_deps -eq 1 ]; then + echo "HINT: Check composer.json dependencies and composer install output" + exit 1 + fi + + echo "✓ All critical dependencies verified with source files" + + # Step 10: Copy the files into the package directory + - name: Copy the package files into the package + run: | + mkdir -p package/${{ github.event.repository.name }} + rsync -av --progress \ + --exclude='/package' \ + --exclude='/.git' \ + --exclude='/.github' \ + --exclude='/.cursor' \ + --exclude='/.vscode' \ + --exclude='/.nextcloud' \ + --exclude='/docker' \ + --exclude='/docker-compose.yml' \ + --exclude='/docs' \ + --exclude='/website' \ + --exclude='/node_modules' \ + --exclude='/src' \ + --exclude='/phpcs-custom-sniffs' \ + --exclude='/resources' \ + --exclude='/tests' \ + --exclude='/path' \ + --exclude='/package.json' \ + --exclude='/package-lock.json' \ + --exclude='/composer.json' \ + --exclude='/composer.lock' \ + --exclude='/composer-setup.php' \ + --exclude='/phpcs.xml' \ + --exclude='/phpmd.xml' \ + --exclude='/psalm.xml' \ + --exclude='/phpunit.xml' \ + --exclude='/.phpunit.cache' \ + --exclude='.phpunit.result.cache' \ + --exclude='/jest.config.js' \ + --exclude='/webpack.config.js' \ + --exclude='/tsconfig.json' \ + --exclude='/.babelrc' \ + --exclude='/.eslintrc.js' \ + --exclude='/.prettierrc' \ + --exclude='/stylelint.config.js' \ + --exclude='/.spectral.yml' \ + --exclude='/.gitignore' \ + --exclude='/.gitattributes' \ + --exclude='/.php-cs-fixer.dist.php' \ + --exclude='/.nvmrc' \ + --exclude='/changelog-ci-config.json' \ + --exclude='/coverage.txt' \ + --exclude='/signing-key.key' \ + --exclude='/signing-cert.crt' \ + --exclude='/openapi.json' \ + --exclude='/*_ANALYSIS.md' \ + --exclude='/*_FIX.md' \ + --exclude='/*_SUMMARY.md' \ + --exclude='/*_GUIDE.md' \ + ./ package/${{ github.event.repository.name }}/ + + # Step 11: Verify package contents before creating tarball + - name: Verify package vendor directory + run: | + echo "Verifying package contains complete vendor dependencies..." + + # Check vendor directory was copied + if [ ! -d "package/${{ github.event.repository.name }}/vendor" ]; then + echo "ERROR: vendor directory not found in package" + exit 1 + fi + + # Verify vendor packages have source files (not just LICENSE) + if [ ! -d "package/${{ github.event.repository.name }}/vendor/openai-php/client/src" ]; then + echo "ERROR: openai-php/client/src not found in package" + echo "HINT: Check rsync exclusion patterns - they may be too broad" + ls -la package/${{ github.event.repository.name }}/vendor/openai-php/client/ || true + exit 1 + fi + + # Quick sanity check: count vendor subdirectories + vendor_count=$(find package/${{ github.event.repository.name }}/vendor -maxdepth 1 -type d | wc -l) + if [ $vendor_count -lt 10 ]; then + echo "WARNING: Only $vendor_count vendor directories found (expected 20+)" + echo "Listing vendor contents:" + ls -la package/${{ github.event.repository.name }}/vendor/ + fi + + echo "✓ Package vendor directory verified with source files" + + # Step 12: Create the TAR.GZ archive + - name: Create Tarball + run: | + cd package && tar -czf ../nextcloud-release.tar.gz ${{ github.event.repository.name }} + + # Step 13: Sign the TAR.GZ file with OpenSSL + - name: Sign the TAR.GZ file with OpenSSL + run: | + openssl dgst -sha512 -sign signing-key.key nextcloud-release.tar.gz | openssl base64 -out nextcloud-release.signature + + # Step 13a: Upload tarball as workflow artifact for easy inspection + - name: Upload tarball as artifact + uses: actions/upload-artifact@v4 + with: + name: nextcloud-release-${{ env.NEW_VERSION }} + path: | + nextcloud-release.tar.gz + nextcloud-release.signature + retention-days: 30 + + # Step 14: Generate Git version information (optional, for logging) + - name: Git Version + id: version + uses: codacy/git-version@2.7.1 + with: + release-branch: feature/php-linting + + # Step 15: Extract repository description (optional) + - name: Extract repository description + id: repo-description + run: | + description=$(jq -r '.description' <(curl -s https://api.github.com/repos/${{ github.repository }})) + echo "REPO_DESCRIPTION=$description" >> $GITHUB_ENV + + # Step 16: Output the version (for logging) + - name: Use the version + run: | + echo "Git Version info: ${{ steps.version.outputs.version }}" + + # Step 17: Create a new GitHub release (as prerelease) + - name: Upload Unstable Release + uses: ncipollo/release-action@v1.12.0 + with: + tag: v${{ env.NEW_VERSION }} + name: Unstable Release ${{ env.NEW_VERSION }} + draft: false + prerelease: true + + # Step 18: Attach the tarball as asset to the GitHub release + - name: Attach tarball to GitHub release + uses: svenstaro/upload-release-action@v2 + with: + repo_token: ${{ secrets.GITHUB_TOKEN }} + file: nextcloud-release.tar.gz + asset_name: ${{ env.APP_NAME }}-${{ env.NEW_VERSION }}.tar.gz + tag: v${{ env.NEW_VERSION }} + overwrite: true + + # Step 19: Upload the app to the Nextcloud App Store as unstable/nightly + - name: Upload app to Nextcloud appstore + uses: nextcloud-releases/nextcloud-appstore-push-action@a011fe619bcf6e77ddebc96f9908e1af4071b9c1 + with: + app_name: ${{ env.APP_NAME }} + appstore_token: ${{ secrets.NEXTCLOUD_APPSTORE_TOKEN }} + download_url: https://github.com/${{ github.repository }}/releases/download/v${{ env.NEW_VERSION }}/${{ env.APP_NAME }}-${{ env.NEW_VERSION }}.tar.gz + app_private_key: ${{ secrets.NEXTCLOUD_SIGNING_KEY }} + nightly: true + + # Step 20: Verify the release + - name: Verify version and contents + run: | + echo "App version: ${{ env.NEW_VERSION }}" + echo "Tarball contents:" + tar -tvf nextcloud-release.tar.gz | head -100 + echo "Verify vendor directory in tarball:" + tar -tvf nextcloud-release.tar.gz | grep "vendor/openai-php/client" | head -5 || echo "WARNING: openai-php/client not found in tarball!" + echo "info.xml contents:" + tar -xOf nextcloud-release.tar.gz ${{ env.APP_NAME }}/appinfo/info.xml diff --git a/README.md b/README.md index 50d73bacc..eb45cc94d 100644 --- a/README.md +++ b/README.md @@ -200,7 +200,7 @@ This monorepo is a Nextcloud app, it is based on the following structure: ├── templates/ # Template files for rendering app views └── website/ # Documentation website source files -When running locally, or in development mode the folders nodus_modules and vendor are added. Thes shoudl however not be commited. +When running locally, or in development mode the folders nodus_modules and vendor are added. These should however not be commited. ## Contributing diff --git a/appinfo/routes.php b/appinfo/routes.php index 930d4e98e..c52fe6ecd 100644 --- a/appinfo/routes.php +++ b/appinfo/routes.php @@ -17,14 +17,14 @@ ['name' => 'configurations#patch', 'url' => '/api/configurations/{id}', 'verb' => 'PATCH', 'requirements' => ['id' => '[^/]+']], ['name' => 'applications#patch', 'url' => '/api/applications/{id}', 'verb' => 'PATCH', 'requirements' => ['id' => '[^/]+']], ['name' => 'agents#patch', 'url' => '/api/agents/{id}', 'verb' => 'PATCH', 'requirements' => ['id' => '[^/]+']], - + // Settings - Legacy endpoints (kept for compatibility) ['name' => 'settings#index', 'url' => '/api/settings', 'verb' => 'GET'], ['name' => 'settings#update', 'url' => '/api/settings', 'verb' => 'PUT'], ['name' => 'settings#rebase', 'url' => '/api/settings/rebase', 'verb' => 'POST'], ['name' => 'settings#stats', 'url' => '/api/settings/stats', 'verb' => 'GET'], - + // Settings - Focused endpoints for better performance ['name' => 'settings#getSolrSettings', 'url' => '/api/settings/solr', 'verb' => 'GET'], ['name' => 'settings#updateSolrSettings', 'url' => '/api/settings/solr', 'verb' => 'PATCH'], @@ -42,25 +42,25 @@ ['name' => 'settings#createMissingSolrFields', 'url' => '/api/solr/fields/create-missing', 'verb' => 'POST'], ['name' => 'settings#fixMismatchedSolrFields', 'url' => '/api/solr/fields/fix-mismatches', 'verb' => 'POST'], ['name' => 'settings#deleteSolrField', 'url' => '/api/solr/fields/{fieldName}', 'verb' => 'DELETE', 'requirements' => ['fieldName' => '[^/]+']], - + // Collection-specific field management ['name' => 'settings#getObjectCollectionFields', 'url' => '/api/solr/collections/objects/fields', 'verb' => 'GET'], ['name' => 'settings#getFileCollectionFields', 'url' => '/api/solr/collections/files/fields', 'verb' => 'GET'], ['name' => 'settings#createMissingObjectFields', 'url' => '/api/solr/collections/objects/fields/create-missing', 'verb' => 'POST'], ['name' => 'settings#createMissingFileFields', 'url' => '/api/solr/collections/files/fields/create-missing', 'verb' => 'POST'], - + // SOLR Dashboard Management endpoints ['name' => 'settings#getSolrDashboardStats', 'url' => '/api/solr/dashboard/stats', 'verb' => 'GET'], ['name' => 'settings#inspectSolrIndex', 'url' => '/api/settings/solr/inspect', 'verb' => 'POST'], ['name' => 'settings#manageSolr', 'url' => '/api/solr/manage/{operation}', 'verb' => 'POST'], ['name' => 'settings#setupSolr', 'url' => '/api/solr/setup', 'verb' => 'POST'], ['name' => 'settings#testSolrSetup', 'url' => '/api/solr/test-setup', 'verb' => 'POST'], - + // Collection-specific operations (with collection name parameter) ['name' => 'settings#deleteSpecificSolrCollection', 'url' => '/api/solr/collections/{name}', 'verb' => 'DELETE', 'requirements' => ['name' => '[^/]+']], ['name' => 'settings#clearSpecificCollection', 'url' => '/api/solr/collections/{name}/clear', 'verb' => 'POST', 'requirements' => ['name' => '[^/]+']], ['name' => 'settings#reindexSpecificCollection', 'url' => '/api/solr/collections/{name}/reindex', 'verb' => 'POST', 'requirements' => ['name' => '[^/]+']], - + // SOLR Collection and ConfigSet Management endpoints (SolrController) ['name' => 'solr#listCollections', 'url' => '/api/solr/collections', 'verb' => 'GET'], ['name' => 'solr#createCollection', 'url' => '/api/solr/collections', 'verb' => 'POST'], @@ -69,30 +69,30 @@ ['name' => 'solr#deleteConfigSet', 'url' => '/api/solr/configsets/{name}', 'verb' => 'DELETE'], ['name' => 'solr#copyCollection', 'url' => '/api/solr/collections/copy', 'verb' => 'POST'], ['name' => 'settings#updateSolrCollectionAssignments', 'url' => '/api/solr/collections/assignments', 'verb' => 'PUT'], - + // Vector Search endpoints (Semantic and Hybrid Search) - SolrController ['name' => 'solr#semanticSearch', 'url' => '/api/search/semantic', 'verb' => 'POST'], ['name' => 'solr#hybridSearch', 'url' => '/api/search/hybrid', 'verb' => 'POST'], ['name' => 'solr#getVectorStats', 'url' => '/api/vectors/stats', 'verb' => 'GET'], ['name' => 'solr#testVectorEmbedding', 'url' => '/api/vectors/test', 'verb' => 'POST'], - + // Object Vectorization endpoints - SolrController ['name' => 'solr#vectorizeObject', 'url' => '/api/objects/{objectId}/vectorize', 'verb' => 'POST'], ['name' => 'solr#bulkVectorizeObjects', 'url' => '/api/objects/vectorize/bulk', 'verb' => 'POST'], ['name' => 'solr#getVectorizationStats', 'url' => '/api/solr/vectorize/stats', 'verb' => 'GET'], - + ['name' => 'settings#getRbacSettings', 'url' => '/api/settings/rbac', 'verb' => 'GET'], ['name' => 'settings#updateRbacSettings', 'url' => '/api/settings/rbac', 'verb' => 'PATCH'], ['name' => 'settings#updateRbacSettings', 'url' => '/api/settings/rbac', 'verb' => 'PUT'], - + ['name' => 'settings#getMultitenancySettings', 'url' => '/api/settings/multitenancy', 'verb' => 'GET'], ['name' => 'settings#updateMultitenancySettings', 'url' => '/api/settings/multitenancy', 'verb' => 'PATCH'], ['name' => 'settings#updateMultitenancySettings', 'url' => '/api/settings/multitenancy', 'verb' => 'PUT'], - + ['name' => 'settings#getOrganisationSettings', 'url' => '/api/settings/organisation', 'verb' => 'GET'], ['name' => 'settings#updateOrganisationSettings', 'url' => '/api/settings/organisation', 'verb' => 'PATCH'], ['name' => 'settings#updateOrganisationSettings', 'url' => '/api/settings/organisation', 'verb' => 'PUT'], - + ['name' => 'settings#getLLMSettings', 'url' => '/api/settings/llm', 'verb' => 'GET'], ['name' => 'settings#getDatabaseInfo', 'url' => '/api/settings/database', 'verb' => 'GET'], ['name' => 'settings#getSolrInfo', 'url' => '/api/settings/solr-info', 'verb' => 'GET'], @@ -113,12 +113,12 @@ ['name' => 'settings#updateObjectSettings', 'url' => '/api/settings/objects/vectorize', 'verb' => 'POST'], ['name' => 'settings#patchObjectSettings', 'url' => '/api/settings/objects/vectorize', 'verb' => 'PATCH'], ['name' => 'settings#updateObjectSettings', 'url' => '/api/settings/objects/vectorize', 'verb' => 'PUT'], - + // Object vectorization endpoints ['name' => 'objects#vectorizeBatch', 'url' => '/api/objects/vectorize/batch', 'verb' => 'POST'], ['name' => 'objects#getObjectVectorizationCount', 'url' => '/api/objects/vectorize/count', 'verb' => 'GET'], ['name' => 'objects#getObjectVectorizationStats', 'url' => '/api/objects/vectorize/stats', 'verb' => 'GET'], - + // Core file extraction endpoints (use fileExtraction controller to avoid conflict with files controller) // NOTE: Specific routes MUST come before parameterized routes like {id} ['name' => 'fileExtraction#index', 'url' => '/api/files', 'verb' => 'GET'], @@ -131,25 +131,25 @@ ['name' => 'fileExtraction#cleanup', 'url' => '/api/files/cleanup', 'verb' => 'POST'], ['name' => 'fileExtraction#show', 'url' => '/api/files/{id}', 'verb' => 'GET'], ['name' => 'fileExtraction#extract', 'url' => '/api/files/{id}/extract', 'verb' => 'POST'], - + ['name' => 'settings#getRetentionSettings', 'url' => '/api/settings/retention', 'verb' => 'GET'], - + // Debug endpoints for type filtering issue ['name' => 'settings#debugTypeFiltering', 'url' => '/api/debug/type-filtering', 'verb' => 'GET'], ['name' => 'settings#updateRetentionSettings', 'url' => '/api/settings/retention', 'verb' => 'PATCH'], ['name' => 'settings#updateRetentionSettings', 'url' => '/api/settings/retention', 'verb' => 'PUT'], - + ['name' => 'settings#getVersionInfo', 'url' => '/api/settings/version', 'verb' => 'GET'], - + // API Tokens for GitHub and GitLab ['name' => 'settings#getApiTokens', 'url' => '/api/settings/api-tokens', 'verb' => 'GET'], ['name' => 'settings#saveApiTokens', 'url' => '/api/settings/api-tokens', 'verb' => 'POST'], ['name' => 'settings#testGitHubToken', 'url' => '/api/settings/api-tokens/test/github', 'verb' => 'POST'], ['name' => 'settings#testGitLabToken', 'url' => '/api/settings/api-tokens/test/gitlab', 'verb' => 'POST'], - - // Statistics endpoint + + // Statistics endpoint ['name' => 'settings#getStatistics', 'url' => '/api/settings/statistics', 'verb' => 'GET'], - + // Cache management ['name' => 'settings#getCacheStats', 'url' => '/api/settings/cache', 'verb' => 'GET'], ['name' => 'settings#clearCache', 'url' => '/api/settings/cache', 'verb' => 'DELETE'], @@ -181,7 +181,7 @@ ['name' => 'objects#objects', 'url' => '/api/objects', 'verb' => 'GET'], // ['name' => 'objects#import', 'url' => '/api/objects/{register}/import', 'verb' => 'POST'], // DISABLED: Use registers import endpoint instead ['name' => 'objects#index', 'url' => '/api/objects/{register}/{schema}', 'verb' => 'GET'], - + ['name' => 'objects#create', 'url' => '/api/objects/{register}/{schema}', 'verb' => 'POST'], ['name' => 'objects#export', 'url' => '/api/objects/{register}/{schema}/export', 'verb' => 'GET'], ['name' => 'objects#show', 'url' => '/api/objects/{register}/{schema}/{id}', 'verb' => 'GET', 'requirements' => ['id' => '[^/]+']], @@ -190,7 +190,7 @@ ['name' => 'objects#destroy', 'url' => '/api/objects/{register}/{schema}/{id}', 'verb' => 'DELETE', 'requirements' => ['id' => '[^/]+']], ['name' => 'objects#merge', 'url' => '/api/objects/{register}/{schema}/{id}/merge', 'verb' => 'POST', 'requirements' => ['id' => '[^/]+']], ['name' => 'objects#migrate', 'url' => '/api/migrate', 'verb' => 'POST'], - // Relations + // Relations ['name' => 'objects#contracts', 'url' => '/api/objects/{register}/{schema}/{id}/contracts', 'verb' => 'GET', 'requirements' => ['id' => '[^/]+']], ['name' => 'objects#uses', 'url' => '/api/objects/{register}/{schema}/{id}/uses', 'verb' => 'GET', 'requirements' => ['id' => '[^/]+']], ['name' => 'objects#used', 'url' => '/api/objects/{register}/{schema}/{id}/used', 'verb' => 'GET', 'requirements' => ['id' => '[^/]+']], @@ -239,22 +239,22 @@ ['name' => 'deleted#destroyMultiple', 'url' => '/api/deleted', 'verb' => 'DELETE'], // Revert ['name' => 'revert#revert', 'url' => '/api/objects/{register}/{schema}/{id}/revert', 'verb' => 'POST', 'requirements' => ['id' => '[^/]+']], - + // Files operations under objects ['name' => 'files#create', 'url' => 'api/objects/{register}/{schema}/{id}/files', 'verb' => 'POST'], ['name' => 'files#save', 'url' => 'api/objects/{register}/{schema}/{id}/files/save', 'verb' => 'POST'], ['name' => 'files#index', 'url' => 'api/objects/{register}/{schema}/{id}/files', 'verb' => 'GET'], ['name' => 'files#show', 'url' => 'api/objects/{register}/{schema}/{id}/files/{fileId}', 'verb' => 'GET', 'requirements' => ['fileId' => '\d+']], ['name' => 'objects#downloadFiles', 'url' => '/api/objects/{register}/{schema}/{id}/files/download', 'verb' => 'GET', 'requirements' => ['id' => '[^/]+']], - ['name' => 'files#createMultipart', 'url' => 'api/objects/{register}/{schema}/{id}/filesMultipart', 'verb' => 'POST'], + ['name' => 'files#createMultipart', 'url' => 'api/objects/{register}/{schema}/{id}/filesMultipart', 'verb' => 'POST'], ['name' => 'files#update', 'url' => 'api/objects/{register}/{schema}/{id}/files/{fileId}', 'verb' => 'PUT', 'requirements' => ['fileId' => '\d+']], ['name' => 'files#delete', 'url' => 'api/objects/{register}/{schema}/{id}/files/{fileId}', 'verb' => 'DELETE', 'requirements' => ['fileId' => '\d+']], ['name' => 'files#publish', 'url' => 'api/objects/{register}/{schema}/{id}/files/{fileId}/publish', 'verb' => 'POST', 'requirements' => ['fileId' => '\d+']], ['name' => 'files#depublish', 'url' => 'api/objects/{register}/{schema}/{id}/files/{fileId}/depublish', 'verb' => 'POST', 'requirements' => ['fileId' => '\d+']], - + // Direct file access by ID (authenticated) ['name' => 'files#downloadById', 'url' => '/api/files/{fileId}/download', 'verb' => 'GET', 'requirements' => ['fileId' => '\d+']], - + // Schemas ['name' => 'schemas#upload', 'url' => '/api/schemas/upload', 'verb' => 'POST'], ['name' => 'schemas#uploadUpdate', 'url' => '/api/schemas/{id}/upload', 'verb' => 'PUT', 'requirements' => ['id' => '[^/]+']], @@ -280,7 +280,10 @@ ['name' => 'configuration#preview', 'url' => '/api/configurations/{id}/preview', 'verb' => 'GET', 'requirements' => ['id' => '\d+']], ['name' => 'configuration#import', 'url' => '/api/configurations/{id}/import', 'verb' => 'POST', 'requirements' => ['id' => '\d+']], ['name' => 'configuration#export', 'url' => '/api/configurations/{id}/export', 'verb' => 'GET', 'requirements' => ['id' => '\d+']], - + + // @TODO: Backwards compatibility measure + ['name' => 'configurations#import', 'url' => '/api/configurations/import', 'verb' => 'POST'], + // Configuration discovery endpoints ['name' => 'configuration#discover', 'url' => '/api/configurations/discover', 'verb' => 'GET'], ['name' => 'configuration#enrichDetails', 'url' => '/api/configurations/enrich', 'verb' => 'GET'], @@ -289,15 +292,15 @@ ['name' => 'configuration#getGitHubConfigurations', 'url' => '/api/configurations/github/files', 'verb' => 'GET'], ['name' => 'configuration#getGitLabBranches', 'url' => '/api/configurations/gitlab/branches', 'verb' => 'GET'], ['name' => 'configuration#getGitLabConfigurations', 'url' => '/api/configurations/gitlab/files', 'verb' => 'GET'], - + // Configuration import endpoints ['name' => 'configuration#importFromGitHub', 'url' => '/api/configurations/import/github', 'verb' => 'POST'], ['name' => 'configuration#importFromGitLab', 'url' => '/api/configurations/import/gitlab', 'verb' => 'POST'], ['name' => 'configuration#importFromUrl', 'url' => '/api/configurations/import/url', 'verb' => 'POST'], - + // Configuration publish endpoints ['name' => 'configuration#publishToGitHub', 'url' => '/api/configurations/{id}/publish/github', 'verb' => 'POST'], - + // User Settings - GitHub Integration ['name' => 'userSettings#getGitHubTokenStatus', 'url' => '/api/user-settings/github/status', 'verb' => 'GET'], ['name' => 'userSettings#setGitHubToken', 'url' => '/api/user-settings/github/token', 'verb' => 'POST'], @@ -327,7 +330,7 @@ ['name' => 'organisation#leave', 'url' => '/api/organisations/{uuid}/leave', 'verb' => 'POST'], // Tags ['name' => 'tags#getAllTags', 'url' => 'api/tags', 'verb' => 'GET'], - + // Views - Saved search configurations ['name' => 'views#index', 'url' => '/api/views', 'verb' => 'GET'], ['name' => 'views#show', 'url' => '/api/views/{id}', 'verb' => 'GET', 'requirements' => ['id' => '[^/]+']], @@ -335,14 +338,14 @@ ['name' => 'views#update', 'url' => '/api/views/{id}', 'verb' => 'PUT', 'requirements' => ['id' => '[^/]+']], ['name' => 'views#patch', 'url' => '/api/views/{id}', 'verb' => 'PATCH', 'requirements' => ['id' => '[^/]+']], ['name' => 'views#destroy', 'url' => '/api/views/{id}', 'verb' => 'DELETE', 'requirements' => ['id' => '[^/]+']], - + // Chat - AI Assistant endpoints ['name' => 'chat#sendMessage', 'url' => '/api/chat/send', 'verb' => 'POST'], ['name' => 'chat#getHistory', 'url' => '/api/chat/history', 'verb' => 'GET'], ['name' => 'chat#clearHistory', 'url' => '/api/chat/history', 'verb' => 'DELETE'], ['name' => 'chat#getChatStats', 'url' => '/api/chat/stats', 'verb' => 'GET'], ['name' => 'chat#sendFeedback', 'url' => '/api/conversations/{conversationUuid}/messages/{messageId}/feedback', 'verb' => 'POST', 'requirements' => ['conversationUuid' => '[^/]+', 'messageId' => '\\d+']], - + // Conversations - AI Conversation management ['name' => 'conversation#index', 'url' => '/api/conversations', 'verb' => 'GET'], ['name' => 'conversation#show', 'url' => '/api/conversations/{uuid}', 'verb' => 'GET', 'requirements' => ['uuid' => '[^/]+']], @@ -352,25 +355,25 @@ ['name' => 'conversation#destroy', 'url' => '/api/conversations/{uuid}', 'verb' => 'DELETE', 'requirements' => ['uuid' => '[^/]+']], ['name' => 'conversation#restore', 'url' => '/api/conversations/{uuid}/restore', 'verb' => 'POST', 'requirements' => ['uuid' => '[^/]+']], ['name' => 'conversation#destroyPermanent', 'url' => '/api/conversations/{uuid}/permanent', 'verb' => 'DELETE', 'requirements' => ['uuid' => '[^/]+']], - + // File Text Management - Extract and manage text from files ['name' => 'fileText#getFileText', 'url' => '/api/files/{fileId}/text', 'verb' => 'GET', 'requirements' => ['fileId' => '\\d+']], ['name' => 'fileText#extractFileText', 'url' => '/api/files/{fileId}/extract', 'verb' => 'POST', 'requirements' => ['fileId' => '\\d+']], ['name' => 'fileText#bulkExtract', 'url' => '/api/files/extract/bulk', 'verb' => 'POST'], ['name' => 'fileText#getStats', 'url' => '/api/files/extraction/stats', 'verb' => 'GET'], ['name' => 'fileText#deleteFileText', 'url' => '/api/files/{fileId}/text', 'verb' => 'DELETE', 'requirements' => ['fileId' => '\\d+']], - + // File Chunking & Indexing - Process extracted files and index chunks in SOLR ['name' => 'fileText#processAndIndexExtracted', 'url' => '/api/files/chunks/process', 'verb' => 'POST'], ['name' => 'fileText#processAndIndexFile', 'url' => '/api/files/{fileId}/chunks/process', 'verb' => 'POST', 'requirements' => ['fileId' => '\\d+']], ['name' => 'fileText#getChunkingStats', 'url' => '/api/files/chunks/stats', 'verb' => 'GET'], - + // File Warmup & Indexing - Bulk process and index files in SOLR ['name' => 'settings#warmupFiles', 'url' => '/api/solr/warmup/files', 'verb' => 'POST'], ['name' => 'settings#indexFile', 'url' => '/api/solr/files/{fileId}/index', 'verb' => 'POST', 'requirements' => ['fileId' => '\\d+']], ['name' => 'settings#reindexFiles', 'url' => '/api/solr/files/reindex', 'verb' => 'POST'], ['name' => 'settings#getFileIndexStats', 'url' => '/api/solr/files/stats', 'verb' => 'GET'], - + // File Search - Keyword, semantic, and hybrid search over file contents ['name' => 'fileSearch#keywordSearch', 'url' => '/api/search/files/keyword', 'verb' => 'POST'], ['name' => 'fileSearch#semanticSearch', 'url' => '/api/search/files/semantic', 'verb' => 'POST'], diff --git a/lib/AppInfo/Application.php b/lib/AppInfo/Application.php index 01268ce85..02c090ad6 100644 --- a/lib/AppInfo/Application.php +++ b/lib/AppInfo/Application.php @@ -788,6 +788,33 @@ public function boot(IBootContext $context): void $logger->debug('SOLR Nightly Warmup Job already registered'); } + + $logger->info('OpenRegister boot: Set multitenancy settings'); + /** @var SettingsService $settingsService */ + $settingsService = $container->get(SettingsService::class); + + $multiTenancySettings = $settingsService->getMultitenancySettings(); + + if ($multiTenancySettings['multitenancy']['enabled'] === true && $multiTenancySettings['multitenancy']['defaultUserTenant'] === '' && count($multiTenancySettings['availableTenants']) >= 1) { + $orgs = array_filter($multiTenancySettings['availableTenants'], function ($tenant) { return $tenant['name'] === 'Default organisation';}); + + $defaultOrg = array_shift($orgs); + $multiTenancySettings['multitenancy']['defaultUserTenant'] = ['label' => $defaultOrg['name'], 'id' => $defaultOrg['uuid']]; + $multiTenancySettings['multitenancy']['defaultObjectTenant'] = ['label' => $defaultOrg['name'], 'id' => $defaultOrg['uuid']]; + + $settingsService->updateMultitenancySettingsOnly($multiTenancySettings['multitenancy']); + + } elseif ($multiTenancySettings['multitenancy']['enabled'] === true && $multiTenancySettings['multitenancy']['defaultUserTenant'] === '') { + /** @var OrganisationService $organisationService */ + $organisationService = $container->get(OrganisationService::class); + + $defaultOrg = $organisationService->ensureDefaultOrganisation(); + $multiTenancySettings['multitenancy']['defaultUserTenant'] = ['label' => $defaultOrg->getName(), 'id' => $defaultOrg->getUuid()]; + $multiTenancySettings['multitenancy']['defaultObjectTenant'] = ['label' => $defaultOrg->getName(), 'id' => $defaultOrg->getUuid()]; + + $settingsService->updateMultitenancySettingsOnly($multiTenancySettings['multitenancy']); + } + } catch (\Exception $e) { $logger->error('OpenRegister boot: Failed to register event listeners and background jobs', [ 'exception' => $e->getMessage(), diff --git a/lib/Db/MultiTenancyTrait.php b/lib/Db/MultiTenancyTrait.php index adea8fb81..541b22888 100644 --- a/lib/Db/MultiTenancyTrait.php +++ b/lib/Db/MultiTenancyTrait.php @@ -36,7 +36,7 @@ * - The mapper must inject IGroupManager ($this->groupManager - for RBAC) * - The mapper must inject IUserSession ($this->userSession - for current user) * - The mapper must have access to IDBConnection via $this->db (from QBMapper parent) - * + * * Optional dependencies for advanced features: * - IAppConfig ($this->appConfig) - for multitenancy config settings * - LoggerInterface ($this->logger) - for debug logging @@ -66,11 +66,11 @@ protected function getActiveOrganisationUuid(): ?string /** * Get active organisation UUIDs (active + all parents) - * + * * Returns array of organisation UUIDs that the current user can access. * Includes the active organisation and all parent organisations in the hierarchy. * Used for filtering queries to allow access to parent resources. - * + * * @return array Array of organisation UUIDs */ protected function getActiveOrganisationUuids(): array @@ -78,7 +78,7 @@ protected function getActiveOrganisationUuids(): array if (isset($this->organisationService) === false) { return []; } - + return $this->organisationService->getUserActiveOrganisations(); }//end getActiveOrganisationUuids() @@ -182,8 +182,8 @@ protected function isCurrentUserAdmin(): bool * @return void */ protected function applyOrganisationFilter( - IQueryBuilder $qb, - string $columnName = 'organisation', + IQueryBuilder $qb, + string $columnName = 'organisation', bool $allowNullOrg = false, string $tableAlias = '', bool $enablePublished = false, @@ -193,7 +193,7 @@ protected function applyOrganisationFilter( if ($multiTenancyEnabled === false) { return; } - + // Check if multitenancy is enabled (if appConfig is available) // Only check app config if parameter was not explicitly set to false if (isset($this->appConfig) === true) { @@ -201,14 +201,14 @@ protected function applyOrganisationFilter( if (empty($multitenancyConfig) === false) { $multitenancyData = json_decode($multitenancyConfig, true); $configMultitenancyEnabled = $multitenancyData['enabled'] ?? true; - + if ($configMultitenancyEnabled === false) { // Multitenancy is disabled in config, no filtering return; } } } - + // Get current user $user = $this->userSession->getUser(); $userId = $user ? $user->getUID() : null; @@ -224,10 +224,10 @@ protected function applyOrganisationFilter( // Get active organisation UUIDs (active + all parents) $activeOrganisationUuids = $this->getActiveOrganisationUuids(); - + // Build fully qualified column name $organisationColumn = $tableAlias ? $tableAlias . '.' . $columnName : $columnName; - + // Check if published entities should bypass multi-tenancy (works for objects, schemas, registers) $publishedBypassEnabled = false; if ($enablePublished === true && isset($this->appConfig) === true) { @@ -237,7 +237,7 @@ protected function applyOrganisationFilter( $publishedBypassEnabled = $multitenancyData['publishedObjectsBypassMultiTenancy'] ?? false; } } - + // CASE 1: No active organisation set if (empty($activeOrganisationUuids) === true) { // Build conditions for users without active organisation @@ -255,6 +255,12 @@ protected function applyOrganisationFilter( $orgConditions->add($qb->expr()->isNull($organisationColumn)); } + if ($user === null) { + $defaultOrg = $this->organisationService->getDefaultUserTenant(); + + $orgConditions->add($qb->expr()->eq(x: $organisationColumn, y: $qb->createNamedParameter(value: $defaultOrg->getUuid(), type: IQueryBuilder::PARAM_STR))); + } + // Include published entities if bypass is enabled (works for objects, schemas, registers) // Note: Organizations can see their own depublished items via the organization filter above. // The depublished check here only applies to the published bypass (entities from OTHER organizations). @@ -262,7 +268,7 @@ protected function applyOrganisationFilter( $now = (new \DateTime())->format('Y-m-d H:i:s'); $publishedColumn = $tableAlias ? $tableAlias . '.published' : 'published'; $depublishedColumn = $tableAlias ? $tableAlias . '.depublished' : 'depublished'; - + // Published bypass condition: entity must be published AND not depublished // This ensures depublished entities from OTHER organizations are never visible via published bypass $orgConditions->add( @@ -288,7 +294,7 @@ protected function applyOrganisationFilter( } return; } - + // CASE 2: Active organisation(s) set // Check admin status and admin override setting - only if user exists @@ -297,7 +303,7 @@ protected function applyOrganisationFilter( $userGroups = $this->groupManager->getUserGroupIds($user); $isAdmin = in_array('admin', $userGroups); } - + $adminOverrideEnabled = false; if ($isAdmin === true && isset($this->appConfig) === true) { $multitenancyConfig = $this->appConfig->getValueString('openregister', 'multitenancy', ''); @@ -306,13 +312,13 @@ protected function applyOrganisationFilter( $adminOverrideEnabled = $multitenancyData['adminOverride'] ?? false; } } - + // Apply admin override logic if ($isAdmin === true && $adminOverrideEnabled === true) { // Admin override enabled - admins see everything return; } - + // Build organisation filter conditions $orgConditions = $qb->expr()->orX(); @@ -338,7 +344,7 @@ protected function applyOrganisationFilter( $orgConditions->add( $qb->expr()->eq($organisationColumn, $qb->createNamedParameter($directActiveOrgUuid, IQueryBuilder::PARAM_STR)) ); - + // Condition 2: Entity from parent organizations (children can see all parent objects, including depublished) // Only add this if there are parent organizations $parentOrgs = array_filter($activeOrganisationUuids, function($uuid) use ($directActiveOrgUuid) { @@ -355,10 +361,10 @@ protected function applyOrganisationFilter( $qb->expr()->in($organisationColumn, $qb->createNamedParameter($activeOrganisationUuids, IQueryBuilder::PARAM_STR_ARRAY)) ); } - + // Include published entities if bypass is enabled (works for objects, schemas, registers) - // + // // BEHAVIOR WHEN ENABLED: // - Published objects bypass RBAC read permissions (anyone can read published objects) // - Published objects bypass organization filtering (visible from ANY organization) diff --git a/lib/Service/ConfigurationService.php b/lib/Service/ConfigurationService.php index 85b8dfd8a..a2bf56fd6 100644 --- a/lib/Service/ConfigurationService.php +++ b/lib/Service/ConfigurationService.php @@ -19,6 +19,7 @@ namespace OCA\OpenRegister\Service; +use DateTime; use Exception; use GuzzleHttp\Client; use GuzzleHttp\Exception\GuzzleException; @@ -324,8 +325,8 @@ public function exportConfig(array | Configuration | Register $input=[], bool $i // Add OpenRegister-specific metadata as an extension following OpenAPI spec // https://swagger.io/docs/specification/v3_0/openapi-extensions/ // Standard OAS properties (title, description, version) are in the info section above - // Note: Internal properties (autoUpdate, notificationGroups, owner, organisation, registers, - // schemas, objects, views, agents, sources, applications) are excluded as they are + // Note: Internal properties (autoUpdate, notificationGroups, owner, organisation, registers, + // schemas, objects, views, agents, sources, applications) are excluded as they are // instance-specific or automatically managed during import $openApiSpec['x-openregister'] = [ 'type' => $input->getType(), @@ -640,13 +641,13 @@ private function exportObject(ObjectEntity $object): array { // Use jsonSerialize to get the JSON representation of the object. $objectArray = $object->jsonSerialize(); - + // Remove organisation if present (though objects typically don't have this at top level) // Organisation is instance-specific and should not be exported. if (isset($objectArray['organisation']) === true) { unset($objectArray['organisation']); } - + return $objectArray; }//end exportObject() @@ -902,11 +903,16 @@ public function importFromJson(array $data, ?Configuration $configuration=null, { // ⚠️ CRITICAL: Configuration entity is required for proper tracking if ($configuration === null) { + $now = new DateTime(); + $configuration = new Configuration(); + $configuration->setTitle("imported-configuration-{$now->format('c')}"); + /* throw new Exception( 'importFromJson must be called with a Configuration entity. ' . 'Direct imports without a Configuration are not allowed to ensure proper entity tracking. ' . 'Please create a Configuration entity first before importing.' ); + */ } // Ensure data is consistently an array by converting any stdClass objects $data = $this->ensureArrayStructure($data); @@ -1122,11 +1128,11 @@ public function importFromJson(array $data, ?Configuration $configuration=null, '_limit' => 1, ]; $this->logger->debug('Import object search filter', ['filter' => $search]); - + // Search for existing object $results = $this->objectService->searchObjects($search, true, true); $existingObject = is_array($results) && count($results) > 0 ? $results[0] : null; - + if (!$existingObject) { $this->logger->info( 'No existing object found - will create new object', @@ -1142,7 +1148,7 @@ public function importFromJson(array $data, ?Configuration $configuration=null, // This prevents any internal lookups from using string slugs $objectData['@self']['register'] = (int) $registerId; $objectData['@self']['schema'] = (int) $schemaId; - + if ($existingObject) { $existingObjectData = is_array($existingObject) ? $existingObject : $existingObject->jsonSerialize(); $importedVersion = $objectData['@self']['version'] ?? $objectData['version'] ?? '1.0.0'; @@ -1249,11 +1255,11 @@ private function createOrUpdateConfiguration(array $data, string $appId, string // Extract metadata following OAS standard first, then x-openregister extension $info = $data['info'] ?? []; $xOpenregister = $data['x-openregister'] ?? []; - + // Standard OAS properties from info section $title = $info['title'] ?? $xOpenregister['title'] ?? $data['title'] ?? "Configuration for {$appId}"; $description = $info['description'] ?? $xOpenregister['description'] ?? $data['description'] ?? "Imported configuration for application {$appId}"; - + // OpenRegister-specific properties $type = $xOpenregister['type'] ?? $data['type'] ?? 'imported'; @@ -1308,19 +1314,19 @@ private function createOrUpdateConfiguration(array $data, string $appId, string $configuration->setRegisters($registerIds); $configuration->setSchemas($schemaIds); $configuration->setObjects($objectIds); - + // Mark as local configuration (maintained by the app) $configuration->setIsLocal(true); $configuration->setSyncEnabled(false); $configuration->setSyncStatus('never'); - + // Set version requirements from x-openregister if available if (isset($xOpenregister['openregister']) === true) { $configuration->setOpenregister($xOpenregister['openregister']); } - + // Set additional metadata from x-openregister if available - // Note: Internal properties (autoUpdate, notificationGroups, owner, organisation) + // Note: Internal properties (autoUpdate, notificationGroups, owner, organisation) // are not imported as they are instance-specific settings if (isset($xOpenregister['sourceType']) === true) { $configuration->setSourceType($xOpenregister['sourceType']); @@ -1328,7 +1334,7 @@ private function createOrUpdateConfiguration(array $data, string $appId, string if (isset($xOpenregister['sourceUrl']) === true) { $configuration->setSourceUrl($xOpenregister['sourceUrl']); } - + // Support both nested github structure (new) and flat structure (backward compatibility) if (isset($xOpenregister['github']) === true && is_array($xOpenregister['github'])) { // New nested structure @@ -1353,7 +1359,7 @@ private function createOrUpdateConfiguration(array $data, string $appId, string $configuration->setGithubPath($xOpenregister['githubPath']); } } - + // Set owner from parameter if provided (for backward compatibility) if ($owner !== null) { $configuration->setOwner($owner); @@ -1677,6 +1683,11 @@ private function importSchema(array $data, array $slugsAndIdsMap, ?string $owner $property['items']['register'] = $this->registersMap[$property['items']['register']]->getId(); } } + + // OpenRegister cant save oneOf + if (isset($property['oneOf']) === true) { + $property['oneOf'] = []; + } }//end foreach }//end if @@ -1912,23 +1923,23 @@ public function importFromFilePath(string $appId, string $filePath, string $vers // Resolve the file path relative to Nextcloud root $fullPath = $this->appDataPath . '/../../../' . $filePath; $fullPath = realpath($fullPath); - + if ($fullPath === false || !file_exists($fullPath)) { throw new Exception("Configuration file not found: {$filePath}"); } - + // Read the file contents $jsonContent = file_get_contents($fullPath); if ($jsonContent === false) { throw new Exception("Failed to read configuration file: {$filePath}"); } - + // Parse JSON $data = json_decode($jsonContent, true); if (json_last_error() !== JSON_ERROR_NONE) { throw new Exception("Invalid JSON in configuration file: " . json_last_error_msg()); } - + // Set the sourceUrl in the data if not already set // This allows the cron job to track the file location if (!isset($data['x-openregister'])) { @@ -1940,7 +1951,7 @@ public function importFromFilePath(string $appId, string $filePath, string $vers if (!isset($data['x-openregister']['sourceType'])) { $data['x-openregister']['sourceType'] = 'local'; } - + // Call importFromApp with the parsed data return $this->importFromApp( appId: $appId, @@ -1998,7 +2009,7 @@ public function importFromApp(string $appId, array $data, string $version, bool $configuration = null; $xOpenregister = $data['x-openregister'] ?? []; $sourceUrl = $xOpenregister['sourceUrl'] ?? null; - + // If sourceUrl is provided, try to find by sourceUrl first (ensures uniqueness) if ($sourceUrl !== null) { try { @@ -2014,7 +2025,7 @@ public function importFromApp(string $appId, array $data, string $version, bool // No configuration found by sourceUrl } } - + // If not found by sourceUrl, try by appId if ($configuration === null) { try { @@ -2036,36 +2047,36 @@ public function importFromApp(string $appId, array $data, string $version, bool // Create new configuration if none exists if ($configuration === null) { $configuration = new Configuration(); - + // Extract metadata following OAS standard first, then x-openregister extension $info = $data['info'] ?? []; $xOpenregister = $data['x-openregister'] ?? []; - + // Standard OAS properties from info section $title = $info['title'] ?? $xOpenregister['title'] ?? $data['title'] ?? "Configuration for {$appId}"; $description = $info['description'] ?? $xOpenregister['description'] ?? $data['description'] ?? "Configuration imported by application {$appId}"; - + // OpenRegister-specific properties $type = $xOpenregister['type'] ?? $data['type'] ?? 'app'; - + $configuration->setTitle($title); $configuration->setDescription($description); $configuration->setType($type); $configuration->setApp($appId); $configuration->setVersion($version); - + // Mark as local configuration (maintained by the app) $configuration->setIsLocal(true); $configuration->setSyncEnabled(false); $configuration->setSyncStatus('never'); - + // Set version requirements from x-openregister if available if (isset($xOpenregister['openregister']) === true) { $configuration->setOpenregister($xOpenregister['openregister']); } - + // Set additional metadata from x-openregister if available - // Note: Internal properties (autoUpdate, notificationGroups, owner, organisation) + // Note: Internal properties (autoUpdate, notificationGroups, owner, organisation) // are not imported as they are instance-specific settings if (isset($xOpenregister['sourceType']) === true) { $configuration->setSourceType($xOpenregister['sourceType']); @@ -2073,7 +2084,7 @@ public function importFromApp(string $appId, array $data, string $version, bool if (isset($xOpenregister['sourceUrl']) === true) { $configuration->setSourceUrl($xOpenregister['sourceUrl']); } - + // Support both nested github structure (new) and flat structure (backward compatibility) if (isset($xOpenregister['github']) === true && is_array($xOpenregister['github'])) { // New nested structure @@ -2098,14 +2109,14 @@ public function importFromApp(string $appId, array $data, string $version, bool $configuration->setGithubPath($xOpenregister['githubPath']); } } - + $configuration->setRegisters([]); $configuration->setSchemas([]); $configuration->setObjects([]); - + // Insert the configuration to get an ID $configuration = $this->configurationMapper->insert($configuration); - + $this->logger->info("Created new configuration for app {$appId}", [ 'configurationId' => $configuration->getId(), 'version' => $version @@ -2128,35 +2139,35 @@ public function importFromApp(string $appId, array $data, string $version, bool $existingRegisterIds = $configuration->getRegisters(); $existingSchemaIds = $configuration->getSchemas(); $existingObjectIds = $configuration->getObjects(); - + foreach ($result['registers'] as $register) { if ($register instanceof Register && !in_array($register->getId(), $existingRegisterIds, true)) { $existingRegisterIds[] = $register->getId(); } } - + foreach ($result['schemas'] as $schema) { if ($schema instanceof Schema && !in_array($schema->getId(), $existingSchemaIds, true)) { $existingSchemaIds[] = $schema->getId(); } } - + foreach ($result['objects'] as $object) { if ($object instanceof ObjectEntity && !in_array($object->getId(), $existingObjectIds, true)) { $existingObjectIds[] = $object->getId(); } } - + $configuration->setRegisters($existingRegisterIds); $configuration->setSchemas($existingSchemaIds); $configuration->setObjects($existingObjectIds); $configuration->setVersion($version); - + // Update metadata following OAS standard first, then x-openregister extension // This ensures sourceUrl and other tracking info stays current $info = $data['info'] ?? []; $xOpenregister = $data['x-openregister'] ?? []; - + // Standard OAS properties from info section if (isset($info['title']) === true) { $configuration->setTitle($info['title']); @@ -2168,7 +2179,7 @@ public function importFromApp(string $appId, array $data, string $version, bool } elseif (isset($xOpenregister['description']) === true) { $configuration->setDescription($xOpenregister['description']); } - + // OpenRegister-specific properties from x-openregister if (isset($xOpenregister['sourceType']) === true) { $configuration->setSourceType($xOpenregister['sourceType']); @@ -2176,7 +2187,7 @@ public function importFromApp(string $appId, array $data, string $version, bool if (isset($xOpenregister['sourceUrl']) === true) { $configuration->setSourceUrl($xOpenregister['sourceUrl']); } - + // Update github properties (nested or flat) if (isset($xOpenregister['github']) === true && is_array($xOpenregister['github'])) { if (isset($xOpenregister['github']['repo']) === true) { @@ -2200,9 +2211,9 @@ public function importFromApp(string $appId, array $data, string $version, bool $configuration->setGithubPath($xOpenregister['githubPath']); } } - + $this->configurationMapper->update($configuration); - + $this->logger->info("Updated configuration entity for app {$appId}", [ 'configurationId' => $configuration->getId(), 'totalRegisters' => count($existingRegisterIds), @@ -2420,7 +2431,7 @@ public function checkRemoteVersion(Configuration $configuration): ?string try { // Fetch the remote configuration $remoteData = $this->getJSONfromURL($sourceUrl); - + if ($remoteData instanceof JSONResponse) { $this->logger->error('Failed to fetch remote configuration', ['error' => $remoteData->getData()]); return null; @@ -2498,7 +2509,7 @@ public function compareVersions(Configuration $configuration): array // Compare versions $comparison = version_compare($remoteVersion, $localVersion); - + if ($comparison > 0) { $result['hasUpdate'] = true; $result['message'] = "Update available: {$localVersion} → {$remoteVersion}"; @@ -2544,10 +2555,10 @@ public function fetchRemoteConfiguration(Configuration $configuration): array | try { $this->logger->info("Fetching remote configuration from: {$sourceUrl}"); - + // Use existing method to fetch and parse the remote configuration $remoteData = $this->getJSONfromURL($sourceUrl); - + if ($remoteData instanceof JSONResponse) { return $remoteData; } @@ -2597,7 +2608,7 @@ public function previewConfigurationChanges(Configuration $configuration): array { // Fetch the remote configuration $remoteData = $this->fetchRemoteConfiguration($configuration); - + if ($remoteData instanceof JSONResponse) { return $remoteData; } @@ -2634,13 +2645,13 @@ public function previewConfigurationChanges(Configuration $configuration): array // Build register and schema slug to ID maps $registerSlugToId = []; $schemaSlugToId = []; - + // Get existing registers and schemas to build maps $allRegisters = $this->registerMapper->findAll(); foreach ($allRegisters as $register) { $registerSlugToId[strtolower($register->getSlug())] = $register->getId(); } - + $allSchemas = $this->schemaMapper->findAll(); foreach ($allSchemas as $schema) { $schemaSlugToId[strtolower($schema->getSlug())] = $schema->getId(); @@ -2692,7 +2703,7 @@ public function previewConfigurationChanges(Configuration $configuration): array private function previewRegisterChange(string $slug, array $registerData): array { $slug = strtolower($slug); - + // Try to find existing register $existingRegister = null; try { @@ -2715,11 +2726,11 @@ private function previewRegisterChange(string $slug, array $registerData): array if ($existingRegister !== null) { $currentData = $existingRegister->jsonSerialize(); $preview['current'] = $currentData; - + // Check if version allows update $currentVersion = $existingRegister->getVersion() ?? '0.0.0'; $proposedVersion = $registerData['version'] ?? '0.0.0'; - + if (version_compare($proposedVersion, $currentVersion, '<=') === true) { $preview['action'] = 'skip'; $preview['reason'] = "Remote version ({$proposedVersion}) is not newer than current version ({$currentVersion})"; @@ -2755,7 +2766,7 @@ private function previewRegisterChange(string $slug, array $registerData): array private function previewSchemaChange(string $slug, array $schemaData): array { $slug = strtolower($slug); - + // Try to find existing schema $existingSchema = null; try { @@ -2778,11 +2789,11 @@ private function previewSchemaChange(string $slug, array $schemaData): array if ($existingSchema !== null) { $currentData = $existingSchema->jsonSerialize(); $preview['current'] = $currentData; - + // Check if version allows update $currentVersion = $existingSchema->getVersion() ?? '0.0.0'; $proposedVersion = $schemaData['version'] ?? '0.0.0'; - + if (version_compare($proposedVersion, $currentVersion, '<=') === true) { $preview['action'] = 'skip'; $preview['reason'] = "Remote version ({$proposedVersion}) is not newer than current version ({$currentVersion})"; @@ -2823,7 +2834,7 @@ private function previewObjectChange(array $objectData, array $registerSlugToId, $slug = $objectData['@self']['slug'] ?? null; $registerSlug = $objectData['@self']['register'] ?? null; $schemaSlug = $objectData['@self']['schema'] ?? null; - + $preview = [ 'type' => 'object', 'action' => 'skip', @@ -2872,10 +2883,10 @@ private function previewObjectChange(array $objectData, array $registerSlugToId, // Object exists, check version $existingObjectData = is_array($existingObject) ? $existingObject : $existingObject->jsonSerialize(); $preview['current'] = $existingObjectData; - + $currentVersion = $existingObjectData['@self']['version'] ?? $existingObjectData['version'] ?? '1.0.0'; $proposedVersion = $objectData['@self']['version'] ?? $objectData['version'] ?? '1.0.0'; - + if (version_compare($proposedVersion, $currentVersion, '<=') === true) { $preview['action'] = 'skip'; $preview['reason'] = "Remote version ({$proposedVersion}) is not newer than current version ({$currentVersion})"; @@ -2905,16 +2916,16 @@ private function previewObjectChange(array $objectData, array $registerSlugToId, private function compareArrays(array $current, array $proposed, string $prefix = ''): array { $changes = []; - + // Check all keys in proposed data foreach ($proposed as $key => $proposedValue) { $fieldName = $prefix === '' ? $key : "{$prefix}.{$key}"; - + // Skip certain metadata fields if (in_array($key, ['id', 'uuid', 'created', 'updated']) === true) { continue; } - + // Check if field exists in current data if (array_key_exists($key, $current) === false) { $changes[] = [ @@ -2924,9 +2935,9 @@ private function compareArrays(array $current, array $proposed, string $prefix = ]; continue; } - + $currentValue = $current[$key]; - + // Deep comparison for arrays if (is_array($proposedValue) && is_array($currentValue)) { // For simple arrays, just compare values @@ -2952,7 +2963,7 @@ private function compareArrays(array $current, array $proposed, string $prefix = ]; } } - + return $changes; }//end compareArrays() @@ -2972,7 +2983,7 @@ private function isSimpleArray(array $array): bool return false; } } - + return true; }//end isSimpleArray() @@ -3008,10 +3019,10 @@ private function isSimpleArray(array $array): bool public function importConfigurationWithSelection(Configuration $configuration, array $selection): array { $this->logger->info("Starting selective import for configuration {$configuration->getId()}", ['selection' => $selection]); - + // Fetch the remote configuration $remoteData = $this->fetchRemoteConfiguration($configuration); - + if ($remoteData instanceof JSONResponse) { throw new Exception('Failed to fetch remote configuration: ' . json_encode($remoteData->getData())); } @@ -3062,10 +3073,10 @@ public function importConfigurationWithSelection(Configuration $configuration, a $objectSlug = $objectData['@self']['slug'] ?? null; $registerSlug = $objectData['@self']['register'] ?? null; $schemaSlug = $objectData['@self']['schema'] ?? null; - + // Build unique identifier for object $objectId = "{$registerSlug}:{$schemaSlug}:{$objectSlug}"; - + if (in_array($objectId, $selection['objects'], true) === true) { $filteredData['components']['objects'][] = $objectData; } diff --git a/lib/Service/ObjectHandlers/SaveObject.php b/lib/Service/ObjectHandlers/SaveObject.php index 5bf43f996..042254ccc 100644 --- a/lib/Service/ObjectHandlers/SaveObject.php +++ b/lib/Service/ObjectHandlers/SaveObject.php @@ -1152,6 +1152,14 @@ function (array $property) { $data[$property] = $createdUuid; } } catch (Exception $e) { + $this->logger->error( + 'Cascade single object failed', + [ + 'property' => $property, + 'schema' => $definition['$ref'] ?? null, + 'error' => $e->getMessage(), + ] + ); // Continue with other properties even if one fails } }//end foreach @@ -1184,6 +1192,14 @@ function (array $property) { $data[$property] = $createdUuids; } } catch (Exception $e) { + $this->logger->error( + 'Cascade array objects failed', + [ + 'property' => $property, + 'schema' => $definition['$ref'] ?? ($definition['items']['$ref'] ?? null), + 'error' => $e->getMessage(), + ] + ); // Continue with other properties even if one fails }//end try }//end foreach @@ -1255,6 +1271,13 @@ function ($object) { $createdUuids[] = $uuid; } } catch (Exception $e) { + $this->logger->error( + 'Cascade array item failed', + [ + 'schema' => $property['items']['$ref'] ?? null, + 'error' => $e->getMessage(), + ] + ); // Continue with other objects even if one fails } } diff --git a/lib/Service/ObjectService.php b/lib/Service/ObjectService.php index 2ae5ca11c..a6b5d7418 100644 --- a/lib/Service/ObjectService.php +++ b/lib/Service/ObjectService.php @@ -456,8 +456,9 @@ public function setSchema(Schema | string | int $schema): self // When deriving schema from object context, bypass RBAC and multi-tenancy checks. // If user has access to the object, they should be able to access its schema. $schemas = $this->getCachedEntities('schema', [$schema], function($ids) { - return [$this->schemaMapper->find(id: $ids[0], extend: [], published: null, rbac: false, multi: false)]; + return [$this->schemaMapper->find(id: $ids[0], rbac: false, multi: false)]; }); + if (isset($schemas[0]) && $schemas[0] instanceof Schema) { $schema = $schemas[0]; } else { @@ -925,6 +926,7 @@ public function findAll(array $config=[], bool $rbac=true, bool $multi=true): ar && is_array($config['filters']['schema']) === false && !empty($config['filters']['schema'])) { $this->setSchema($config['filters']['schema']); + $config['filters']['schema'] = $this->getSchema(); } // Delegate the findAll operation to the handler. @@ -1416,6 +1418,17 @@ function ($filter) { $filtersWithSub = array_intersect_key($filters, array_flip($filterKeysWithSub)); + + $filtersWithSub = array_map(function($value) { + if($value === 'false') { + return false; + } else if ($value === 'true') { + return true; + } + + return $value; + }, $filtersWithSub); + if (empty($filtersWithSub)) { return []; } @@ -1426,9 +1439,10 @@ function ($filter) { $iterator = 0; foreach ($filterDot as $key => $value) { - if (isset($schema->getProperties()[$key]['inversedBy']) === false) { - continue; - } + +// if (isset($schema->getProperties()[$key]['inversedBy']) === false) { +// continue; +// } $iterator++; $property = $schema->getProperties()[$key]; @@ -1437,11 +1451,16 @@ function ($filter) { // @TODO fix schema finder $value['schema'] = $property['$ref']; + $remoteSchema = $this->schemaMapper->find($value['schema']); $objects = $this->findAll(config: ['filters' => $value]); - $foundIds = array_map( - function (ObjectEntity $object) use ($property, $key) { - $idRaw = $object->jsonSerialize()[$property['inversedBy']]; + + if (isset($property['inversedBy']) === true) { + $foundIds = array_map( + function (ObjectEntity $object) use ($property, $key, $remoteSchema, $schema) { + if (isset($property['inversedBy']) === true) { + $idRaw = $object->jsonSerialize()[$property['inversedBy']]; + } if (Uuid::isValid($idRaw) === true) { return $idRaw; @@ -1452,7 +1471,40 @@ function (ObjectEntity $object) use ($property, $key) { } }, $objects + ); + } else { + $filteredProperties = array_keys(array_filter($remoteSchema->getProperties(), function ($v, $k) use ($property, $schema) { + return (isset($v['inversedBy']) === true + && ( + $v['inversedBy'] === $property['title'] + || $v['inversedBy'] === $k + ) + && ( + $v['$ref'] === $schema->getId() + || $v['$ref'] === $schema->getSlug() + ) ); + }, ARRAY_FILTER_USE_BOTH)); + + foreach($filteredProperties as $property) { + $foundIds[] = array_map(function(ObjectEntity $object) use ($property) { + return $object->jsonSerialize()[$property]; + }, $objects); + } + + $rawIds = []; + array_walk_recursive($foundIds, function($value) use (&$rawIds) { $rawIds[] = $value; }); + + $foundIds = array_map(function(string $rawId) { + if (Uuid::isValid($rawId) === true) { + return $rawId; + } else if (filter_var($rawId, FILTER_VALIDATE_URL) !== false) { + $path = explode(separator: '/', string: parse_url($rawId, PHP_URL_PATH)); + + return end($path); + } + }, $rawIds); + } if ($ids === []) { $ids = $foundIds; @@ -1882,7 +1934,7 @@ public function buildSearchQuery(array $requestParams, int | string | array | nu if (isset($specialParams['_published'])) { $specialParams['_published'] = filter_var($specialParams['_published'], FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE) ?? false; } - + $query = array_merge($query, $specialParams); return $query; @@ -2001,6 +2053,46 @@ private function applyViewsToQuery(array $query, array $viewIds): array }//end applyViewsToQuery() + /** + * In the @self fields for schema and register, rewrite slugs to ids if needed. + * + * + * @param array $query The original query + * @return array The updated query + * @throws Exception + */ + private function rewriteSlugs(array $query): array + { + if (isset($query['@self']['register']) === true && is_array($query['@self']['register']) === true) { + $query['@self']['register'] = array_map( + function($register) { + if (is_int($register) === true) { + return $register; + } + return $this->registerMapper->find($register)->getId(); + }, + $query['@self']['register'] + ); + } else if (isset($query['@self']['register']) === true) { + $query['@self']['register'] = is_int($query['@self']['register']) ? $query['@self']['register'] : $this->registerMapper->find($query['@self']['register'])->getId(); + } + + if (isset($query['@self']['schema']) === true && is_array($query['@self']['schema']) === true) { + $query['@self']['schema'] = array_map( + function($schema) { + if (is_int($schema) === true) { + return $schema; + } + return $this->schemaMapper->find($schema)->getId(); + }, + $query['@self']['schema'] + ); + } else if (isset($query['@self']['schema']) === true) { + $query['@self']['schema'] = is_int($query['@self']['schema']) ? $query['@self']['schema'] : $this->registerMapper->find($query['@self']['schema'])->getId(); + } + + return $query; + } public function searchObjects(array $query=[], bool $rbac=true, bool $multi=true, ?array $ids=null, ?string $uses=null, ?array $views=null): array|int { @@ -2009,6 +2101,8 @@ public function searchObjects(array $query=[], bool $rbac=true, bool $multi=true $query = $this->applyViewsToQuery($query, $views); } + $query = $this->rewriteSlugs($query); + // **CRITICAL PERFORMANCE OPTIMIZATION**: Detect simple vs complex rendering needs $hasExtend = !empty($query['_extend'] ?? []); $hasFields = !empty($query['_fields'] ?? null); diff --git a/lib/Service/OrganisationService.php b/lib/Service/OrganisationService.php index 4788eed85..5562b05ab 100644 --- a/lib/Service/OrganisationService.php +++ b/lib/Service/OrganisationService.php @@ -1189,6 +1189,43 @@ public function getDefaultOrganisation(): ?Organisation }//end getDefaultOrganisation() + /** + * Get the default organisation UUID from config + * + * @return string|null The UUID of the default user tenant, or null if not set + */ + private function getDefaultUserTenantId(): ?string + { + $multitenancyConfig = $this->appConfig->getValueString(app: 'openregister', key: 'multitenancy'); + $multitenancyConfig = json_decode(json: $multitenancyConfig, associative: true); + + $defaultUserTenantId = isset($multitenancyConfig['defaultUserTenant']['id']) === true ? $multitenancyConfig['defaultUserTenant']['id'] : null; + return $defaultUserTenantId !== null ? $defaultUserTenantId : null; + } + + /** + * Get the default organisation object + * + * @return Organisation|null The default user tenant, or null if not set + */ + public function getDefaultUserTenant(): ?Organisation + { + $defaultUserTenantId = $this->getDefaultUserTenantId(); + if ($defaultUserTenantId === null) { + return null; + } + + try { + return $this->organisationMapper->findByUuid($defaultUserTenantId); + } catch (\Exception $e) { + $this->logger->warning('Default organisation not found', [ + 'uuid' => $defaultUserTenantId, + 'error' => $e->getMessage() + ]); + return null; + } + } + /** * Get UUIDs of active organisation and all its parent organisations diff --git a/lib/Service/SettingsService.php b/lib/Service/SettingsService.php index 7685f54ad..e84bc8773 100644 --- a/lib/Service/SettingsService.php +++ b/lib/Service/SettingsService.php @@ -359,7 +359,7 @@ public function getSettings(): array // SOLR Search Configuration $solrConfig = $this->config->getValueString($this->appName, 'solr', ''); - + if (empty($solrConfig)) { $data['solr'] = [ 'enabled' => false, @@ -790,10 +790,10 @@ public function getStats(): array $db = $this->container->get('OCP\IDBConnection'); // **OPTIMIZED QUERIES**: Use direct SQL COUNT queries for maximum performance - + // 1. Objects table - comprehensive stats with single query $objectsQuery = " - SELECT + SELECT COUNT(*) as total_objects, COALESCE(SUM(CAST(size AS UNSIGNED)), 0) as total_size, SUM(CASE WHEN owner IS NULL OR owner = '' THEN 1 ELSE 0 END) as without_owner, @@ -804,11 +804,11 @@ public function getStats(): array SUM(CASE WHEN expires IS NOT NULL AND expires < NOW() THEN COALESCE(CAST(size AS UNSIGNED), 0) ELSE 0 END) as expired_size FROM `*PREFIX*openregister_objects` "; - + $result = $db->executeQuery($objectsQuery); $objectsData = $result->fetch(); $result->closeCursor(); - + $stats['totals']['totalObjects'] = (int) ($objectsData['total_objects'] ?? 0); $stats['sizes']['totalObjectsSize'] = (int) ($objectsData['total_size'] ?? 0); $stats['warnings']['objectsWithoutOwner'] = (int) ($objectsData['without_owner'] ?? 0); @@ -820,7 +820,7 @@ public function getStats(): array // 2. Audit trails table - comprehensive stats $auditQuery = " - SELECT + SELECT COUNT(*) as total_count, COALESCE(SUM(size), 0) as total_size, SUM(CASE WHEN expires IS NULL OR expires = '' THEN 1 ELSE 0 END) as without_expiry, @@ -828,11 +828,11 @@ public function getStats(): array SUM(CASE WHEN expires IS NOT NULL AND expires < NOW() THEN COALESCE(size, 0) ELSE 0 END) as expired_size FROM `*PREFIX*openregister_audit_trails` "; - + $result = $db->executeQuery($auditQuery); $auditData = $result->fetch(); $result->closeCursor(); - + $stats['totals']['totalAuditTrails'] = (int) ($auditData['total_count'] ?? 0); $stats['sizes']['totalAuditTrailsSize'] = (int) ($auditData['total_size'] ?? 0); $stats['warnings']['auditTrailsWithoutExpiry'] = (int) ($auditData['without_expiry'] ?? 0); @@ -841,7 +841,7 @@ public function getStats(): array // 3. Search trails table - comprehensive stats $searchQuery = " - SELECT + SELECT COUNT(*) as total_count, COALESCE(SUM(size), 0) as total_size, SUM(CASE WHEN expires IS NULL OR expires = '' THEN 1 ELSE 0 END) as without_expiry, @@ -849,11 +849,11 @@ public function getStats(): array SUM(CASE WHEN expires IS NOT NULL AND expires < NOW() THEN COALESCE(size, 0) ELSE 0 END) as expired_size FROM `*PREFIX*openregister_search_trails` "; - + $result = $db->executeQuery($searchQuery); $searchData = $result->fetch(); $result->closeCursor(); - + $stats['totals']['totalSearchTrails'] = (int) ($searchData['total_count'] ?? 0); $stats['sizes']['totalSearchTrailsSize'] = (int) ($searchData['total_size'] ?? 0); $stats['warnings']['searchTrailsWithoutExpiry'] = (int) ($searchData['without_expiry'] ?? 0); @@ -876,7 +876,7 @@ public function getStats(): array $result = $db->executeQuery($countQuery); $count = $result->fetchColumn(); $result->closeCursor(); - + $stats['totals']['total' . ucfirst($key)] = (int) ($count ?? 0); } catch (Exception $e) { // Table might not exist, set to 0 and continue @@ -906,11 +906,11 @@ public function getCacheStats(): array // Get basic distributed cache info $distributedStats = $this->getDistributedCacheStats(); $performanceStats = $this->getCachePerformanceMetrics(); - + // Get object cache stats (only if ObjectCacheService provides them) // Use cached stats to avoid expensive operations on every request $objectStats = $this->getCachedObjectStats(); - + $stats = [ 'overview' => [ 'totalCacheSize' => $objectStats['memoryUsage'] ?? 0, @@ -979,7 +979,7 @@ public function getCacheStats(): array ]; } } - + /** * Get cached object statistics to avoid expensive operations on every request * @@ -990,7 +990,7 @@ private function getCachedObjectStats(): array // Use a simple in-memory cache with 30-second TTL to avoid expensive ObjectCacheService calls static $cachedStats = null; static $lastUpdate = 0; - + $now = time(); if ($cachedStats === null || ($now - $lastUpdate) > 30) { try { @@ -1012,7 +1012,7 @@ private function getCachedObjectStats(): array } $lastUpdate = $now; } - + return $cachedStats; } @@ -1026,7 +1026,7 @@ private function calculateHitRate(array $stats): float { $requests = $stats['requests'] ?? 0; $hits = $stats['hits'] ?? 0; - + return $requests > 0 ? ($hits / $requests) * 100 : 0.0; } @@ -1039,7 +1039,7 @@ private function getDistributedCacheStats(): array { try { $distributedCache = $this->cacheFactory->createDistributed('openregister'); - + return [ 'type' => 'distributed', 'backend' => get_class($distributedCache), @@ -1184,9 +1184,9 @@ private function clearNamesCache(): array $objectCacheService = $this->container->get(ObjectCacheService::class); $beforeStats = $objectCacheService->getStats(); $beforeNameCacheSize = $beforeStats['name_cache_size'] ?? 0; - + $objectCacheService->clearNameCache(); - + $afterStats = $objectCacheService->getStats(); $afterNameCacheSize = $afterStats['name_cache_size'] ?? 0; @@ -1226,9 +1226,9 @@ public function warmupNamesCache(): array $startTime = microtime(true); $objectCacheService = $this->container->get(ObjectCacheService::class); $beforeStats = $objectCacheService->getStats(); - + $loadedCount = $objectCacheService->warmupNameCache(); - + $executionTime = round((microtime(true) - $startTime) * 1000, 2); $afterStats = $objectCacheService->getStats(); @@ -1396,7 +1396,7 @@ public function testSolrConnection(): array // Delegate to GuzzleSolrService for consistent configuration and URL handling $guzzleSolrService = $this->container->get(GuzzleSolrService::class); return $guzzleSolrService->testConnection(); - + } catch (Exception $e) { return [ 'success' => false, @@ -1423,14 +1423,14 @@ private function testZookeeperConnection(array $solrSettings): array try { $zookeeperHosts = $solrSettings['zookeeperHosts'] ?? 'zookeeper:2181'; $hosts = explode(',', $zookeeperHosts); - + $successfulHosts = []; $failedHosts = []; - + foreach ($hosts as $host) { $host = trim($host); if (empty($host)) continue; - + // Test Zookeeper connection using SOLR's Zookeeper API $url = sprintf( '%s://%s:%d%s/admin/collections?action=CLUSTERSTATUS&wt=json', @@ -1439,16 +1439,16 @@ private function testZookeeperConnection(array $solrSettings): array $solrSettings['port'], $solrSettings['path'] ); - + $context = stream_context_create([ 'http' => [ 'timeout' => 5, 'method' => 'GET' ] ]); - + $response = @file_get_contents($url, false, $context); - + if ($response !== false) { $data = json_decode($response, true); if (isset($data['cluster'])) { @@ -1460,11 +1460,11 @@ private function testZookeeperConnection(array $solrSettings): array $failedHosts[] = $host; } } - + return [ 'success' => !empty($successfulHosts), - 'message' => !empty($successfulHosts) ? - 'Zookeeper accessible via ' . implode(', ', $successfulHosts) : + 'message' => !empty($successfulHosts) ? + 'Zookeeper accessible via ' . implode(', ', $successfulHosts) : 'Zookeeper not accessible via any host', 'details' => [ 'zookeeper_hosts' => $zookeeperHosts, @@ -1473,7 +1473,7 @@ private function testZookeeperConnection(array $solrSettings): array 'test_method' => 'SOLR Collections API' ] ]; - + } catch (Exception $e) { return [ 'success' => false, @@ -1497,7 +1497,7 @@ private function testSolrConnectivity(array $solrSettings): array try { // Build SOLR URL - handle Kubernetes service names properly $host = $solrSettings['host']; - + // Check if it's a Kubernetes service name (contains .svc.cluster.local) if (strpos($host, '.svc.cluster.local') !== false) { // Kubernetes service - don't append port, it's handled by the service @@ -1526,11 +1526,11 @@ private function testSolrConnectivity(array $solrSettings): array '/solr/admin/ping?wt=json', '/admin/info/system?wt=json' ]; - + $testUrl = null; $testType = 'admin_ping'; $lastError = null; - + // Create HTTP context with timeout $context = stream_context_create([ 'http' => [ @@ -1542,17 +1542,17 @@ private function testSolrConnectivity(array $solrSettings): array ] ] ]); - + // Try each endpoint until one works $response = false; $responseTime = 0; - + foreach ($testEndpoints as $endpoint) { $testUrl = $baseUrl . $endpoint; $startTime = microtime(true); $response = @file_get_contents($testUrl, false, $context); $responseTime = (microtime(true) - $startTime) * 1000; - + if ($response !== false) { // Found a working endpoint break; @@ -1560,7 +1560,7 @@ private function testSolrConnectivity(array $solrSettings): array $lastError = "Failed to connect to: " . $testUrl; } } - + if ($response === false) { return [ 'success' => false, @@ -1575,14 +1575,14 @@ private function testSolrConnectivity(array $solrSettings): array ] ]; } - + $data = json_decode($response, true); - + // Validate admin response - be flexible about response format if ($testType === 'admin_ping') { // Check for successful response - different endpoints have different formats $isValidResponse = false; - + if (isset($data['status']) && $data['status'] === 'OK') { // Standard ping response $isValidResponse = true; @@ -1593,7 +1593,7 @@ private function testSolrConnectivity(array $solrSettings): array // Any valid JSON response indicates SOLR is responding $isValidResponse = true; } - + if (!$isValidResponse) { return [ 'success' => false, @@ -1606,7 +1606,7 @@ private function testSolrConnectivity(array $solrSettings): array ] ]; } - + return [ 'success' => true, 'message' => 'SOLR server responding correctly', @@ -1634,7 +1634,7 @@ private function testSolrConnectivity(array $solrSettings): array ] ]; } - + return [ 'success' => true, 'message' => 'SOLR standalone server responding correctly', @@ -1646,7 +1646,7 @@ private function testSolrConnectivity(array $solrSettings): array ] ]; } - + } catch (Exception $e) { return [ 'success' => false, @@ -1670,10 +1670,10 @@ private function testSolrCollection(array $solrSettings): array { try { $collectionName = $solrSettings['collection'] ?? $solrSettings['core'] ?? 'openregister'; - + // Build SOLR URL - handle Kubernetes service names properly $host = $solrSettings['host']; - + // Check if it's a Kubernetes service name (contains .svc.cluster.local) if (strpos($host, '.svc.cluster.local') !== false) { // Kubernetes service - don't append port, it's handled by the service @@ -1694,20 +1694,20 @@ private function testSolrCollection(array $solrSettings): array $solrSettings['path'] ); } - + // For SolrCloud, test collection existence if ($solrSettings['useCloud'] ?? false) { $url = $baseUrl . '/admin/collections?action=CLUSTERSTATUS&wt=json'; - + $context = stream_context_create([ 'http' => [ 'timeout' => 10, 'method' => 'GET' ] ]); - + $response = @file_get_contents($url, false, $context); - + if ($response === false) { return [ 'success' => false, @@ -1715,10 +1715,10 @@ private function testSolrCollection(array $solrSettings): array 'details' => ['url' => $url] ]; } - + $data = json_decode($response, true); $collections = $data['cluster']['collections'] ?? []; - + if (isset($collections[$collectionName])) { return [ 'success' => true, @@ -1742,16 +1742,16 @@ private function testSolrCollection(array $solrSettings): array } else { // For standalone SOLR, test core existence $url = $baseUrl . '/admin/cores?action=STATUS&core=' . urlencode($collectionName) . '&wt=json'; - + $context = stream_context_create([ 'http' => [ 'timeout' => 10, 'method' => 'GET' ] ]); - + $response = @file_get_contents($url, false, $context); - + if ($response === false) { return [ 'success' => false, @@ -1759,9 +1759,9 @@ private function testSolrCollection(array $solrSettings): array 'details' => ['url' => $url] ]; } - + $data = json_decode($response, true); - + if (isset($data['status'][$collectionName])) { return [ 'success' => true, @@ -1782,7 +1782,7 @@ private function testSolrCollection(array $solrSettings): array ]; } } - + } catch (Exception $e) { return [ 'success' => false, @@ -1805,10 +1805,10 @@ private function testSolrQuery(array $solrSettings): array { try { $collectionName = $solrSettings['collection'] ?? $solrSettings['core'] ?? 'openregister'; - + // Build SOLR URL - handle Kubernetes service names properly $host = $solrSettings['host']; - + // Check if it's a Kubernetes service name (contains .svc.cluster.local) if (strpos($host, '.svc.cluster.local') !== false) { // Kubernetes service - don't append port, it's handled by the service @@ -1829,21 +1829,21 @@ private function testSolrQuery(array $solrSettings): array $solrSettings['path'] ); } - + // Test collection select query $testUrl = $baseUrl . '/' . $collectionName . '/select?q=*:*&rows=0&wt=json'; - + $context = stream_context_create([ 'http' => [ 'timeout' => 10, 'method' => 'GET' ] ]); - + $startTime = microtime(true); $response = @file_get_contents($testUrl, false, $context); $responseTime = (microtime(true) - $startTime) * 1000; - + if ($response === false) { return [ 'success' => false, @@ -1855,9 +1855,9 @@ private function testSolrQuery(array $solrSettings): array ] ]; } - + $data = json_decode($response, true); - + // Check for successful query response if (!isset($data['responseHeader']['status']) || $data['responseHeader']['status'] !== 0) { return [ @@ -1871,7 +1871,7 @@ private function testSolrQuery(array $solrSettings): array ] ]; } - + return [ 'success' => true, 'message' => 'Collection query successful', @@ -1883,7 +1883,7 @@ private function testSolrQuery(array $solrSettings): array 'query_time' => $data['responseHeader']['QTime'] ?? 0 ] ]; - + } catch (Exception $e) { return [ 'success' => false, @@ -1915,7 +1915,7 @@ public function warmupSolrIndex(int $batchSize = 2000, int $maxObjects = 0, stri { try { $solrSettings = $this->getSolrSettings(); - + if (!$solrSettings['enabled']) { return [ 'success' => false, @@ -1931,7 +1931,7 @@ public function warmupSolrIndex(int $batchSize = 2000, int $maxObjects = 0, stri // Get SolrService for bulk indexing via direct DI $solrService = $this->container->get(GuzzleSolrService::class); - + if ($solrService === null) { return [ 'success' => false, @@ -1944,9 +1944,9 @@ public function warmupSolrIndex(int $batchSize = 2000, int $maxObjects = 0, stri ] ]; } - + $startTime = microtime(true); - + // Get all schemas for schema mirroring $schemas = []; try { @@ -1956,19 +1956,19 @@ public function warmupSolrIndex(int $batchSize = 2000, int $maxObjects = 0, stri // Continue without schema mirroring if schema mapper is not available $this->logger->warning('Schema mapper not available for warmup', ['error' => $e->getMessage()]); } - + // **COMPLETE WARMUP**: Mirror schemas + index objects + cache warmup $warmupResult = $solrService->warmupIndex($schemas, $maxObjects, $mode, $collectErrors); - + $totalDuration = microtime(true) - $startTime; - + if ($warmupResult['success']) { $operations = $warmupResult['operations'] ?? []; $indexed = $operations['objects_indexed'] ?? 0; $schemasProcessed = $operations['schemas_processed'] ?? 0; $fieldsCreated = $operations['fields_created'] ?? 0; $objectsPerSecond = $totalDuration > 0 ? round($indexed / $totalDuration, 2) : 0; - + return [ 'success' => true, 'message' => 'SOLR complete warmup finished successfully', @@ -2008,7 +2008,7 @@ public function warmupSolrIndex(int $batchSize = 2000, int $maxObjects = 0, stri 'file' => $e->getFile(), 'line' => $e->getLine() ]); - + // **ERROR COLLECTION MODE**: Return errors in response if collectErrors is true if ($collectErrors) { return [ @@ -2033,7 +2033,7 @@ public function warmupSolrIndex(int $batchSize = 2000, int $maxObjects = 0, stri ] ]; } - + // **ERROR VISIBILITY**: Re-throw exception to expose errors in controller (default behavior) throw new \RuntimeException( 'SOLR warmup failed: ' . $e->getMessage(), @@ -2058,7 +2058,7 @@ public function getSolrDashboardStats(): array try { $objectCacheService = $this->container->get(ObjectCacheService::class); $rawStats = $objectCacheService->getSolrDashboardStats(); - + // Transform the raw stats into the expected dashboard structure return $this->transformSolrStatsToDashboard($rawStats); } catch (Exception $e) { @@ -2247,7 +2247,7 @@ public function manageSolr(string $operation): array { try { $objectCacheService = $this->container->get(ObjectCacheService::class); - + switch ($operation) { case 'commit': $result = $objectCacheService->commitSolr(); @@ -2258,7 +2258,7 @@ public function manageSolr(string $operation): array 'details' => $result, 'timestamp' => date('c') ]; - + case 'optimize': $result = $objectCacheService->optimizeSolr(); return [ @@ -2268,7 +2268,7 @@ public function manageSolr(string $operation): array 'details' => $result, 'timestamp' => date('c') ]; - + case 'clear': $result = $objectCacheService->clearSolrIndexForDashboard(); return [ @@ -2278,10 +2278,10 @@ public function manageSolr(string $operation): array 'details' => $result, 'timestamp' => date('c') ]; - + case 'warmup': return $this->warmupSolrIndex(); - + default: return [ 'success' => false, @@ -2290,7 +2290,7 @@ public function manageSolr(string $operation): array 'timestamp' => date('c') ]; } - + } catch (Exception $e) { return [ 'success' => false, @@ -2304,7 +2304,7 @@ public function manageSolr(string $operation): array /** * Test SOLR connection and get comprehensive status information - * + * * @deprecated Use GuzzleSolrService::testConnectionForDashboard() directly * @return array Connection test results with detailed status information */ @@ -2325,7 +2325,7 @@ public function getSolrSettingsOnly(): array { try { $solrConfig = $this->config->getValueString($this->appName, 'solr', ''); - + if (empty($solrConfig)) { return [ 'enabled' => false, @@ -2412,7 +2412,7 @@ public function updateSolrSettingsOnly(array $solrData): array 'objectCollection' => $solrData['objectCollection'] ?? null, 'fileCollection' => $solrData['fileCollection'] ?? null, ]; - + $this->config->setValueString($this->appName, 'solr', json_encode($solrConfig)); return $solrConfig; } catch (Exception $e) { @@ -2491,7 +2491,7 @@ public function updateSolrFacetConfiguration(array $facetConfig): array try { // Validate the configuration structure $validatedConfig = $this->validateFacetConfiguration($facetConfig); - + $this->config->setValueString($this->appName, 'solr_facet_config', json_encode($validatedConfig)); return $validatedConfig; } catch (Exception $e) { @@ -2572,7 +2572,7 @@ public function getRbacSettingsOnly(): array { try { $rbacConfig = $this->config->getValueString($this->appName, 'rbac', ''); - + $rbacData = []; if (empty($rbacConfig)) { $rbacData = [ @@ -2592,7 +2592,7 @@ public function getRbacSettingsOnly(): array 'adminOverride' => $storedData['adminOverride'] ?? true, ]; } - + return [ 'rbac' => $rbacData, 'availableGroups' => $this->getAvailableGroups(), @@ -2620,9 +2620,9 @@ public function updateRbacSettingsOnly(array $rbacData): array 'defaultObjectOwner' => $rbacData['defaultObjectOwner'] ?? '', 'adminOverride' => $rbacData['adminOverride'] ?? true, ]; - + $this->config->setValueString($this->appName, 'rbac', json_encode($rbacConfig)); - + return [ 'rbac' => $rbacConfig, 'availableGroups' => $this->getAvailableGroups(), @@ -2643,7 +2643,7 @@ public function getOrganisationSettingsOnly(): array { try { $organisationConfig = $this->config->getValueString($this->appName, 'organisation', ''); - + $organisationData = []; if (empty($organisationConfig)) { $organisationData = [ @@ -2657,7 +2657,7 @@ public function getOrganisationSettingsOnly(): array 'auto_create_default_organisation' => $storedData['auto_create_default_organisation'] ?? true, ]; } - + return [ 'organisation' => $organisationData, ]; @@ -2680,9 +2680,9 @@ public function updateOrganisationSettingsOnly(array $organisationData): array 'default_organisation' => $organisationData['default_organisation'] ?? null, 'auto_create_default_organisation' => $organisationData['auto_create_default_organisation'] ?? true, ]; - + $this->config->setValueString($this->appName, 'organisation', json_encode($organisationConfig)); - + return [ 'organisation' => $organisationConfig, ]; @@ -2749,11 +2749,11 @@ public function getMultitenancySettingsOnly(): array { try { $multitenancyConfig = $this->config->getValueString($this->appName, 'multitenancy', ''); - + $multitenancyData = []; if (empty($multitenancyConfig)) { $multitenancyData = [ - 'enabled' => false, + 'enabled' => true, 'defaultUserTenant' => '', 'defaultObjectTenant' => '', 'publishedObjectsBypassMultiTenancy' => false, @@ -2769,7 +2769,7 @@ public function getMultitenancySettingsOnly(): array 'adminOverride' => $storedData['adminOverride'] ?? true, ]; } - + return [ 'multitenancy' => $multitenancyData, 'availableTenants' => $this->getAvailableOrganisations(), @@ -2789,7 +2789,7 @@ public function getMultitenancySettingsOnly(): array public function updateMultitenancySettingsOnly(array $multitenancyData): array { try { - + $multitenancyConfig = [ 'enabled' => $multitenancyData['enabled'] ?? false, 'defaultUserTenant' => $multitenancyData['defaultUserTenant'] ?? '', @@ -2797,9 +2797,9 @@ public function updateMultitenancySettingsOnly(array $multitenancyData): array 'publishedObjectsBypassMultiTenancy' => $multitenancyData['publishedObjectsBypassMultiTenancy'] ?? false, 'adminOverride' => $multitenancyData['adminOverride'] ?? true, ]; - + $this->config->setValueString($this->appName, 'multitenancy', json_encode($multitenancyConfig)); - + return [ 'multitenancy' => $multitenancyConfig, 'availableTenants' => $this->getAvailableOrganisations(), @@ -2819,7 +2819,7 @@ public function getLLMSettingsOnly(): array { try { $llmConfig = $this->config->getValueString($this->appName, 'llm', ''); - + if (empty($llmConfig) === true) { // Return default configuration return [ @@ -2849,14 +2849,14 @@ public function getLLMSettingsOnly(): array ], ]; } - + $decoded = json_decode($llmConfig, true); - + // Ensure enabled field exists (for backward compatibility) if (isset($decoded['enabled']) === false) { $decoded['enabled'] = false; } - + // Ensure vector config exists (for backward compatibility) if (isset($decoded['vectorConfig']) === false) { $decoded['vectorConfig'] = [ @@ -2874,7 +2874,7 @@ public function getLLMSettingsOnly(): array // Remove deprecated solrCollection if it exists unset($decoded['vectorConfig']['solrCollection']); } - + return $decoded; } catch (Exception $e) { throw new \RuntimeException('Failed to retrieve LLM settings: '.$e->getMessage()); @@ -2893,7 +2893,7 @@ public function updateLLMSettingsOnly(array $llmData): array try { // Get existing config for PATCH support $existingConfig = $this->getLLMSettingsOnly(); - + // Merge with existing config (PATCH behavior) $llmConfig = [ 'enabled' => $llmData['enabled'] ?? $existingConfig['enabled'] ?? false, @@ -2921,7 +2921,7 @@ public function updateLLMSettingsOnly(array $llmData): array 'solrField' => $llmData['vectorConfig']['solrField'] ?? $existingConfig['vectorConfig']['solrField'] ?? '_embedding_', ], ]; - + $this->config->setValueString($this->appName, 'llm', json_encode($llmConfig)); return $llmConfig; } catch (Exception $e) { @@ -2939,7 +2939,7 @@ public function getFileSettingsOnly(): array { try { $fileConfig = $this->config->getValueString($this->appName, 'fileManagement', ''); - + if (empty($fileConfig) === true) { // Return default configuration return [ @@ -2962,7 +2962,7 @@ public function getFileSettingsOnly(): array 'dolphinApiKey' => '', ]; } - + return json_decode($fileConfig, true); } catch (Exception $e) { throw new \RuntimeException('Failed to retrieve File Management settings: '.$e->getMessage()); @@ -2997,7 +2997,7 @@ public function updateFileSettingsOnly(array $fileData): array 'dolphinApiEndpoint' => $fileData['dolphinApiEndpoint'] ?? '', 'dolphinApiKey' => $fileData['dolphinApiKey'] ?? '', ]; - + $this->config->setValueString($this->appName, 'fileManagement', json_encode($fileConfig)); return $fileConfig; } catch (Exception $e) { @@ -3022,7 +3022,7 @@ public function getObjectSettingsOnly(): array { try { $objectConfig = $this->config->getValueString($this->appName, 'objectManagement', ''); - + if (empty($objectConfig)) { return [ 'vectorizationEnabled' => false, @@ -3071,7 +3071,7 @@ public function updateObjectSettingsOnly(array $objectData): array 'batchSize' => $objectData['batchSize'] ?? 25, 'autoRetry' => $objectData['autoRetry'] ?? true, ]; - + $this->config->setValueString($this->appName, 'objectManagement', json_encode($objectConfig)); return $objectConfig; } catch (Exception $e) { @@ -3089,7 +3089,7 @@ public function getRetentionSettingsOnly(): array { try { $retentionConfig = $this->config->getValueString($this->appName, 'retention', ''); - + if (empty($retentionConfig)) { return [ 'objectArchiveRetention' => 31536000000, // 1 year default @@ -3142,7 +3142,7 @@ public function updateRetentionSettingsOnly(array $retentionData): array 'auditTrailsEnabled' => $retentionData['auditTrailsEnabled'] ?? true, 'searchTrailsEnabled' => $retentionData['searchTrailsEnabled'] ?? true, ]; - + $this->config->setValueString($this->appName, 'retention', json_encode($retentionConfig)); return $retentionConfig; } catch (Exception $e) { @@ -3181,15 +3181,15 @@ private function convertToBoolean($value): bool if (is_bool($value)) { return $value; } - + if (is_string($value)) { return in_array(strtolower($value), ['true', '1', 'yes', 'on'], true); } - + if (is_numeric($value)) { return (int) $value !== 0; } - + return (bool) $value; }//end convertToBoolean() diff --git a/website/docs/features/img.png b/website/docs/features/img.png deleted file mode 100644 index 2c24e9213..000000000 Binary files a/website/docs/features/img.png and /dev/null differ diff --git a/website/docs/features/img_1.png b/website/docs/features/img_1.png deleted file mode 100644 index 22876dad9..000000000 Binary files a/website/docs/features/img_1.png and /dev/null differ diff --git a/website/docs/features/img_2.png b/website/docs/features/img_2.png deleted file mode 100644 index 25f24525e..000000000 Binary files a/website/docs/features/img_2.png and /dev/null differ diff --git a/website/docs/features/img_3.png b/website/docs/features/img_3.png deleted file mode 100644 index d0bf77f85..000000000 Binary files a/website/docs/features/img_3.png and /dev/null differ diff --git a/website/docs/features/img_4.png b/website/docs/features/img_4.png deleted file mode 100644 index 630295d3f..000000000 Binary files a/website/docs/features/img_4.png and /dev/null differ diff --git a/website/docs/features/img_5.png b/website/docs/features/img_5.png deleted file mode 100644 index 630295d3f..000000000 Binary files a/website/docs/features/img_5.png and /dev/null differ diff --git a/website/static/oas/Examples/woo_bct_17-12-2025.json b/website/static/oas/Examples/woo_bct_17-12-2025.json new file mode 100644 index 000000000..e34ee8dbb --- /dev/null +++ b/website/static/oas/Examples/woo_bct_17-12-2025.json @@ -0,0 +1,3789 @@ +{ + "components": { + "mappings": { + "cloudeventtobctcall": { + "name": "CloudEventToBCTCall", + "description": "", + "version": "0.0.3", + "reference": "", + "mapping": { + "QueryExecute2.ObjectType": "S", + "QueryExecute2.QueryItems.QueryItem.RubricType": "qrtDbField", + "QueryExecute2.QueryItems.QueryItem.RubricID": "poststuk_id", + "QueryExecute2.QueryItems.QueryItem.Condition": "qcAnd", + "QueryExecute2.QueryItems.QueryItem.Operator": "qoEqual", + "QueryExecute2.QueryItems.QueryItem.Value": "data.documentId", + "QueryExecute2.SkipEmptyConditions": true, + "QueryExecute2.SearchByQueryOrder": true, + "QueryExecute2.SearchSubFolders": false, + "QueryExecute2.SearchRelated": false, + "QueryExecute2.SearchRecursive": false, + "QueryExecute2.ReturnIDsOnly": false, + "QueryExecute2.SearchMostRecent": false, + "QueryExecute2.MaxResult": 0, + "QueryExecute2.ResultItems.TypeValue.0.Type": "V", + "QueryExecute2.ResultItems.TypeValue.0.Value": "poststuk_id", + "QueryExecute2.ResultItems.TypeValue.1.Type": "V", + "QueryExecute2.ResultItems.TypeValue.1.Value": "onderwerp", + "QueryExecute2.ResultItems.TypeValue.2.Type": "R", + "QueryExecute2.ResultItems.TypeValue.2.Value": "wooPubDat", + "QueryExecute2.ResultItems.TypeValue.3.Type": "D", + "QueryExecute2.ResultItems.TypeValue.3.Value": "Dispinfocatpub" + }, + "unset": [], + "cast": [], + "passThrough": false, + "configurations": [], + "dateCreated": "2025-07-17T12:49:15+00:00", + "dateModified": "2025-07-17T12:49:15+00:00", + "slug": "cloudeventtobctcall" + }, + "corsa-to-woo-verzoeken-en-besluiten": { + "name": "Corsa to WOO-verzoeken en -besluiten", + "description": "", + "version": "0.0.7", + "reference": "", + "mapping": { + "kenmerk": "poststuk_id", + "titel": "onderwerp", + "samenvatting": "inhoud1", + "@self.published": "RwooPubDat" + }, + "unset": [], + "cast": { + "publicatieDatum": "unsetIfValue==wooPubDat" + }, + "passThrough": false, + "configurations": [], + "dateCreated": "2025-07-02T13:14:51+00:00", + "dateModified": "2025-07-02T13:14:51+00:00", + "slug": "corsa-to-woo-verzoeken-en-besluiten" + }, + "cloudevent-to-corsa-soap": { + "name": "CloudEvent to Corsa SOAP", + "description": "", + "version": "0.0.15", + "reference": "", + "mapping": { + "soap.QueryExecute2.ObjectType": "S", + "soap.QueryExecute2.QueryItems.QueryItem.0.RubricType": "qrtDbField", + "soap.QueryExecute2.QueryItems.QueryItem.0.RubricID": "poststuk_id", + "soap.QueryExecute2.QueryItems.QueryItem.0.Condition": "qcAnd", + "soap.QueryExecute2.QueryItems.QueryItem.0.Operator": "qoEqual", + "soap.QueryExecute2.QueryItems.QueryItem.0.Value": "data.documentId", + "soap.QueryExecute2.SkipEmptyConditions": "true", + "soap.QueryExecute2.SearchByQueryOrder": "true", + "soap.QueryExecute2.SearchSubFolders": "false", + "soap.QueryExecute2.SearchRelated": "false", + "soap.QueryExecute2.SearchRecursive": "false", + "soap.QueryExecute2.ReturnIDsOnly": "false", + "soap.QueryExecute2.SearchMostRecent": "false", + "soap.QueryExecute2.MaxResult": "0", + "soap.QueryExecute2.ResultItems.TypeValue.0.Type": "V", + "soap.QueryExecute2.ResultItems.TypeValue.0.Value": "poststuk_id", + "soap.QueryExecute2.ResultItems.TypeValue.1.Type": "V", + "soap.QueryExecute2.ResultItems.TypeValue.1.Value": "onderwerp", + "soap.QueryExecute2.ResultItems.TypeValue.2.Type": "R", + "soap.QueryExecute2.ResultItems.TypeValue.2.Value": "wooPubDat", + "soap.QueryExecute2.ResultItems.TypeValue.3.Type": "D", + "soap.QueryExecute2.ResultItems.TypeValue.3.Value": "Dispinfocatpub", + "soap.QueryExecute2.ResultItems.TypeValue.4.Type": "V", + "soap.QueryExecute2.ResultItems.TypeValue.4.Value": "inhoud" + }, + "unset": [], + "cast": { + "soap.QueryExecute2.SkipEmptyConditions": "bool", + "soap.QueryExecute2.SearchByQueryOrder": "bool", + "soap.QueryExecute2.SearchSubFolders": "bool", + "soap.QueryExecute2.SearchRelated": "bool", + "soap.QueryExecute2.SearchRecursive": "bool", + "soap.QueryExecute2.ReturnIDsOnly": "bool", + "soap.QueryExecute2.SearchMostRecent": "bool", + "soap.QueryExecute2.MaxResult": "int" + }, + "passThrough": true, + "configurations": [], + "dateCreated": "2025-07-01T08:01:11+00:00", + "dateModified": "2025-07-01T08:01:11+00:00", + "slug": "cloudevent-to-corsa-soap" + } + }, + "sources": { + "bct-corsa-mockservice": { + "name": "BCT Corsa Mockservice", + "description": "https://nuovodemo.ota.bct.nl/corsaws/Corsa72WS.asmx", + "version": "0.0.1", + "reference": "http://nextcloud.local/", + "location": "!ChangeMe!", + "isEnabled": true, + "type": "soap", + "locale": "", + "accept": "", + "documentation": "", + "loggingConfig": [], + "oas": "Array", + "paths": [], + "headers": [], + "translationConfig": [], + "configuration": { + "wsdl": "!ChangeMe!", + "cert": "!ChangeMe!", + "ssl_key": "!ChangeMe!", + "preRequest.endpoint": "Connect", + "preRequest.config.body": "{\"Connect\": { \"ApplicationID\": \"!ChangeMe!\", \"ConnectionID\": \"!ChangeMe!\", \"UserName\": \"!ChangeMe!\", \"Password\": \"!ChangeMe!\", \"EncodedPass\": false } }" + }, + "endpointsConfig": [], + "status": "", + "logRetention": 0, + "errorRetention": 0, + "objectCount": 0, + "test": false, + "rateLimitLimit": null, + "rateLimitRemaining": null, + "rateLimitReset": null, + "rateLimitWindow": null, + "lastCall": "2025-12-16T12:27:15+00:00", + "lastSync": "2025-06-12T11:24:42+00:00", + "dateCreated": "2025-07-01T09:09:33+00:00", + "dateModified": "2025-07-01T09:09:33+00:00", + "configurations": [], + "slug": "bct-corsa-mockservice" + } + }, + "rules": { + "fetch-anonymized-file-from-bct": { + "name": "Fetch anonimysed file from BCT", + "description": "", + "reference": "https://bct.accept.commonground.nu/apps/openconnector/api/rules/5", + "version": "0.0.13", + "action": "post", + "timing": "after", + "conditions": { + "==": [ + { + "var": "flowToken.requestAmended.parameters.data.anonymized" + }, + true + ] + }, + "type": "fetch_file", + "configuration": { + "fetch_file": { + "source": "bct-corsa-mockservice", + "filePath": "", + "subObjectFilepath": "", + "objectIdPath": "", + "method": "POST", + "tags": [], + "sourceConfiguration": { + "body": { + "GetFileVersion": { + "ObjectType": "S", + "ObjectID": "{{ originId }}", + "FileType": "ftAnonymised", + "FileVersion": 0 + } + } + }, + "autoShare": true, + "endpoint": { + "endpoint": "GetFileVersion", + "published": true + }, + "contentPath": "FileBytes", + "originIdPath": "kenmerk", + "filenamePath": "VersionInfo.DocumentName", + "fileExtension": ".pdf" + } + }, + "order": 1, + "configurations": [], + "created": "2025-04-10T13:44:24+00:00", + "updated": "2025-11-04T13:11:50+00:00", + "slug": "fetch-anonymized-file-from-bct" + }, + "fetch-archived-file-from-bct": { + "name": "Fetch archived file from BCT", + "description": "", + "reference": "https://bct.accept.commonground.nu/apps/openconnector/api/rules/5", + "version": "0.0.10", + "action": "post", + "timing": "after", + "conditions": { + "==": [ + { + "var": "flowToken.requestAmended.parameters.data.anonymized" + }, + false + ] + }, + "type": "fetch_file", + "configuration": { + "fetch_file": { + "source": "bct-corsa-mockservice", + "filePath": "", + "subObjectFilepath": "", + "objectIdPath": "", + "method": "POST", + "tags": [], + "sourceConfiguration": { + "body": { + "GetFileVersion": { + "ObjectType": "S", + "ObjectID": "{{ originId }}", + "FileType": "ftArchive", + "FileVersion": 0 + } + } + }, + "autoShare": true, + "endpoint": { + "endpoint": "GetFileVersion", + "published": true + }, + "contentPath": "FileBytes", + "originIdPath": "kenmerk", + "filenamePath": "VersionInfo.DocumentName", + "fileExtension": ".pdf" + } + }, + "order": 1, + "configurations": [], + "created": "2025-04-10T13:44:24+00:00", + "updated": "2025-11-04T13:12:05+00:00", + "slug": "fetch-archived-file-from-bct" + }, + "bct-auth": { + "name": "BCT Auth", + "description": "", + "reference": null, + "version": "0.0.1", + "action": "post", + "timing": "before", + "conditions": null, + "type": "authentication", + "configuration": { + "authentication": { + "type": "apikey", + "users": [ + "bct" + ], + "groups": [], + "header": "X-Corsa-Secret", + "keys": { + "yWusci0XtY6zVKf$Ga-uG9bVoJ0NDcq@": "bct" + } + } + }, + "order": 0, + "configurations": [], + "created": "2025-06-12T08:53:29+00:00", + "updated": "2025-06-12T08:53:29+00:00", + "slug": "bct-auth" + }, + "cloudevent-to-corsa-soap": { + "name": "CloudEvent to Corsa SOAP", + "description": "", + "reference": null, + "version": "0.0.2", + "action": "post", + "timing": "after", + "conditions": { + "==": [ + 1, + 1 + ] + }, + "type": "mapping", + "configuration": { + "mapping": "cloudevent-to-corsa-soap" + }, + "order": 0, + "configurations": [], + "created": "2025-07-01T08:14:21+00:00", + "updated": "2025-07-18T08:23:31+00:00", + "slug": "cloudevent-to-corsa-soap" + }, + "sync-corsa": { + "name": "Sync CORSA Woo-verzoeken en -besluiten", + "description": "", + "reference": "https://bct.accept.commonground.nu/apps/openconnector/api/rules/3", + "version": "0.0.7", + "action": "post", + "timing": "after", + "conditions": { + "or": [ + { + "==": [ + { + "var": "parameters.data.informatieCategorie" + }, + "3.32i" + ] + }, + { + "==": [ + { + "var": "parameters.data.informatieCategorie" + }, + "3.32I" + ] + }, + { + "==": [ + { + "var": "parameters.data.informatieCategorie" + }, + "" + ] + } + ] + }, + "type": "synchronization", + "configuration": { + "force": true, + "synchronization": { + "synchronization": 1, + "retainResponse": true + }, + "error": { + "code": 500, + "name": "Something went wrong", + "message": "We encountered an unexpected problem", + "includeJsonLogicResult": false + }, + "authentication": { + "type": { + "label": "Basic Authentication", + "value": "basic" + }, + "users": [], + "groups": [], + "keys": [] + }, + "download": { + "fileIdPosition": 0 + }, + "upload": { + "path": "", + "allowedTypes": "", + "maxSize": 10 + }, + "locking": { + "action": "lock", + "timeout": 30 + }, + "fetch_file": { + "source": "", + "filePath": "", + "subObjectFilepath": "", + "objectIdPath": "", + "method": "", + "tags": [], + "sourceConfiguration": "\"[]\"", + "autoShare": false, + "endpoint": "", + "contentPath": "", + "originIdPath": "", + "filenamePath": "", + "fileExtension": "" + }, + "write_file": { + "filePath": "", + "fileNamePath": "", + "tags": [], + "autoShare": false + }, + "fileparts_create": { + "sizeLocation": "", + "schemaId": "", + "filenameLocation": "", + "filePartLocation": "", + "mappingId": "" + }, + "filepart_upload": { + "mappingId": "" + }, + "save_object": { + "register": "", + "schema": "", + "mapping": "" + }, + "extend_external_input": { + "validate": true, + "properties": [ + { + "property": "", + "schema": "" + } + ] + }, + "extend_input": { + "items": [ + { + "property": "", + "extends": [] + } + ] + } + }, + "order": 1, + "configurations": [], + "created": "2025-07-01T08:19:08+00:00", + "updated": "2025-10-21T13:31:09+00:00", + "slug": "sync-corsa" + }, + "sync-corsa-klachtoordelen": { + "name": "Sync CORSA Klachtoordelen", + "description": "", + "reference": "https://bct.accept.commonground.nu/", + "version": "0.0.7", + "action": "post", + "timing": "after", + "conditions": { + "or": [ + { + "==": [ + { + "var": "parameters.data.informatieCategorie" + }, + "3.32l" + ] + }, + { + "==": [ + { + "var": "parameters.data.informatieCategorie" + }, + "3.32L" + ] + }, + { + "==": [ + { + "var": "parameters.data.informatieCategorie" + }, + "" + ] + } + ] + }, + "type": "synchronization", + "configuration": { + "force": true, + "synchronization": { + "synchronization": 17, + "retainResponse": true + }, + "error": { + "code": 500, + "name": "Something went wrong", + "message": "We encountered an unexpected problem", + "includeJsonLogicResult": false + }, + "authentication": { + "type": { + "label": "Basic Authentication", + "value": "basic" + }, + "users": [], + "groups": [], + "keys": [] + }, + "download": { + "fileIdPosition": 0 + }, + "upload": { + "path": "", + "allowedTypes": "", + "maxSize": 10 + }, + "locking": { + "action": "lock", + "timeout": 30 + }, + "fetch_file": { + "source": "", + "filePath": "", + "subObjectFilepath": "", + "objectIdPath": "", + "method": "", + "tags": [], + "sourceConfiguration": "\"[]\"", + "autoShare": false, + "endpoint": "", + "contentPath": "", + "originIdPath": "", + "filenamePath": "", + "fileExtension": "" + }, + "write_file": { + "filePath": "", + "fileNamePath": "", + "tags": [], + "autoShare": false + }, + "fileparts_create": { + "sizeLocation": "", + "schemaId": "", + "filenameLocation": "", + "filePartLocation": "", + "mappingId": "" + }, + "filepart_upload": { + "mappingId": "" + }, + "save_object": { + "register": "", + "schema": "", + "mapping": "" + }, + "extend_external_input": { + "validate": true, + "properties": [ + { + "property": "", + "schema": "" + } + ] + }, + "extend_input": { + "items": [ + { + "property": "", + "extends": [] + } + ] + } + }, + "order": 1, + "configurations": [], + "created": "2025-09-11T07:55:02+00:00", + "updated": "2025-10-21T13:31:35+00:00", + "slug": "sync-corsa-klachtoordelen" + }, + "sync-corsa-beschikkingen": { + "name": "Sync CORSA Beschikkingen", + "description": "", + "reference": "https://bct.accept.commonground.nu/", + "version": "0.0.7", + "action": "post", + "timing": "after", + "conditions": { + "or": [ + { + "==": [ + { + "var": "parameters.data.informatieCategorie" + }, + "3.32k" + ] + }, + { + "==": [ + { + "var": "parameters.data.informatieCategorie" + }, + "3.32K" + ] + }, + { + "==": [ + { + "var": "parameters.data.informatieCategorie" + }, + "" + ] + } + ] + }, + "type": "synchronization", + "configuration": { + "force": true, + "synchronization": { + "synchronization": 16, + "retainResponse": true + }, + "error": { + "code": 500, + "name": "Something went wrong", + "message": "We encountered an unexpected problem", + "includeJsonLogicResult": false + }, + "authentication": { + "type": { + "label": "Basic Authentication", + "value": "basic" + }, + "users": [], + "groups": [], + "keys": [] + }, + "download": { + "fileIdPosition": 0 + }, + "upload": { + "path": "", + "allowedTypes": "", + "maxSize": 10 + }, + "locking": { + "action": "lock", + "timeout": 30 + }, + "fetch_file": { + "source": "", + "filePath": "", + "subObjectFilepath": "", + "objectIdPath": "", + "method": "", + "tags": [], + "sourceConfiguration": "\"[]\"", + "autoShare": false, + "endpoint": "", + "contentPath": "", + "originIdPath": "", + "filenamePath": "", + "fileExtension": "" + }, + "write_file": { + "filePath": "", + "fileNamePath": "", + "tags": [], + "autoShare": false + }, + "fileparts_create": { + "sizeLocation": "", + "schemaId": "", + "filenameLocation": "", + "filePartLocation": "", + "mappingId": "" + }, + "filepart_upload": { + "mappingId": "" + }, + "save_object": { + "register": "", + "schema": "", + "mapping": "" + }, + "extend_external_input": { + "validate": true, + "properties": [ + { + "property": "", + "schema": "" + } + ] + }, + "extend_input": { + "items": [ + { + "property": "", + "extends": [] + } + ] + } + }, + "order": 1, + "configurations": [], + "created": "2025-09-11T07:55:02+00:00", + "updated": "2025-10-21T13:31:50+00:00", + "slug": "sync-corsa-beschikkingen" + }, + "sync-corsa-onderzoeksrapporten": { + "name": "Sync CORSA Onderzoeksrapporten", + "description": "", + "reference": "https://bct.accept.commonground.nu/", + "version": "0.0.7", + "action": "post", + "timing": "after", + "conditions": { + "or": [ + { + "==": [ + { + "var": "parameters.data.informatieCategorie" + }, + "3.32j" + ] + }, + { + "==": [ + { + "var": "parameters.data.informatieCategorie" + }, + "3.32J" + ] + }, + { + "==": [ + { + "var": "parameters.data.informatieCategorie" + }, + "" + ] + } + ] + }, + "type": "synchronization", + "configuration": { + "force": true, + "synchronization": { + "synchronization": 15, + "retainResponse": true + }, + "error": { + "code": 500, + "name": "Something went wrong", + "message": "We encountered an unexpected problem", + "includeJsonLogicResult": false + }, + "authentication": { + "type": { + "label": "Basic Authentication", + "value": "basic" + }, + "users": [], + "groups": [], + "keys": [] + }, + "download": { + "fileIdPosition": 0 + }, + "upload": { + "path": "", + "allowedTypes": "", + "maxSize": 10 + }, + "locking": { + "action": "lock", + "timeout": 30 + }, + "fetch_file": { + "source": "", + "filePath": "", + "subObjectFilepath": "", + "objectIdPath": "", + "method": "", + "tags": [], + "sourceConfiguration": "\"[]\"", + "autoShare": false, + "endpoint": "", + "contentPath": "", + "originIdPath": "", + "filenamePath": "", + "fileExtension": "" + }, + "write_file": { + "filePath": "", + "fileNamePath": "", + "tags": [], + "autoShare": false + }, + "fileparts_create": { + "sizeLocation": "", + "schemaId": "", + "filenameLocation": "", + "filePartLocation": "", + "mappingId": "" + }, + "filepart_upload": { + "mappingId": "" + }, + "save_object": { + "register": "", + "schema": "", + "mapping": "" + }, + "extend_external_input": { + "validate": true, + "properties": [ + { + "property": "", + "schema": "" + } + ] + }, + "extend_input": { + "items": [ + { + "property": "", + "extends": [] + } + ] + } + }, + "order": 1, + "configurations": [], + "created": "2025-09-11T07:55:02+00:00", + "updated": "2025-10-21T13:32:04+00:00", + "slug": "sync-corsa-onderzoeksrapporten" + }, + "sync-corsa-subsidieverplichtingen-anders-dan-met-beschikking": { + "name": "Sync CORSA Subsidieverplichtingen anders dan met beschikking", + "description": "", + "reference": "https://bct.accept.commonground.nu/", + "version": "0.0.7", + "action": "post", + "timing": "after", + "conditions": { + "or": [ + { + "==": [ + { + "var": "parameters.data.informatieCategorie" + }, + "3.32h" + ] + }, + { + "==": [ + { + "var": "parameters.data.informatieCategorie" + }, + "3.32H" + ] + }, + { + "==": [ + { + "var": "parameters.data.informatieCategorie" + }, + "" + ] + } + ] + }, + "type": "synchronization", + "configuration": { + "force": true, + "synchronization": { + "synchronization": 14, + "retainResponse": true + }, + "error": { + "code": 500, + "name": "Something went wrong", + "message": "We encountered an unexpected problem", + "includeJsonLogicResult": false + }, + "authentication": { + "type": { + "label": "Basic Authentication", + "value": "basic" + }, + "users": [], + "groups": [], + "keys": [] + }, + "download": { + "fileIdPosition": 0 + }, + "upload": { + "path": "", + "allowedTypes": "", + "maxSize": 10 + }, + "locking": { + "action": "lock", + "timeout": 30 + }, + "fetch_file": { + "source": "", + "filePath": "", + "subObjectFilepath": "", + "objectIdPath": "", + "method": "", + "tags": [], + "sourceConfiguration": "\"[]\"", + "autoShare": false, + "endpoint": "", + "contentPath": "", + "originIdPath": "", + "filenamePath": "", + "fileExtension": "" + }, + "write_file": { + "filePath": "", + "fileNamePath": "", + "tags": [], + "autoShare": false + }, + "fileparts_create": { + "sizeLocation": "", + "schemaId": "", + "filenameLocation": "", + "filePartLocation": "", + "mappingId": "" + }, + "filepart_upload": { + "mappingId": "" + }, + "save_object": { + "register": "", + "schema": "", + "mapping": "" + }, + "extend_external_input": { + "validate": true, + "properties": [ + { + "property": "", + "schema": "" + } + ] + }, + "extend_input": { + "items": [ + { + "property": "", + "extends": [] + } + ] + } + }, + "order": 1, + "configurations": [], + "created": "2025-09-11T07:55:02+00:00", + "updated": "2025-10-21T13:32:21+00:00", + "slug": "sync-corsa-subsidieverplichtingen-anders-dan-met-beschikking" + }, + "sync-corsa-jaarplannen-en-jaarverslagen": { + "name": "Sync CORSA Jaarplannen en jaarverslagen", + "description": "", + "reference": "https://bct.accept.commonground.nu/", + "version": "0.0.7", + "action": "post", + "timing": "after", + "conditions": { + "or": [ + { + "==": [ + { + "var": "parameters.data.informatieCategorie" + }, + "3.32g" + ] + }, + { + "==": [ + { + "var": "parameters.data.informatieCategorie" + }, + "3.32G" + ] + }, + { + "==": [ + { + "var": "parameters.data.informatieCategorie" + }, + "" + ] + } + ] + }, + "type": "synchronization", + "configuration": { + "force": true, + "synchronization": { + "synchronization": 13, + "retainResponse": true + }, + "error": { + "code": 500, + "name": "Something went wrong", + "message": "We encountered an unexpected problem", + "includeJsonLogicResult": false + }, + "authentication": { + "type": { + "label": "Basic Authentication", + "value": "basic" + }, + "users": [], + "groups": [], + "keys": [] + }, + "download": { + "fileIdPosition": 0 + }, + "upload": { + "path": "", + "allowedTypes": "", + "maxSize": 10 + }, + "locking": { + "action": "lock", + "timeout": 30 + }, + "fetch_file": { + "source": "", + "filePath": "", + "subObjectFilepath": "", + "objectIdPath": "", + "method": "", + "tags": [], + "sourceConfiguration": "\"[]\"", + "autoShare": false, + "endpoint": "", + "contentPath": "", + "originIdPath": "", + "filenamePath": "", + "fileExtension": "" + }, + "write_file": { + "filePath": "", + "fileNamePath": "", + "tags": [], + "autoShare": false + }, + "fileparts_create": { + "sizeLocation": "", + "schemaId": "", + "filenameLocation": "", + "filePartLocation": "", + "mappingId": "" + }, + "filepart_upload": { + "mappingId": "" + }, + "save_object": { + "register": "", + "schema": "", + "mapping": "" + }, + "extend_external_input": { + "validate": true, + "properties": [ + { + "property": "", + "schema": "" + } + ] + }, + "extend_input": { + "items": [ + { + "property": "", + "extends": [] + } + ] + } + }, + "order": 1, + "configurations": [], + "created": "2025-09-11T07:55:02+00:00", + "updated": "2025-10-21T13:32:32+00:00", + "slug": "sync-corsa-jaarplannen-en-jaarverslagen" + }, + "sync-corsa-agendas-en-besluitenlijsten-bestuurscolleges": { + "name": "Sync CORSA Agenda's en besluitenlijsten bestuurscolleges", + "description": "", + "reference": "https://bct.accept.commonground.nu/", + "version": "0.0.7", + "action": "post", + "timing": "after", + "conditions": { + "or": [ + { + "==": [ + { + "var": "parameters.data.informatieCategorie" + }, + "3.32d" + ] + }, + { + "==": [ + { + "var": "parameters.data.informatieCategorie" + }, + "3.32D" + ] + }, + { + "==": [ + { + "var": "parameters.data.informatieCategorie" + }, + "" + ] + } + ] + }, + "type": "synchronization", + "configuration": { + "force": true, + "synchronization": { + "synchronization": 10, + "retainResponse": true + }, + "error": { + "code": 500, + "name": "Something went wrong", + "message": "We encountered an unexpected problem", + "includeJsonLogicResult": false + }, + "authentication": { + "type": { + "label": "Basic Authentication", + "value": "basic" + }, + "users": [], + "groups": [], + "keys": [] + }, + "download": { + "fileIdPosition": 0 + }, + "upload": { + "path": "", + "allowedTypes": "", + "maxSize": 10 + }, + "locking": { + "action": "lock", + "timeout": 30 + }, + "fetch_file": { + "source": "", + "filePath": "", + "subObjectFilepath": "", + "objectIdPath": "", + "method": "", + "tags": [], + "sourceConfiguration": "\"[]\"", + "autoShare": false, + "endpoint": "", + "contentPath": "", + "originIdPath": "", + "filenamePath": "", + "fileExtension": "" + }, + "write_file": { + "filePath": "", + "fileNamePath": "", + "tags": [], + "autoShare": false + }, + "fileparts_create": { + "sizeLocation": "", + "schemaId": "", + "filenameLocation": "", + "filePartLocation": "", + "mappingId": "" + }, + "filepart_upload": { + "mappingId": "" + }, + "save_object": { + "register": "", + "schema": "", + "mapping": "" + }, + "extend_external_input": { + "validate": true, + "properties": [ + { + "property": "", + "schema": "" + } + ] + }, + "extend_input": { + "items": [ + { + "property": "", + "extends": [] + } + ] + } + }, + "order": 1, + "configurations": [], + "created": "2025-09-11T07:55:02+00:00", + "updated": "2025-10-21T13:32:40+00:00", + "slug": "sync-corsa-agendas-en-besluitenlijsten-bestuurscolleges" + }, + "sync-corsa-adviezen": { + "name": "Sync CORSA Adviezen", + "description": "", + "reference": "https://bct.accept.commonground.nu/", + "version": "0.0.7", + "action": "post", + "timing": "after", + "conditions": { + "or": [ + { + "==": [ + { + "var": "parameters.data.informatieCategorie" + }, + "3.32e" + ] + }, + { + "==": [ + { + "var": "parameters.data.informatieCategorie" + }, + "3.32E" + ] + }, + { + "==": [ + { + "var": "parameters.data.informatieCategorie" + }, + "" + ] + } + ] + }, + "type": "synchronization", + "configuration": { + "force": true, + "synchronization": { + "synchronization": 11, + "retainResponse": true + }, + "error": { + "code": 500, + "name": "Something went wrong", + "message": "We encountered an unexpected problem", + "includeJsonLogicResult": false + }, + "authentication": { + "type": { + "label": "Basic Authentication", + "value": "basic" + }, + "users": [], + "groups": [], + "keys": [] + }, + "download": { + "fileIdPosition": 0 + }, + "upload": { + "path": "", + "allowedTypes": "", + "maxSize": 10 + }, + "locking": { + "action": "lock", + "timeout": 30 + }, + "fetch_file": { + "source": "", + "filePath": "", + "subObjectFilepath": "", + "objectIdPath": "", + "method": "", + "tags": [], + "sourceConfiguration": "\"[]\"", + "autoShare": false, + "endpoint": "", + "contentPath": "", + "originIdPath": "", + "filenamePath": "", + "fileExtension": "" + }, + "write_file": { + "filePath": "", + "fileNamePath": "", + "tags": [], + "autoShare": false + }, + "fileparts_create": { + "sizeLocation": "", + "schemaId": "", + "filenameLocation": "", + "filePartLocation": "", + "mappingId": "" + }, + "filepart_upload": { + "mappingId": "" + }, + "save_object": { + "register": "", + "schema": "", + "mapping": "" + }, + "extend_external_input": { + "validate": true, + "properties": [ + { + "property": "", + "schema": "" + } + ] + }, + "extend_input": { + "items": [ + { + "property": "", + "extends": [] + } + ] + } + }, + "order": 1, + "configurations": [], + "created": "2025-09-11T07:55:02+00:00", + "updated": "2025-10-21T13:32:49+00:00", + "slug": "sync-corsa-adviezen" + }, + "sync-corsa-vergaderstukken-decentrale-overheden": { + "name": "Sync CORSA Vergaderstukken decentrale overheden", + "description": "", + "reference": "https://bct.accept.commonground.nu/", + "version": "0.0.7", + "action": "post", + "timing": "after", + "conditions": { + "or": [ + { + "==": [ + { + "var": "parameters.data.informatieCategorie" + }, + "3.32c" + ] + }, + { + "==": [ + { + "var": "parameters.data.informatieCategorie" + }, + "3.32C" + ] + }, + { + "==": [ + { + "var": "parameters.data.informatieCategorie" + }, + "" + ] + } + ] + }, + "type": "synchronization", + "configuration": { + "force": true, + "synchronization": { + "synchronization": 9, + "retainResponse": true + }, + "error": { + "code": 500, + "name": "Something went wrong", + "message": "We encountered an unexpected problem", + "includeJsonLogicResult": false + }, + "authentication": { + "type": { + "label": "Basic Authentication", + "value": "basic" + }, + "users": [], + "groups": [], + "keys": [] + }, + "download": { + "fileIdPosition": 0 + }, + "upload": { + "path": "", + "allowedTypes": "", + "maxSize": 10 + }, + "locking": { + "action": "lock", + "timeout": 30 + }, + "fetch_file": { + "source": "", + "filePath": "", + "subObjectFilepath": "", + "objectIdPath": "", + "method": "", + "tags": [], + "sourceConfiguration": "\"[]\"", + "autoShare": false, + "endpoint": "", + "contentPath": "", + "originIdPath": "", + "filenamePath": "", + "fileExtension": "" + }, + "write_file": { + "filePath": "", + "fileNamePath": "", + "tags": [], + "autoShare": false + }, + "fileparts_create": { + "sizeLocation": "", + "schemaId": "", + "filenameLocation": "", + "filePartLocation": "", + "mappingId": "" + }, + "filepart_upload": { + "mappingId": "" + }, + "save_object": { + "register": "", + "schema": "", + "mapping": "" + }, + "extend_external_input": { + "validate": true, + "properties": [ + { + "property": "", + "schema": "" + } + ] + }, + "extend_input": { + "items": [ + { + "property": "", + "extends": [] + } + ] + } + }, + "order": 1, + "configurations": [], + "created": "2025-09-11T07:55:02+00:00", + "updated": "2025-10-21T13:33:02+00:00", + "slug": "sync-corsa-vergaderstukken-decentrale-overheden" + }, + "sync-corsa-vergaderstukken-staten-generaal": { + "name": "Sync CORSA Vergaderstukken Staten-Generaal", + "description": "", + "reference": "https://bct.accept.commonground.nu/", + "version": "0.0.7", + "action": "post", + "timing": "after", + "conditions": { + "or": [ + { + "==": [ + { + "var": "parameters.data.informatieCategorie" + }, + "3.32b" + ] + }, + { + "==": [ + { + "var": "parameters.data.informatieCategorie" + }, + "3.32B" + ] + }, + { + "==": [ + { + "var": "parameters.data.informatieCategorie" + }, + "" + ] + } + ] + }, + "type": "synchronization", + "configuration": { + "force": true, + "synchronization": { + "synchronization": 8, + "retainResponse": true + }, + "error": { + "code": 500, + "name": "Something went wrong", + "message": "We encountered an unexpected problem", + "includeJsonLogicResult": false + }, + "authentication": { + "type": { + "label": "Basic Authentication", + "value": "basic" + }, + "users": [], + "groups": [], + "keys": [] + }, + "download": { + "fileIdPosition": 0 + }, + "upload": { + "path": "", + "allowedTypes": "", + "maxSize": 10 + }, + "locking": { + "action": "lock", + "timeout": 30 + }, + "fetch_file": { + "source": "", + "filePath": "", + "subObjectFilepath": "", + "objectIdPath": "", + "method": "", + "tags": [], + "sourceConfiguration": "\"[]\"", + "autoShare": false, + "endpoint": "", + "contentPath": "", + "originIdPath": "", + "filenamePath": "", + "fileExtension": "" + }, + "write_file": { + "filePath": "", + "fileNamePath": "", + "tags": [], + "autoShare": false + }, + "fileparts_create": { + "sizeLocation": "", + "schemaId": "", + "filenameLocation": "", + "filePartLocation": "", + "mappingId": "" + }, + "filepart_upload": { + "mappingId": "" + }, + "save_object": { + "register": "", + "schema": "", + "mapping": "" + }, + "extend_external_input": { + "validate": true, + "properties": [ + { + "property": "", + "schema": "" + } + ] + }, + "extend_input": { + "items": [ + { + "property": "", + "extends": [] + } + ] + } + }, + "order": 1, + "configurations": [], + "created": "2025-09-11T07:55:02+00:00", + "updated": "2025-10-21T13:33:11+00:00", + "slug": "sync-corsa-vergaderstukken-staten-generaal" + }, + "sync-corsa-bij-vertegenwoordigende-organen-ingekomen-stukken": { + "name": "Sync CORSA Bij vertegenwoordigende organen ingekomen stukken", + "description": "", + "reference": "https://bct.accept.commonground.nu/", + "version": "0.0.7", + "action": "post", + "timing": "after", + "conditions": { + "or": [ + { + "==": [ + { + "var": "parameters.data.informatieCategorie" + }, + "3.32a" + ] + }, + { + "==": [ + { + "var": "parameters.data.informatieCategorie" + }, + "3.32A" + ] + }, + { + "==": [ + { + "var": "parameters.data.informatieCategorie" + }, + "" + ] + } + ] + }, + "type": "synchronization", + "configuration": { + "force": true, + "synchronization": { + "synchronization": 7, + "retainResponse": true + }, + "error": { + "code": 500, + "name": "Something went wrong", + "message": "We encountered an unexpected problem", + "includeJsonLogicResult": false + }, + "authentication": { + "type": { + "label": "Basic Authentication", + "value": "basic" + }, + "users": [], + "groups": [], + "keys": [] + }, + "download": { + "fileIdPosition": 0 + }, + "upload": { + "path": "", + "allowedTypes": "", + "maxSize": 10 + }, + "locking": { + "action": "lock", + "timeout": 30 + }, + "fetch_file": { + "source": "", + "filePath": "", + "subObjectFilepath": "", + "objectIdPath": "", + "method": "", + "tags": [], + "sourceConfiguration": "\"[]\"", + "autoShare": false, + "endpoint": "", + "contentPath": "", + "originIdPath": "", + "filenamePath": "", + "fileExtension": "" + }, + "write_file": { + "filePath": "", + "fileNamePath": "", + "tags": [], + "autoShare": false + }, + "fileparts_create": { + "sizeLocation": "", + "schemaId": "", + "filenameLocation": "", + "filePartLocation": "", + "mappingId": "" + }, + "filepart_upload": { + "mappingId": "" + }, + "save_object": { + "register": "", + "schema": "", + "mapping": "" + }, + "extend_external_input": { + "validate": true, + "properties": [ + { + "property": "", + "schema": "" + } + ] + }, + "extend_input": { + "items": [ + { + "property": "", + "extends": [] + } + ] + } + }, + "order": 1, + "configurations": [], + "created": "2025-09-11T07:55:02+00:00", + "updated": "2025-10-21T13:33:19+00:00", + "slug": "sync-corsa-bij-vertegenwoordigende-organen-ingekomen-stukken" + }, + "sync-corsa-bereikbaarheidsgegevens": { + "name": "Sync CORSA Bereikbaarheidsgegevens", + "description": "", + "reference": "https://bct.accept.commonground.nu/", + "version": "0.0.7", + "action": "post", + "timing": "after", + "conditions": { + "or": [ + { + "==": [ + { + "var": "parameters.data.informatieCategorie" + }, + "3.31e" + ] + }, + { + "==": [ + { + "var": "parameters.data.informatieCategorie" + }, + "3.31E" + ] + }, + { + "==": [ + { + "var": "parameters.data.informatieCategorie" + }, + "" + ] + } + ] + }, + "type": "synchronization", + "configuration": { + "force": true, + "synchronization": { + "synchronization": 6, + "retainResponse": true + }, + "error": { + "code": 500, + "name": "Something went wrong", + "message": "We encountered an unexpected problem", + "includeJsonLogicResult": false + }, + "authentication": { + "type": { + "label": "Basic Authentication", + "value": "basic" + }, + "users": [], + "groups": [], + "keys": [] + }, + "download": { + "fileIdPosition": 0 + }, + "upload": { + "path": "", + "allowedTypes": "", + "maxSize": 10 + }, + "locking": { + "action": "lock", + "timeout": 30 + }, + "fetch_file": { + "source": "", + "filePath": "", + "subObjectFilepath": "", + "objectIdPath": "", + "method": "", + "tags": [], + "sourceConfiguration": "\"[]\"", + "autoShare": false, + "endpoint": "", + "contentPath": "", + "originIdPath": "", + "filenamePath": "", + "fileExtension": "" + }, + "write_file": { + "filePath": "", + "fileNamePath": "", + "tags": [], + "autoShare": false + }, + "fileparts_create": { + "sizeLocation": "", + "schemaId": "", + "filenameLocation": "", + "filePartLocation": "", + "mappingId": "" + }, + "filepart_upload": { + "mappingId": "" + }, + "save_object": { + "register": "", + "schema": "", + "mapping": "" + }, + "extend_external_input": { + "validate": true, + "properties": [ + { + "property": "", + "schema": "" + } + ] + }, + "extend_input": { + "items": [ + { + "property": "", + "extends": [] + } + ] + } + }, + "order": 1, + "configurations": [], + "created": "2025-09-11T07:55:02+00:00", + "updated": "2025-10-21T13:33:28+00:00", + "slug": "sync-corsa-bereikbaarheidsgegevens" + }, + "sync-corsa-organisatie-en-werkwijze": { + "name": "Sync CORSA Organisatie en werkwijze", + "description": "", + "reference": "https://bct.accept.commonground.nu/", + "version": "0.0.7", + "action": "post", + "timing": "after", + "conditions": { + "or": [ + { + "==": [ + { + "var": "parameters.data.informatieCategorie" + }, + "3.31d" + ] + }, + { + "==": [ + { + "var": "parameters.data.informatieCategorie" + }, + "3.31D" + ] + }, + { + "==": [ + { + "var": "parameters.data.informatieCategorie" + }, + "" + ] + } + ] + }, + "type": "synchronization", + "configuration": { + "force": true, + "synchronization": { + "synchronization": 5, + "retainResponse": true + }, + "error": { + "code": 500, + "name": "Something went wrong", + "message": "We encountered an unexpected problem", + "includeJsonLogicResult": false + }, + "authentication": { + "type": { + "label": "Basic Authentication", + "value": "basic" + }, + "users": [], + "groups": [], + "keys": [] + }, + "download": { + "fileIdPosition": 0 + }, + "upload": { + "path": "", + "allowedTypes": "", + "maxSize": 10 + }, + "locking": { + "action": "lock", + "timeout": 30 + }, + "fetch_file": { + "source": "", + "filePath": "", + "subObjectFilepath": "", + "objectIdPath": "", + "method": "", + "tags": [], + "sourceConfiguration": "\"[]\"", + "autoShare": false, + "endpoint": "", + "contentPath": "", + "originIdPath": "", + "filenamePath": "", + "fileExtension": "" + }, + "write_file": { + "filePath": "", + "fileNamePath": "", + "tags": [], + "autoShare": false + }, + "fileparts_create": { + "sizeLocation": "", + "schemaId": "", + "filenameLocation": "", + "filePartLocation": "", + "mappingId": "" + }, + "filepart_upload": { + "mappingId": "" + }, + "save_object": { + "register": "", + "schema": "", + "mapping": "" + }, + "extend_external_input": { + "validate": true, + "properties": [ + { + "property": "", + "schema": "" + } + ] + }, + "extend_input": { + "items": [ + { + "property": "", + "extends": [] + } + ] + } + }, + "order": 1, + "configurations": [], + "created": "2025-09-11T07:55:02+00:00", + "updated": "2025-10-21T13:33:36+00:00", + "slug": "sync-corsa-organisatie-en-werkwijze" + }, + "sync-corsa-ontwerpen-van-wet-en-regelgeving-met-adviesaanvraag": { + "name": "Sync CORSA Ontwerpen van wet- en regelgeving met adviesaanvraag", + "description": "", + "reference": "https://bct.accept.commonground.nu/", + "version": "0.0.7", + "action": "post", + "timing": "after", + "conditions": { + "or": [ + { + "==": [ + { + "var": "parameters.data.informatieCategorie" + }, + "3.31c" + ] + }, + { + "==": [ + { + "var": "parameters.data.informatieCategorie" + }, + "3.31C" + ] + }, + { + "==": [ + { + "var": "parameters.data.informatieCategorie" + }, + "" + ] + } + ] + }, + "type": "synchronization", + "configuration": { + "force": true, + "synchronization": { + "synchronization": 4, + "retainResponse": true + }, + "error": { + "code": 500, + "name": "Something went wrong", + "message": "We encountered an unexpected problem", + "includeJsonLogicResult": false + }, + "authentication": { + "type": { + "label": "Basic Authentication", + "value": "basic" + }, + "users": [], + "groups": [], + "keys": [] + }, + "download": { + "fileIdPosition": 0 + }, + "upload": { + "path": "", + "allowedTypes": "", + "maxSize": 10 + }, + "locking": { + "action": "lock", + "timeout": 30 + }, + "fetch_file": { + "source": "", + "filePath": "", + "subObjectFilepath": "", + "objectIdPath": "", + "method": "", + "tags": [], + "sourceConfiguration": "\"[]\"", + "autoShare": false, + "endpoint": "", + "contentPath": "", + "originIdPath": "", + "filenamePath": "", + "fileExtension": "" + }, + "write_file": { + "filePath": "", + "fileNamePath": "", + "tags": [], + "autoShare": false + }, + "fileparts_create": { + "sizeLocation": "", + "schemaId": "", + "filenameLocation": "", + "filePartLocation": "", + "mappingId": "" + }, + "filepart_upload": { + "mappingId": "" + }, + "save_object": { + "register": "", + "schema": "", + "mapping": "" + }, + "extend_external_input": { + "validate": true, + "properties": [ + { + "property": "", + "schema": "" + } + ] + }, + "extend_input": { + "items": [ + { + "property": "", + "extends": [] + } + ] + } + }, + "order": 1, + "configurations": [], + "created": "2025-09-11T07:55:02+00:00", + "updated": "2025-10-21T13:33:44+00:00", + "slug": "sync-corsa-ontwerpen-van-wet-en-regelgeving-met-adviesaanvraag" + }, + "sync-corsa-overige-besluiten-van-algemene-strekking": { + "name": "Sync CORSA Overige besluiten van algemene strekking", + "description": "", + "reference": "https://bct.accept.commonground.nu/", + "version": "0.0.7", + "action": "post", + "timing": "after", + "conditions": { + "or": [ + { + "==": [ + { + "var": "parameters.data.informatieCategorie" + }, + "3.31b" + ] + }, + { + "==": [ + { + "var": "parameters.data.informatieCategorie" + }, + "3.31B" + ] + }, + { + "==": [ + { + "var": "parameters.data.informatieCategorie" + }, + "" + ] + } + ] + }, + "type": "synchronization", + "configuration": { + "force": true, + "synchronization": { + "synchronization": 3, + "retainResponse": true + }, + "error": { + "code": 500, + "name": "Something went wrong", + "message": "We encountered an unexpected problem", + "includeJsonLogicResult": false + }, + "authentication": { + "type": { + "label": "Basic Authentication", + "value": "basic" + }, + "users": [], + "groups": [], + "keys": [] + }, + "download": { + "fileIdPosition": 0 + }, + "upload": { + "path": "", + "allowedTypes": "", + "maxSize": 10 + }, + "locking": { + "action": "lock", + "timeout": 30 + }, + "fetch_file": { + "source": "", + "filePath": "", + "subObjectFilepath": "", + "objectIdPath": "", + "method": "", + "tags": [], + "sourceConfiguration": "\"[]\"", + "autoShare": false, + "endpoint": "", + "contentPath": "", + "originIdPath": "", + "filenamePath": "", + "fileExtension": "" + }, + "write_file": { + "filePath": "", + "fileNamePath": "", + "tags": [], + "autoShare": false + }, + "fileparts_create": { + "sizeLocation": "", + "schemaId": "", + "filenameLocation": "", + "filePartLocation": "", + "mappingId": "" + }, + "filepart_upload": { + "mappingId": "" + }, + "save_object": { + "register": "", + "schema": "", + "mapping": "" + }, + "extend_external_input": { + "validate": true, + "properties": [ + { + "property": "", + "schema": "" + } + ] + }, + "extend_input": { + "items": [ + { + "property": "", + "extends": [] + } + ] + } + }, + "order": 1, + "configurations": [], + "created": "2025-09-11T07:55:02+00:00", + "updated": "2025-10-21T13:33:52+00:00", + "slug": "sync-corsa-overige-besluiten-van-algemene-strekking" + }, + "sync-corsa-convenanten": { + "name": "Sync CORSA Convenanten", + "description": "", + "reference": "https://bct.accept.commonground.nu/", + "version": "0.0.7", + "action": "post", + "timing": "after", + "conditions": { + "or": [ + { + "==": [ + { + "var": "parameters.data.informatieCategorie" + }, + "3.32f" + ] + }, + { + "==": [ + { + "var": "parameters.data.informatieCategorie" + }, + "3.32F" + ] + }, + { + "==": [ + { + "var": "parameters.data.informatieCategorie" + }, + "" + ] + } + ] + }, + "type": "synchronization", + "configuration": { + "force": true, + "synchronization": { + "synchronization": 12, + "retainResponse": true + }, + "error": { + "code": 500, + "name": "Something went wrong", + "message": "We encountered an unexpected problem", + "includeJsonLogicResult": false + }, + "authentication": { + "type": { + "label": "Basic Authentication", + "value": "basic" + }, + "users": [], + "groups": [], + "keys": [] + }, + "download": { + "fileIdPosition": 0 + }, + "upload": { + "path": "", + "allowedTypes": "", + "maxSize": 10 + }, + "locking": { + "action": "lock", + "timeout": 30 + }, + "fetch_file": { + "source": "", + "filePath": "", + "subObjectFilepath": "", + "objectIdPath": "", + "method": "", + "tags": [], + "sourceConfiguration": "\"[]\"", + "autoShare": false, + "endpoint": "", + "contentPath": "", + "originIdPath": "", + "filenamePath": "", + "fileExtension": "" + }, + "write_file": { + "filePath": "", + "fileNamePath": "", + "tags": [], + "autoShare": false + }, + "fileparts_create": { + "sizeLocation": "", + "schemaId": "", + "filenameLocation": "", + "filePartLocation": "", + "mappingId": "" + }, + "filepart_upload": { + "mappingId": "" + }, + "save_object": { + "register": "", + "schema": "", + "mapping": "" + }, + "extend_external_input": { + "validate": true, + "properties": [ + { + "property": "", + "schema": "" + } + ] + }, + "extend_input": { + "items": [ + { + "property": "", + "extends": [] + } + ] + } + }, + "order": 1, + "configurations": [], + "created": "2025-09-11T07:55:02+00:00", + "updated": "2025-10-21T13:34:02+00:00", + "slug": "sync-corsa-convenanten" + }, + "sync-corsa-wetten-en-algemeen-verbindende-voorschriften": { + "name": "Sync CORSA Wetten en algemeen verbindende voorschriften", + "description": "", + "reference": "https://bct.accept.commonground.nu/", + "version": "0.0.7", + "action": "post", + "timing": "after", + "conditions": { + "or": [ + { + "==": [ + { + "var": "parameters.data.informatieCategorie" + }, + "3.31a" + ] + }, + { + "==": [ + { + "var": "parameters.data.informatieCategorie" + }, + "3.31A" + ] + }, + { + "==": [ + { + "var": "parameters.data.informatieCategorie" + }, + "" + ] + } + ] + }, + "type": "synchronization", + "configuration": { + "force": true, + "synchronization": { + "synchronization": 2, + "retainResponse": true + }, + "error": { + "code": 500, + "name": "Something went wrong", + "message": "We encountered an unexpected problem", + "includeJsonLogicResult": false + }, + "authentication": { + "type": { + "label": "Basic Authentication", + "value": "basic" + }, + "users": [], + "groups": [], + "keys": [] + }, + "download": { + "fileIdPosition": 0 + }, + "upload": { + "path": "", + "allowedTypes": "", + "maxSize": 10 + }, + "locking": { + "action": "lock", + "timeout": 30 + }, + "fetch_file": { + "source": "", + "filePath": "", + "subObjectFilepath": "", + "objectIdPath": "", + "method": "", + "tags": [], + "sourceConfiguration": "\"[]\"", + "autoShare": false, + "endpoint": "", + "contentPath": "", + "originIdPath": "", + "filenamePath": "", + "fileExtension": "" + }, + "write_file": { + "filePath": "", + "fileNamePath": "", + "tags": [], + "autoShare": false + }, + "fileparts_create": { + "sizeLocation": "", + "schemaId": "", + "filenameLocation": "", + "filePartLocation": "", + "mappingId": "" + }, + "filepart_upload": { + "mappingId": "" + }, + "save_object": { + "register": "", + "schema": "", + "mapping": "" + }, + "extend_external_input": { + "validate": true, + "properties": [ + { + "property": "", + "schema": "" + } + ] + }, + "extend_input": { + "items": [ + { + "property": "", + "extends": [] + } + ] + } + }, + "order": 1, + "configurations": [], + "created": "2025-09-11T07:55:02+00:00", + "updated": "2025-10-21T13:34:10+00:00", + "slug": "sync-corsa-wetten-en-algemeen-verbindende-voorschriften" + }, + "delete-corsa-openwoo-app": { + "name": "Delete Corsa -> OpenWoo.app", + "description": "", + "reference": null, + "version": "0.0.4", + "action": "post", + "timing": "after", + "conditions": { + "or": [ + { + "!!": { + "var": "parameters.data.deletedBy" + } + }, + { + "!!": { + "var": "data.deletedBy" + } + } + ] + }, + "type": "synchronization", + "configuration": { + "synchronization": { + "synchronization": 18, + "retainResponse": true + } + }, + "order": 3, + "configurations": [], + "created": "2025-10-09T14:19:50+00:00", + "updated": "2025-11-11T10:26:43+00:00", + "slug": "delete-corsa-openwoo-app" + } + }, + "endpoints": { + "create-cloudevent": { + "name": "Create CloudEvent", + "description": "", + "reference": "https://bct.accept.commonground.nu/apps/openconnector/api/endpoints/2", + "version": "0.0.1", + "endpoint": "cloudevents/events", + "endpointArray": [ + "cloudevents", + "events" + ], + "endpointRegex": "#^cloudevents/events$#", + "method": "POST", + "targetType": "register/schema", + "targetId": "cloudevents/cloudevent", + "conditions": [], + "inputMapping": null, + "outputMapping": null, + "rules": [ + "cloudevent-to-corsa-soap", + "sync-corsa", + "bct-auth", + "sync-corsa-klachtoordelen", + "sync-corsa-beschikkingen", + "sync-corsa-onderzoeksrapporten", + "sync-corsa-subsidieverplichtingen-anders-dan-met-beschikking", + "sync-corsa-jaarplannen-en-jaarverslagen", + "sync-corsa-agendas-en-besluitenlijsten-bestuurscolleges", + "sync-corsa-adviezen", + "sync-corsa-vergaderstukken-decentrale-overheden", + "sync-corsa-vergaderstukken-staten-generaal", + "sync-corsa-bij-vertegenwoordigende-organen-ingekomen-stukken", + "sync-corsa-bereikbaarheidsgegevens", + "sync-corsa-organisatie-en-werkwijze", + "sync-corsa-ontwerpen-van-wet-en-regelgeving-met-adviesaanvraag", + "sync-corsa-overige-besluiten-van-algemene-strekking", + "sync-corsa-convenanten", + "sync-corsa-wetten-en-algemeen-verbindende-voorschriften" + ], + "configurations": [], + "slug": "create-cloudevent", + "created": "2025-06-12T08:35:16+00:00", + "updated": "2025-10-09T14:20:04+00:00" + } + }, + "synchronizations": { + "sync-corsa": { + "name": "Sync Corsa Woo-verzoeken en -besluiten", + "description": "", + "reference": "https://bct.accept.commonground.nu/apps/openconnector/api/synchronizations/1", + "version": "0.0.16", + "sourceId": "bct-corsa-mockservice", + "sourceType": "api", + "sourceHash": "", + "sourceHashMapping": "", + "sourceTargetMapping": "corsa-to-woo-verzoeken-en-besluiten", + "sourceConfig": { + "idPosition": "poststuk_id", + "resultsPosition": "QueryExecute2Result", + "endpoint": "QueryExecute2", + "headers": [], + "query": [], + "useDataAsRequestBody": "soap", + "usesPagination": "false", + "restrictDeletion": "1" + }, + "sourceLastChanged": "2025-07-01T08:17:11+00:00", + "sourceLastChecked": "2025-07-01T08:17:11+00:00", + "sourceLastSynced": "2025-07-01T08:17:11+00:00", + "currentPage": 1, + "targetId": "woo/woo_verzoeken_en_besluiten", + "targetType": "register/schema", + "targetHash": "", + "targetSourceMapping": "1", + "targetConfig": [], + "targetLastChanged": "2025-07-01T08:17:11+00:00", + "targetLastChecked": "2025-07-01T08:17:11+00:00", + "targetLastSynced": "2025-09-09T07:57:47+00:00", + "created": "2025-07-01T08:17:11+00:00", + "updated": "2025-10-09T14:30:29+00:00", + "conditions": { + "==": [ + 1, + 1 + ] + }, + "followUps": [], + "actions": [ + "fetch-anonymized-file-from-bct", + "fetch-archived-file-from-bct" + ], + "configurations": [], + "status": null, + "slug": "sync-corsa" + }, + "sync-corsa-wetten-en-algemeen-verbindende-voorschriften": { + "name": "Sync Corsa Wetten en algemeen verbindende voorschriften", + "description": "", + "reference": "https://bct.accept.commonground.nu/apps/openconnector/api/synchronizations/2", + "version": "0.0.17", + "sourceId": "bct-corsa-mockservice", + "sourceType": "api", + "sourceHash": "", + "sourceHashMapping": "", + "sourceTargetMapping": "corsa-to-woo-verzoeken-en-besluiten", + "sourceConfig": { + "idPosition": "poststuk_id", + "resultsPosition": "QueryExecute2Result", + "endpoint": "QueryExecute2", + "headers": [], + "query": [], + "useDataAsRequestBody": "soap", + "usesPagination": "false", + "restrictDeletion": "1" + }, + "sourceLastChanged": "2025-07-01T08:17:11+00:00", + "sourceLastChecked": "2025-07-01T08:17:11+00:00", + "sourceLastSynced": "2025-07-01T08:17:11+00:00", + "currentPage": 1, + "targetId": "woo/wetten_en_algemeen_verbindende_voorschriften", + "targetType": "register/schema", + "targetHash": "", + "targetSourceMapping": "1", + "targetConfig": [], + "targetLastChanged": "2025-07-01T08:17:11+00:00", + "targetLastChecked": "2025-07-01T08:17:11+00:00", + "targetLastSynced": "2025-08-21T07:30:09+00:00", + "created": "2025-08-26T11:47:20+00:00", + "updated": "2025-10-09T14:30:52+00:00", + "conditions": { + "==": [ + 1, + 1 + ] + }, + "followUps": [], + "actions": [ + "fetch-anonymized-file-from-bct", + "fetch-archived-file-from-bct" + ], + "configurations": [], + "status": null, + "slug": "sync-corsa-wetten-en-algemeen-verbindende-voorschriften" + }, + "sync-corsa-overige-besluiten-van-algemene-strekking": { + "name": "Sync Corsa Overige besluiten van algemene strekking", + "description": "", + "reference": "https://bct.accept.commonground.nu/apps/openconnector/api/synchronizations/3", + "version": "0.0.16", + "sourceId": "bct-corsa-mockservice", + "sourceType": "api", + "sourceHash": "", + "sourceHashMapping": "", + "sourceTargetMapping": "corsa-to-woo-verzoeken-en-besluiten", + "sourceConfig": { + "idPosition": "poststuk_id", + "resultsPosition": "QueryExecute2Result", + "endpoint": "QueryExecute2", + "headers": [], + "query": [], + "useDataAsRequestBody": "soap", + "usesPagination": "false", + "restrictDeletion": "1" + }, + "sourceLastChanged": "2025-07-01T08:17:11+00:00", + "sourceLastChecked": "2025-07-01T08:17:11+00:00", + "sourceLastSynced": "2025-07-01T08:17:11+00:00", + "currentPage": 1, + "targetId": "woo/overige_besluiten_van_algemene_strekking", + "targetType": "register/schema", + "targetHash": "", + "targetSourceMapping": "1", + "targetConfig": [], + "targetLastChanged": "2025-07-01T08:17:11+00:00", + "targetLastChecked": "2025-07-01T08:17:11+00:00", + "targetLastSynced": "2025-08-21T07:30:09+00:00", + "created": "2025-08-26T11:48:23+00:00", + "updated": "2025-10-09T14:31:16+00:00", + "conditions": { + "==": [ + 1, + 1 + ] + }, + "followUps": [], + "actions": [ + "fetch-anonymized-file-from-bct", + "fetch-archived-file-from-bct" + ], + "configurations": [], + "status": null, + "slug": "sync-corsa-overige-besluiten-van-algemene-strekking" + }, + "sync-corsa-ontwerpen-van-wet-en-regelgeving-met-adviesaanvraag": { + "name": "Sync Corsa Ontwerpen van wet- en regelgeving met adviesaanvraag", + "description": "", + "reference": "https://bct.accept.commonground.nu/apps/openconnector/api/synchronizations/4", + "version": "0.0.16", + "sourceId": "bct-corsa-mockservice", + "sourceType": "api", + "sourceHash": "", + "sourceHashMapping": "", + "sourceTargetMapping": "corsa-to-woo-verzoeken-en-besluiten", + "sourceConfig": { + "idPosition": "poststuk_id", + "resultsPosition": "QueryExecute2Result", + "endpoint": "QueryExecute2", + "headers": [], + "query": [], + "useDataAsRequestBody": "soap", + "usesPagination": "false", + "restrictDeletion": "1" + }, + "sourceLastChanged": "2025-07-01T08:17:11+00:00", + "sourceLastChecked": "2025-07-01T08:17:11+00:00", + "sourceLastSynced": "2025-07-01T08:17:11+00:00", + "currentPage": 1, + "targetId": "woo/ontwerpen_van_wet_en_regelgeving_met_adviesaanvraag", + "targetType": "register/schema", + "targetHash": "", + "targetSourceMapping": "1", + "targetConfig": [], + "targetLastChanged": "2025-07-01T08:17:11+00:00", + "targetLastChecked": "2025-07-01T08:17:11+00:00", + "targetLastSynced": "2025-08-21T07:30:09+00:00", + "created": "2025-08-26T11:48:49+00:00", + "updated": "2025-10-09T14:31:34+00:00", + "conditions": { + "==": [ + 1, + 1 + ] + }, + "followUps": [], + "actions": [ + "fetch-anonymized-file-from-bct", + "fetch-archived-file-from-bct" + ], + "configurations": [], + "status": null, + "slug": "sync-corsa-ontwerpen-van-wet-en-regelgeving-met-adviesaanvraag" + }, + "sync-corsa-organisatie-en-werkwijze": { + "name": "Sync Corsa Organisatie en werkwijze", + "description": "", + "reference": "https://bct.accept.commonground.nu/apps/openconnector/api/synchronizations/5", + "version": "0.0.16", + "sourceId": "bct-corsa-mockservice", + "sourceType": "api", + "sourceHash": "", + "sourceHashMapping": "", + "sourceTargetMapping": "corsa-to-woo-verzoeken-en-besluiten", + "sourceConfig": { + "idPosition": "poststuk_id", + "resultsPosition": "QueryExecute2Result", + "endpoint": "QueryExecute2", + "headers": [], + "query": [], + "useDataAsRequestBody": "soap", + "usesPagination": "false", + "restrictDeletion": "1" + }, + "sourceLastChanged": "2025-07-01T08:17:11+00:00", + "sourceLastChecked": "2025-07-01T08:17:11+00:00", + "sourceLastSynced": "2025-07-01T08:17:11+00:00", + "currentPage": 1, + "targetId": "woo/organisatie_en_werkwijze", + "targetType": "register/schema", + "targetHash": "", + "targetSourceMapping": "1", + "targetConfig": [], + "targetLastChanged": "2025-07-01T08:17:11+00:00", + "targetLastChecked": "2025-07-01T08:17:11+00:00", + "targetLastSynced": "2025-08-21T07:30:09+00:00", + "created": "2025-08-26T11:50:13+00:00", + "updated": "2025-10-09T14:31:45+00:00", + "conditions": { + "==": [ + 1, + 1 + ] + }, + "followUps": [], + "actions": [ + "fetch-anonymized-file-from-bct", + "fetch-archived-file-from-bct" + ], + "configurations": [], + "status": null, + "slug": "sync-corsa-organisatie-en-werkwijze" + }, + "sync-corsa-bereikbaarheidsgegevens": { + "name": "Sync Corsa Bereikbaarheidsgegevens", + "description": "", + "reference": "https://bct.accept.commonground.nu/apps/openconnector/api/synchronizations/6", + "version": "0.0.16", + "sourceId": "bct-corsa-mockservice", + "sourceType": "api", + "sourceHash": "", + "sourceHashMapping": "", + "sourceTargetMapping": "corsa-to-woo-verzoeken-en-besluiten", + "sourceConfig": { + "idPosition": "poststuk_id", + "resultsPosition": "QueryExecute2Result", + "endpoint": "QueryExecute2", + "headers": [], + "query": [], + "useDataAsRequestBody": "soap", + "usesPagination": "false", + "restrictDeletion": "1" + }, + "sourceLastChanged": "2025-07-01T08:17:11+00:00", + "sourceLastChecked": "2025-07-01T08:17:11+00:00", + "sourceLastSynced": "2025-07-01T08:17:11+00:00", + "currentPage": 1, + "targetId": "woo/bereikbaarheidsgegevens", + "targetType": "register/schema", + "targetHash": "", + "targetSourceMapping": "1", + "targetConfig": [], + "targetLastChanged": "2025-07-01T08:17:11+00:00", + "targetLastChecked": "2025-07-01T08:17:11+00:00", + "targetLastSynced": "2025-10-13T14:08:36+00:00", + "created": "2025-08-26T11:50:36+00:00", + "updated": "2025-10-09T14:31:55+00:00", + "conditions": { + "==": [ + 1, + 1 + ] + }, + "followUps": [], + "actions": [ + "fetch-anonymized-file-from-bct", + "fetch-archived-file-from-bct" + ], + "configurations": [], + "status": null, + "slug": "sync-corsa-bereikbaarheidsgegevens" + }, + "sync-corsa-bij-vertegenwoordigende-organen-ingekomen-stukken": { + "name": "Sync Corsa Bij vertegenwoordigende organen ingekomen stukken", + "description": "", + "reference": "https://bct.accept.commonground.nu/apps/openconnector/api/synchronizations/7", + "version": "0.0.16", + "sourceId": "bct-corsa-mockservice", + "sourceType": "api", + "sourceHash": "", + "sourceHashMapping": "", + "sourceTargetMapping": "corsa-to-woo-verzoeken-en-besluiten", + "sourceConfig": { + "idPosition": "poststuk_id", + "resultsPosition": "QueryExecute2Result", + "endpoint": "QueryExecute2", + "headers": [], + "query": [], + "useDataAsRequestBody": "soap", + "usesPagination": "false", + "restrictDeletion": "1" + }, + "sourceLastChanged": "2025-07-01T08:17:11+00:00", + "sourceLastChecked": "2025-07-01T08:17:11+00:00", + "sourceLastSynced": "2025-07-01T08:17:11+00:00", + "currentPage": 1, + "targetId": "woo/bij-vertegenwoordigende-organen-ingekomen-stukken", + "targetType": "register/schema", + "targetHash": "", + "targetSourceMapping": "1", + "targetConfig": [], + "targetLastChanged": "2025-07-01T08:17:11+00:00", + "targetLastChecked": "2025-07-01T08:17:11+00:00", + "targetLastSynced": "2025-08-21T07:30:09+00:00", + "created": "2025-08-26T11:50:51+00:00", + "updated": "2025-10-09T14:32:08+00:00", + "conditions": { + "==": [ + 1, + 1 + ] + }, + "followUps": [], + "actions": [ + "fetch-anonymized-file-from-bct", + "fetch-archived-file-from-bct" + ], + "configurations": [], + "status": null, + "slug": "sync-corsa-bij-vertegenwoordigende-organen-ingekomen-stukken" + }, + "sync-corsa-vergaderstukken-staten-generaal": { + "name": "Sync Corsa Vergaderstukken Staten-Generaal", + "description": "", + "reference": "https://bct.accept.commonground.nu/apps/openconnector/api/synchronizations/8", + "version": "0.0.16", + "sourceId": "bct-corsa-mockservice", + "sourceType": "api", + "sourceHash": "", + "sourceHashMapping": "", + "sourceTargetMapping": "corsa-to-woo-verzoeken-en-besluiten", + "sourceConfig": { + "idPosition": "poststuk_id", + "resultsPosition": "QueryExecute2Result", + "endpoint": "QueryExecute2", + "headers": [], + "query": [], + "useDataAsRequestBody": "soap", + "usesPagination": "false", + "restrictDeletion": "1" + }, + "sourceLastChanged": "2025-07-01T08:17:11+00:00", + "sourceLastChecked": "2025-07-01T08:17:11+00:00", + "sourceLastSynced": "2025-07-01T08:17:11+00:00", + "currentPage": 1, + "targetId": "woo/vergaderstukken_staten_generaal", + "targetType": "register/schema", + "targetHash": "", + "targetSourceMapping": "1", + "targetConfig": [], + "targetLastChanged": "2025-07-01T08:17:11+00:00", + "targetLastChecked": "2025-07-01T08:17:11+00:00", + "targetLastSynced": "2025-08-21T07:30:09+00:00", + "created": "2025-08-26T11:51:13+00:00", + "updated": "2025-10-09T14:32:26+00:00", + "conditions": { + "==": [ + 1, + 1 + ] + }, + "followUps": [], + "actions": [ + "fetch-anonymized-file-from-bct", + "fetch-archived-file-from-bct" + ], + "configurations": [], + "status": null, + "slug": "sync-corsa-vergaderstukken-staten-generaal" + }, + "sync-corsa-vergaderstukken-decentrale-overheden": { + "name": "Sync Corsa Vergaderstukken decentrale overheden", + "description": "", + "reference": "https://bct.accept.commonground.nu/apps/openconnector/api/synchronizations/9", + "version": "0.0.16", + "sourceId": "bct-corsa-mockservice", + "sourceType": "api", + "sourceHash": "", + "sourceHashMapping": "", + "sourceTargetMapping": "corsa-to-woo-verzoeken-en-besluiten", + "sourceConfig": { + "idPosition": "poststuk_id", + "resultsPosition": "QueryExecute2Result", + "endpoint": "QueryExecute2", + "headers": [], + "query": [], + "useDataAsRequestBody": "soap", + "usesPagination": "false", + "restrictDeletion": "1" + }, + "sourceLastChanged": "2025-07-01T08:17:11+00:00", + "sourceLastChecked": "2025-07-01T08:17:11+00:00", + "sourceLastSynced": "2025-07-01T08:17:11+00:00", + "currentPage": 1, + "targetId": "woo/vergaderstukken_decentrale_overheden", + "targetType": "register/schema", + "targetHash": "", + "targetSourceMapping": "1", + "targetConfig": [], + "targetLastChanged": "2025-07-01T08:17:11+00:00", + "targetLastChecked": "2025-07-01T08:17:11+00:00", + "targetLastSynced": "2025-08-21T07:30:09+00:00", + "created": "2025-08-26T11:51:33+00:00", + "updated": "2025-10-09T14:32:40+00:00", + "conditions": { + "==": [ + 1, + 1 + ] + }, + "followUps": [], + "actions": [ + "fetch-anonymized-file-from-bct", + "fetch-archived-file-from-bct" + ], + "configurations": [], + "status": null, + "slug": "sync-corsa-vergaderstukken-decentrale-overheden" + }, + "sync-corsa-agenda-s-en-besluitenlijsten-bestuurscolleges": { + "name": "Sync Corsa Agenda's en besluitenlijsten bestuurscolleges", + "description": "", + "reference": "https://bct.accept.commonground.nu/apps/openconnector/api/synchronizations/10", + "version": "0.0.16", + "sourceId": "bct-corsa-mockservice", + "sourceType": "api", + "sourceHash": "", + "sourceHashMapping": "", + "sourceTargetMapping": "corsa-to-woo-verzoeken-en-besluiten", + "sourceConfig": { + "idPosition": "poststuk_id", + "resultsPosition": "QueryExecute2Result", + "endpoint": "QueryExecute2", + "headers": [], + "query": [], + "useDataAsRequestBody": "soap", + "usesPagination": "false", + "restrictDeletion": "1" + }, + "sourceLastChanged": "2025-07-01T08:17:11+00:00", + "sourceLastChecked": "2025-07-01T08:17:11+00:00", + "sourceLastSynced": "2025-07-01T08:17:11+00:00", + "currentPage": 1, + "targetId": "woo/agendas_en_besluitenlijsten_bestuurscolleges", + "targetType": "register/schema", + "targetHash": "", + "targetSourceMapping": "1", + "targetConfig": [], + "targetLastChanged": "2025-07-01T08:17:11+00:00", + "targetLastChecked": "2025-07-01T08:17:11+00:00", + "targetLastSynced": "2025-08-21T07:30:09+00:00", + "created": "2025-08-26T11:52:00+00:00", + "updated": "2025-10-09T14:32:50+00:00", + "conditions": { + "==": [ + 1, + 1 + ] + }, + "followUps": [], + "actions": [ + "fetch-anonymized-file-from-bct", + "fetch-archived-file-from-bct" + ], + "configurations": [], + "status": null, + "slug": "sync-corsa-agenda-s-en-besluitenlijsten-bestuurscolleges" + }, + "sync-corsa-adviezen": { + "name": "Sync Corsa Adviezen", + "description": "", + "reference": "https://bct.accept.commonground.nu/apps/openconnector/api/synchronizations/11", + "version": "0.0.16", + "sourceId": "bct-corsa-mockservice", + "sourceType": "api", + "sourceHash": "", + "sourceHashMapping": "", + "sourceTargetMapping": "corsa-to-woo-verzoeken-en-besluiten", + "sourceConfig": { + "idPosition": "poststuk_id", + "resultsPosition": "QueryExecute2Result", + "endpoint": "QueryExecute2", + "headers": [], + "query": [], + "useDataAsRequestBody": "soap", + "usesPagination": "false", + "restrictDeletion": "1" + }, + "sourceLastChanged": "2025-07-01T08:17:11+00:00", + "sourceLastChecked": "2025-07-01T08:17:11+00:00", + "sourceLastSynced": "2025-07-01T08:17:11+00:00", + "currentPage": 1, + "targetId": "woo/adviezen", + "targetType": "register/schema", + "targetHash": "", + "targetSourceMapping": "1", + "targetConfig": [], + "targetLastChanged": "2025-07-01T08:17:11+00:00", + "targetLastChecked": "2025-07-01T08:17:11+00:00", + "targetLastSynced": "2025-10-13T15:05:17+00:00", + "created": "2025-08-26T11:52:21+00:00", + "updated": "2025-10-09T14:32:59+00:00", + "conditions": { + "==": [ + 1, + 1 + ] + }, + "followUps": [], + "actions": [ + "fetch-anonymized-file-from-bct", + "fetch-archived-file-from-bct" + ], + "configurations": [], + "status": null, + "slug": "sync-corsa-adviezen" + }, + "sync-corsa-convenanten": { + "name": "Sync Corsa Convenanten", + "description": "", + "reference": "https://bct.accept.commonground.nu/apps/openconnector/api/synchronizations/12", + "version": "0.0.16", + "sourceId": "bct-corsa-mockservice", + "sourceType": "api", + "sourceHash": "", + "sourceHashMapping": "", + "sourceTargetMapping": "corsa-to-woo-verzoeken-en-besluiten", + "sourceConfig": { + "idPosition": "poststuk_id", + "resultsPosition": "QueryExecute2Result", + "endpoint": "QueryExecute2", + "headers": [], + "query": [], + "useDataAsRequestBody": "soap", + "usesPagination": "false", + "restrictDeletion": "1" + }, + "sourceLastChanged": "2025-07-01T08:17:11+00:00", + "sourceLastChecked": "2025-07-01T08:17:11+00:00", + "sourceLastSynced": "2025-07-01T08:17:11+00:00", + "currentPage": 1, + "targetId": "woo/convenant", + "targetType": "register/schema", + "targetHash": "", + "targetSourceMapping": "1", + "targetConfig": [], + "targetLastChanged": "2025-07-01T08:17:11+00:00", + "targetLastChecked": "2025-07-01T08:17:11+00:00", + "targetLastSynced": "2025-10-21T12:18:06+00:00", + "created": "2025-08-26T11:52:40+00:00", + "updated": "2025-10-09T14:33:07+00:00", + "conditions": { + "==": [ + 1, + 1 + ] + }, + "followUps": [], + "actions": [ + "fetch-anonymized-file-from-bct", + "fetch-archived-file-from-bct" + ], + "configurations": [], + "status": null, + "slug": "sync-corsa-convenanten" + }, + "sync-corsa-jaarplannen-en-jaarverslagen": { + "name": "Sync Corsa Jaarplannen en jaarverslagen", + "description": "", + "reference": "https://bct.accept.commonground.nu/apps/openconnector/api/synchronizations/13", + "version": "0.0.16", + "sourceId": "bct-corsa-mockservice", + "sourceType": "api", + "sourceHash": "", + "sourceHashMapping": "", + "sourceTargetMapping": "corsa-to-woo-verzoeken-en-besluiten", + "sourceConfig": { + "idPosition": "poststuk_id", + "resultsPosition": "QueryExecute2Result", + "endpoint": "QueryExecute2", + "headers": [], + "query": [], + "useDataAsRequestBody": "soap", + "usesPagination": "false", + "restrictDeletion": "1" + }, + "sourceLastChanged": "2025-07-01T08:17:11+00:00", + "sourceLastChecked": "2025-07-01T08:17:11+00:00", + "sourceLastSynced": "2025-07-01T08:17:11+00:00", + "currentPage": 1, + "targetId": "woo/jaarplan-of-jaarverslag", + "targetType": "register/schema", + "targetHash": "", + "targetSourceMapping": "1", + "targetConfig": [], + "targetLastChanged": "2025-07-01T08:17:11+00:00", + "targetLastChecked": "2025-07-01T08:17:11+00:00", + "targetLastSynced": "2025-08-21T07:30:09+00:00", + "created": "2025-08-26T11:53:01+00:00", + "updated": "2025-10-09T14:33:18+00:00", + "conditions": { + "==": [ + 1, + 1 + ] + }, + "followUps": [], + "actions": [ + "fetch-anonymized-file-from-bct", + "fetch-archived-file-from-bct" + ], + "configurations": [], + "status": null, + "slug": "sync-corsa-jaarplannen-en-jaarverslagen" + }, + "sync-corsa-subsidieverplichtingen-anders-dan-met-beschikking": { + "name": "Sync Corsa Subsidieverplichtingen anders dan met beschikking", + "description": "", + "reference": "https://bct.accept.commonground.nu/apps/openconnector/api/synchronizations/14", + "version": "0.0.18", + "sourceId": "bct-corsa-mockservice", + "sourceType": "api", + "sourceHash": "", + "sourceHashMapping": "", + "sourceTargetMapping": "corsa-to-woo-verzoeken-en-besluiten", + "sourceConfig": { + "idPosition": "poststuk_id", + "resultsPosition": "QueryExecute2Result", + "endpoint": "QueryExecute2", + "headers": [], + "query": [], + "useDataAsRequestBody": "soap", + "usesPagination": "false", + "restrictDeletion": "1" + }, + "sourceLastChanged": "2025-07-01T08:17:11+00:00", + "sourceLastChecked": "2025-07-01T08:17:11+00:00", + "sourceLastSynced": "2025-07-01T08:17:11+00:00", + "currentPage": 1, + "targetId": "woo/subsidieverplichtingen_anders_dan_met_beschikking", + "targetType": "register/schema", + "targetHash": "", + "targetSourceMapping": "1", + "targetConfig": [], + "targetLastChanged": "2025-07-01T08:17:11+00:00", + "targetLastChecked": "2025-07-01T08:17:11+00:00", + "targetLastSynced": "2025-08-21T07:30:09+00:00", + "created": "2025-08-26T11:53:29+00:00", + "updated": "2025-10-09T14:33:26+00:00", + "conditions": { + "==": [ + 1, + 1 + ] + }, + "followUps": [], + "actions": [ + "fetch-anonymized-file-from-bct", + "fetch-archived-file-from-bct" + ], + "configurations": [], + "status": null, + "slug": "sync-corsa-subsidieverplichtingen-anders-dan-met-beschikking" + }, + "sync-corsa-onderzoeksrapporten": { + "name": "Sync Corsa Onderzoeksrapporten", + "description": "", + "reference": "https://bct.accept.commonground.nu/apps/openconnector/api/synchronizations/15", + "version": "0.0.17", + "sourceId": "bct-corsa-mockservice", + "sourceType": "api", + "sourceHash": "", + "sourceHashMapping": "", + "sourceTargetMapping": "corsa-to-woo-verzoeken-en-besluiten", + "sourceConfig": { + "idPosition": "poststuk_id", + "resultsPosition": "QueryExecute2Result", + "endpoint": "QueryExecute2", + "headers": [], + "query": [], + "useDataAsRequestBody": "soap", + "usesPagination": "false", + "restrictDeletion": "1" + }, + "sourceLastChanged": "2025-07-01T08:17:11+00:00", + "sourceLastChecked": "2025-07-01T08:17:11+00:00", + "sourceLastSynced": "2025-07-01T08:17:11+00:00", + "currentPage": 1, + "targetId": "woo/onderzoeksrapporten", + "targetType": "register/schema", + "targetHash": "", + "targetSourceMapping": "1", + "targetConfig": [], + "targetLastChanged": "2025-07-01T08:17:11+00:00", + "targetLastChecked": "2025-07-01T08:17:11+00:00", + "targetLastSynced": "2025-08-21T07:30:09+00:00", + "created": "2025-08-26T11:54:16+00:00", + "updated": "2025-10-09T14:33:36+00:00", + "conditions": { + "==": [ + 1, + 1 + ] + }, + "followUps": [], + "actions": [ + "fetch-anonymized-file-from-bct", + "fetch-archived-file-from-bct" + ], + "configurations": [], + "status": null, + "slug": "sync-corsa-onderzoeksrapporten" + }, + "sync-corsa-beschikkingen": { + "name": "Sync Corsa Beschikkingen", + "description": "", + "reference": "https://bct.accept.commonground.nu/apps/openconnector/api/synchronizations/16", + "version": "0.0.16", + "sourceId": "bct-corsa-mockservice", + "sourceType": "api", + "sourceHash": "", + "sourceHashMapping": "", + "sourceTargetMapping": "corsa-to-woo-verzoeken-en-besluiten", + "sourceConfig": { + "idPosition": "poststuk_id", + "resultsPosition": "QueryExecute2Result", + "endpoint": "QueryExecute2", + "headers": [], + "query": [], + "useDataAsRequestBody": "soap", + "usesPagination": "false", + "restrictDeletion": "1" + }, + "sourceLastChanged": "2025-07-01T08:17:11+00:00", + "sourceLastChecked": "2025-07-01T08:17:11+00:00", + "sourceLastSynced": "2025-07-01T08:17:11+00:00", + "currentPage": 1, + "targetId": "woo/beschikkingen", + "targetType": "register/schema", + "targetHash": "", + "targetSourceMapping": "1", + "targetConfig": [], + "targetLastChanged": "2025-07-01T08:17:11+00:00", + "targetLastChecked": "2025-07-01T08:17:11+00:00", + "targetLastSynced": "2025-10-23T14:12:39+00:00", + "created": "2025-08-26T11:54:36+00:00", + "updated": "2025-10-09T14:33:46+00:00", + "conditions": { + "==": [ + 1, + 1 + ] + }, + "followUps": [], + "actions": [ + "fetch-anonymized-file-from-bct", + "fetch-archived-file-from-bct" + ], + "configurations": [], + "status": null, + "slug": "sync-corsa-beschikkingen" + }, + "sync-corsa-klachtoordelen": { + "name": "Sync Corsa Klachtoordelen", + "description": "", + "reference": "https://bct.accept.commonground.nu/apps/openconnector/api/synchronizations/17", + "version": "0.0.16", + "sourceId": "bct-corsa-mockservice", + "sourceType": "api", + "sourceHash": "", + "sourceHashMapping": "", + "sourceTargetMapping": "corsa-to-woo-verzoeken-en-besluiten", + "sourceConfig": { + "idPosition": "poststuk_id", + "resultsPosition": "QueryExecute2Result", + "endpoint": "QueryExecute2", + "headers": [], + "query": [], + "useDataAsRequestBody": "soap", + "usesPagination": "false", + "restrictDeletion": "1" + }, + "sourceLastChanged": "2025-07-01T08:17:11+00:00", + "sourceLastChecked": "2025-07-01T08:17:11+00:00", + "sourceLastSynced": "2025-07-01T08:17:11+00:00", + "currentPage": 1, + "targetId": "woo/klachtoordelen", + "targetType": "register/schema", + "targetHash": "", + "targetSourceMapping": "1", + "targetConfig": [], + "targetLastChanged": "2025-07-01T08:17:11+00:00", + "targetLastChecked": "2025-07-01T08:17:11+00:00", + "targetLastSynced": "2025-09-11T09:57:54+00:00", + "created": "2025-08-26T11:54:58+00:00", + "updated": "2025-10-09T14:33:56+00:00", + "conditions": { + "==": [ + 1, + 1 + ] + }, + "followUps": [], + "actions": [ + "fetch-anonymized-file-from-bct", + "fetch-archived-file-from-bct" + ], + "configurations": [], + "status": null, + "slug": "sync-corsa-klachtoordelen" + }, + "delete-corsa-openwoo-app": { + "name": "Delete Corsa -> OpenWoo.app", + "description": "This sync can delete objects from all woo schemas", + "reference": null, + "version": "0.0.3", + "sourceId": "bct-corsa-mockservice", + "sourceType": "api", + "sourceHash": "", + "sourceHashMapping": "", + "sourceTargetMapping": "1", + "sourceConfig": { + "idPosition": "data.documentId", + "resultsPosition": "", + "endpoint": "", + "headers": [], + "query": [], + "findContractByOriginIdOnly": "true", + "synchronizationType": "delete" + }, + "sourceLastChanged": "2025-10-09T13:03:31+00:00", + "sourceLastChecked": "2025-10-09T13:03:31+00:00", + "sourceLastSynced": "2025-10-09T13:03:31+00:00", + "currentPage": 1, + "targetId": "woo/woo_verzoeken_en_besluiten", + "targetType": "register/schema", + "targetHash": "", + "targetSourceMapping": "1", + "targetConfig": [], + "targetLastChanged": "2025-10-09T13:03:31+00:00", + "targetLastChecked": "2025-10-09T13:03:31+00:00", + "targetLastSynced": "2025-10-23T11:09:45+00:00", + "created": "2025-10-09T13:03:31+00:00", + "updated": "2025-10-09T14:20:43+00:00", + "conditions": { + "!!": { + "var": "data.deletedBy" + } + }, + "followUps": [], + "actions": [], + "configurations": [], + "status": null, + "slug": "delete-corsa-openwoo-app" + } + }, + "jobs": [], + "registers": { + "cloudevents": { + "slug": "cloudevents", + "title": "CloudEvents", + "version": "0.0.1", + "description": "", + "schemas": [ + "cloudevent" + ], + "source": "internal", + "tablePrefix": "", + "folder": "581", + "updated": "2025-06-12T08:33:53+00:00", + "created": "2025-06-12T08:33:53+00:00", + "owner": null, + "application": null, + "organisation": null, + "authorization": null, + "groups": null, + "deleted": null + } + }, + "schemas": { + "cloudevent": { + "uri": null, + "slug": "cloudevent", + "title": "CloudEvent", + "description": "", + "version": "0.0.10", + "summary": "", + "icon": null, + "required": [ + "specversion", + "source" + ], + "properties": { + "id": { + "description": "", + "type": "string", + "format": "", + "pattern": "", + "default": "", + "behavior": "", + "required": false, + "deprecated": false, + "visible": true, + "hideOnCollection": false, + "order": null, + "minLength": null, + "maxLength": null, + "example": "", + "immutable": false, + "minimum": null, + "maximum": null, + "multipleOf": null, + "exclusiveMin": false, + "exclusiveMax": false, + "minItems": null, + "maxItems": null, + "cascadeDelete": false, + "inversedBy": "", + "$ref": "", + "objectConfiguration": { + "handling": "nested-object", + "schema": "" + }, + "fileConfiguration": { + "handling": "ignore", + "allowedMimeTypes": [], + "location": "", + "maxSize": 0 + }, + "oneOf": [] + }, + "type": { + "description": "", + "type": "string", + "format": "", + "pattern": "", + "default": "", + "behavior": "", + "required": false, + "deprecated": false, + "visible": true, + "hideOnCollection": false, + "order": null, + "minLength": null, + "maxLength": null, + "example": "", + "immutable": false, + "minimum": null, + "maximum": null, + "multipleOf": null, + "exclusiveMin": false, + "exclusiveMax": false, + "minItems": null, + "maxItems": null, + "cascadeDelete": false, + "inversedBy": "", + "$ref": "", + "objectConfiguration": { + "handling": "nested-object", + "schema": "" + }, + "fileConfiguration": { + "handling": "ignore", + "allowedMimeTypes": [], + "location": "", + "maxSize": 0 + }, + "oneOf": [] + }, + "time": { + "description": "", + "type": "string", + "format": "date-time", + "pattern": "", + "default": "", + "behavior": "", + "required": false, + "deprecated": false, + "visible": true, + "hideOnCollection": false, + "order": null, + "minLength": null, + "maxLength": null, + "example": "", + "immutable": false, + "minimum": null, + "maximum": null, + "multipleOf": null, + "exclusiveMin": false, + "exclusiveMax": false, + "minItems": null, + "maxItems": null, + "cascadeDelete": false, + "inversedBy": "", + "$ref": "", + "objectConfiguration": { + "handling": "nested-object", + "schema": "" + }, + "fileConfiguration": { + "handling": "ignore", + "allowedMimeTypes": [], + "location": "", + "maxSize": 0 + }, + "oneOf": [] + }, + "datacontenttype": { + "description": "", + "type": "string", + "format": "", + "pattern": "", + "default": "", + "behavior": "", + "required": false, + "deprecated": false, + "visible": true, + "hideOnCollection": false, + "order": null, + "minLength": null, + "maxLength": null, + "example": "", + "immutable": false, + "minimum": null, + "maximum": null, + "multipleOf": null, + "exclusiveMin": false, + "exclusiveMax": false, + "minItems": null, + "maxItems": null, + "cascadeDelete": false, + "inversedBy": "", + "$ref": "", + "objectConfiguration": { + "handling": "nested-object", + "schema": "" + }, + "fileConfiguration": { + "handling": "ignore", + "allowedMimeTypes": [], + "location": "", + "maxSize": 0 + }, + "oneOf": [] + }, + "data": { + "description": "", + "type": "object", + "format": "", + "pattern": "", + "default": "", + "behavior": "", + "required": false, + "deprecated": false, + "visible": true, + "hideOnCollection": false, + "order": null, + "minLength": null, + "maxLength": null, + "example": "", + "immutable": false, + "minimum": null, + "maximum": null, + "multipleOf": null, + "exclusiveMin": false, + "exclusiveMax": false, + "minItems": null, + "maxItems": null, + "cascadeDelete": false, + "inversedBy": "", + "$ref": "", + "objectConfiguration": { + "handling": null, + "schema": "" + }, + "fileConfiguration": { + "handling": "ignore", + "allowedMimeTypes": [], + "location": "", + "maxSize": 0 + }, + "oneOf": [] + }, + "specversion": { + "description": "", + "type": "string", + "format": "", + "pattern": "", + "default": "", + "behavior": "", + "required": true, + "deprecated": false, + "visible": true, + "hideOnCollection": false, + "order": null, + "minLength": null, + "maxLength": null, + "example": "", + "immutable": false, + "minimum": null, + "maximum": null, + "multipleOf": null, + "exclusiveMin": false, + "exclusiveMax": false, + "minItems": null, + "maxItems": null, + "cascadeDelete": false, + "inversedBy": "", + "$ref": "", + "objectConfiguration": { + "handling": "nested-object", + "schema": "" + }, + "fileConfiguration": { + "handling": "ignore", + "allowedMimeTypes": [], + "location": "", + "maxSize": 0 + }, + "oneOf": [] + }, + "source": { + "description": "", + "type": "string", + "format": "", + "pattern": "", + "default": "", + "behavior": "", + "required": true, + "deprecated": false, + "visible": true, + "hideOnCollection": false, + "order": null, + "minLength": null, + "maxLength": null, + "example": "", + "immutable": false, + "minimum": null, + "maximum": null, + "multipleOf": null, + "exclusiveMin": false, + "exclusiveMax": false, + "minItems": null, + "maxItems": null, + "cascadeDelete": false, + "inversedBy": "", + "$ref": "", + "objectConfiguration": { + "handling": "nested-object", + "schema": "" + }, + "fileConfiguration": { + "handling": "ignore", + "allowedMimeTypes": [], + "location": "", + "maxSize": 0 + }, + "oneOf": [] + } + }, + "archive": [], + "source": null, + "hardValidation": false, + "immutable": false, + "searchable": true, + "updated": "2025-06-12T08:47:56+00:00", + "created": "2025-06-12T08:24:42+00:00", + "maxDepth": 0, + "owner": null, + "application": null, + "organisation": null, + "groups": null, + "authorization": null, + "deleted": null, + "configuration": null + } + }, + "objects": [] + }, + "openapi": "3.0.0", + "info": { + "id": 2, + "title": "CloudEvents", + "description": "", + "version": "0.0.1" + } +} \ No newline at end of file