├── .github ├── CODEOWNERS └── workflows │ └── codeql.yml ├── .rspec ├── .yardopts ├── spec ├── fixtures │ ├── pixel.jpg │ ├── json_responses │ │ ├── other_error_nothing.json │ │ ├── default_400.json │ │ ├── default_404.json │ │ ├── default_409.json │ │ ├── default_502.json │ │ ├── default_401.json │ │ ├── default_403.json │ │ ├── default_500.json │ │ ├── default_422.json │ │ ├── default_429.json │ │ ├── default_503.json │ │ ├── 400_details_string.json │ │ ├── other_error_no_message.json │ │ ├── other_error_no_request_id.json │ │ ├── other_error_no_details.json │ │ ├── 404_details_string.json │ │ ├── 404_type.json │ │ ├── other_error.json │ │ ├── 404_id.json │ │ ├── 400_details_errors_string.json │ │ ├── 403_reasons.json │ │ ├── 400_details_errors_object.json │ │ ├── not_found.json │ │ ├── unparsable.json │ │ └── 422_details.json │ └── vcr_cassettes │ │ ├── delete_request.yml │ │ ├── put_request.yml │ │ ├── get_request.yml │ │ ├── entry │ │ ├── service_unavailable.yml │ │ └── find_not_found.yml │ │ ├── asset │ │ ├── find_not_found.yml │ │ └── create_with_already_used_id.yml │ │ ├── content_type │ │ ├── find_not_found.yml │ │ ├── create_content_type_with_id.yml │ │ └── create.yml │ │ ├── space │ │ ├── find_not_found.yml │ │ ├── save_new_space.yml │ │ ├── create_when_limit_has_been_reached.yml │ │ ├── create_with_unknown_organization.yml │ │ ├── create.yml │ │ └── create_without_organization.yml │ │ ├── webhook │ │ ├── find_not_found.yml │ │ ├── create_with_taken_url.yml │ │ ├── create.yml │ │ └── find.yml │ │ ├── locale │ │ ├── find_for_space_not_found.yml │ │ ├── find.yml │ │ ├── find_default.yml │ │ └── find_not_default.yml │ │ ├── upload │ │ ├── find_not_found.yml │ │ ├── find.yml │ │ ├── create_file.yml │ │ └── create_path.yml │ │ ├── api_key │ │ └── find_for_space_not_found.yml │ │ ├── post_request.yml │ │ ├── roles │ │ └── find_for_space_not_found.yml │ │ └── taxonomy_concept │ │ └── total.yml ├── spec_helper.rb ├── support │ ├── json_responses.rb │ └── vcr.rb └── lib │ └── contentful │ └── management │ ├── space_periodic_usage_spec.rb │ ├── organization_periodic_usage_spec.rb │ ├── array_spec.rb │ ├── user_spec.rb │ ├── webhook_health_spec.rb │ └── organization_spec.rb ├── Gemfile ├── bin └── cma-console ├── lib └── contentful │ ├── management.rb │ └── management │ ├── version.rb │ ├── resource │ ├── entry_fields.rb │ ├── asset_fields.rb │ ├── environment_aware.rb │ ├── array_like.rb │ ├── all_published.rb │ ├── refresher.rb │ ├── archiver.rb │ ├── metadata.rb │ ├── system_properties.rb │ ├── publisher.rb │ ├── fields.rb │ └── field_aware.rb │ ├── client_tag_methods_factory.rb │ ├── client_asset_methods_factory.rb │ ├── file.rb │ ├── space_environment_methods_factory.rb │ ├── environment_tag_methods_factory.rb │ ├── environment_asset_methods_factory.rb │ ├── environment_entry_methods_factory.rb │ ├── environment_locale_methods_factory.rb │ ├── environment_content_type_methods_factory.rb │ ├── environment_ui_extension_methods_factory.rb │ ├── space_role_methods_factory.rb │ ├── space_api_key_methods_factory.rb │ ├── space_webhook_methods_factory.rb │ ├── client_locale_methods_factory.rb │ ├── location.rb │ ├── client_ui_extension_methods_factory.rb │ ├── space_space_membership_methods_factory.rb │ ├── space_preview_api_key_methods_factory.rb │ ├── environment_editor_interface_methods_factory.rb │ ├── client_organization_methods_factory.rb │ ├── entry_snapshot_methods_factory.rb │ ├── space_user_methods_factory.rb │ ├── client_entry_methods_factory.rb │ ├── organization_user_methods_factory.rb │ ├── client_user_methods_factory.rb │ ├── client_preview_api_key_methods_factory.rb │ ├── client_role_methods_factory.rb │ ├── client_api_key_methods_factory.rb │ ├── client_webhook_methods_factory.rb │ ├── client_space_membership_methods_factory.rb │ ├── client_webhook_health_methods_factory.rb │ ├── client_personal_access_tokens_methods_factory.rb │ ├── client_upload_methods_factory.rb │ ├── webhook_webhook_health_methods_factory.rb │ ├── client_content_type_methods_factory.rb │ ├── content_type_editor_interface_methods_factory.rb │ ├── entry_association_methods_factory.rb │ ├── client_space_periodic_usage_methods_factory.rb │ ├── client_webhook_call_methods_factory.rb │ ├── client_organization_periodic_usage_methods_factory.rb │ ├── client_taxonomy_concept_methods_factory.rb │ ├── webhook_webhook_call_methods_factory.rb │ ├── client_taxonomy_concept_scheme_methods_factory.rb │ ├── preview_api_key.rb │ ├── client_association_all_published_method_factory.rb │ ├── space_association_methods_factory.rb │ ├── link.rb │ ├── user.rb │ ├── array.rb │ ├── tag.rb │ ├── client_editor_interface_methods_factory.rb │ ├── client_snapshot_methods_factory.rb │ ├── environment_association_methods_factory.rb │ ├── locale.rb │ ├── validation.rb │ ├── personal_access_token.rb │ ├── client_space_methods_factory.rb │ ├── content_type_snapshot_methods_factory.rb │ ├── organization.rb │ ├── client_environment_methods_factory.rb │ ├── client_association_methods_factory.rb │ ├── space_periodic_usage.rb │ ├── dynamic_entry.rb │ ├── organization_periodic_usage.rb │ ├── role.rb │ ├── content_type_entry_methods_factory.rb │ ├── upload.rb │ ├── request.rb │ ├── space_membership.rb │ ├── webhook_health.rb │ ├── support.rb │ ├── webhook_call.rb │ └── api_key.rb ├── RELEASE.md ├── .gitignore ├── .reek ├── catalog-info.yaml ├── .rubocop.yml ├── .circleci └── config.yml ├── Guardfile ├── Rakefile ├── examples ├── create_space.rb └── content_types.rb ├── LICENSE.txt └── contentful-management.gemspec /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @contentful/team-developer-experience 2 | -------------------------------------------------------------------------------- /.rspec: -------------------------------------------------------------------------------- 1 | --color 2 | --format progress 3 | --order random 4 | -------------------------------------------------------------------------------- /.yardopts: -------------------------------------------------------------------------------- 1 | --no-private 2 | - 3 | CHANGELOG.md 4 | LICENSE.txt 5 | -------------------------------------------------------------------------------- /spec/fixtures/pixel.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/contentful/contentful-management.rb/master/spec/fixtures/pixel.jpg -------------------------------------------------------------------------------- /spec/fixtures/json_responses/other_error_nothing.json: -------------------------------------------------------------------------------- 1 | { 2 | "sys": { 3 | "type": "Error", 4 | "id": "SomeError" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /spec/fixtures/json_responses/default_400.json: -------------------------------------------------------------------------------- 1 | { 2 | "sys": { 3 | "type": "Error", 4 | "id": "BadRequest" 5 | }, 6 | "requestId": "85f-351076632" 7 | } 8 | -------------------------------------------------------------------------------- /spec/fixtures/json_responses/default_404.json: -------------------------------------------------------------------------------- 1 | { 2 | "sys": { 3 | "type": "Error", 4 | "id": "NotFound" 5 | }, 6 | "requestId": "85f-351076632" 7 | } 8 | -------------------------------------------------------------------------------- /spec/fixtures/json_responses/default_409.json: -------------------------------------------------------------------------------- 1 | { 2 | "sys": { 3 | "type": "Error", 4 | "id": "Conflict" 5 | }, 6 | "requestId": "85f-351076632" 7 | } 8 | -------------------------------------------------------------------------------- /spec/fixtures/json_responses/default_502.json: -------------------------------------------------------------------------------- 1 | { 2 | "sys": { 3 | "type": "Error", 4 | "id": "BadGateway" 5 | }, 6 | "requestId": "85f-351076632" 7 | } 8 | -------------------------------------------------------------------------------- /spec/fixtures/json_responses/default_401.json: -------------------------------------------------------------------------------- 1 | { 2 | "sys": { 3 | "type": "Error", 4 | "id": "Unauthorized" 5 | }, 6 | "requestId": "85f-351076632" 7 | } 8 | -------------------------------------------------------------------------------- /spec/fixtures/json_responses/default_403.json: -------------------------------------------------------------------------------- 1 | { 2 | "sys": { 3 | "type": "Error", 4 | "id": "AccessDenied" 5 | }, 6 | "requestId": "85f-351076632" 7 | } 8 | -------------------------------------------------------------------------------- /spec/fixtures/json_responses/default_500.json: -------------------------------------------------------------------------------- 1 | { 2 | "sys": { 3 | "type": "Error", 4 | "id": "ServerError" 5 | }, 6 | "requestId": "85f-351076632" 7 | } 8 | -------------------------------------------------------------------------------- /spec/fixtures/json_responses/default_422.json: -------------------------------------------------------------------------------- 1 | { 2 | "sys": { 3 | "type": "Error", 4 | "id": "UnprocessableEntity" 5 | }, 6 | "requestId": "85f-351076632" 7 | } 8 | -------------------------------------------------------------------------------- /spec/fixtures/json_responses/default_429.json: -------------------------------------------------------------------------------- 1 | { 2 | "sys": { 3 | "type": "Error", 4 | "id": "RateLimitExceeded" 5 | }, 6 | "requestId": "85f-351076632" 7 | } 8 | -------------------------------------------------------------------------------- /spec/fixtures/json_responses/default_503.json: -------------------------------------------------------------------------------- 1 | { 2 | "sys": { 3 | "type": "Error", 4 | "id": "ServiceUnavailable" 5 | }, 6 | "requestId": "85f-351076632" 7 | } 8 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | # Specify your gem's dependencies in contentful-management.gemspec 4 | gemspec 5 | 6 | group :development do 7 | gem 'pry' 8 | end 9 | -------------------------------------------------------------------------------- /bin/cma-console: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # -*- encoding: utf-8 -*- 3 | 4 | $LOAD_PATH << 'lib' 5 | require 'contentful/management/client' 6 | require 'pry' 7 | 8 | Pry::CLI.parse_options 9 | -------------------------------------------------------------------------------- /lib/contentful/management.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'contentful/management/version' 4 | require 'contentful/management/support' 5 | require 'contentful/management/client' 6 | -------------------------------------------------------------------------------- /spec/fixtures/json_responses/400_details_string.json: -------------------------------------------------------------------------------- 1 | { 2 | "sys": { 3 | "type": "Error", 4 | "id": "BadRequest" 5 | }, 6 | "details": "some error", 7 | "requestId": "85f-351076632" 8 | } 9 | -------------------------------------------------------------------------------- /spec/fixtures/json_responses/other_error_no_message.json: -------------------------------------------------------------------------------- 1 | { 2 | "sys": { 3 | "type": "Error", 4 | "id": "SomeError" 5 | }, 6 | "details": "some text", 7 | "requestId": "85f-351076632" 8 | } 9 | -------------------------------------------------------------------------------- /spec/fixtures/json_responses/other_error_no_request_id.json: -------------------------------------------------------------------------------- 1 | { 2 | "sys": { 3 | "type": "Error", 4 | "id": "SomeError" 5 | }, 6 | "details": "some text", 7 | "message": "Some error occurred." 8 | } 9 | -------------------------------------------------------------------------------- /spec/fixtures/json_responses/other_error_no_details.json: -------------------------------------------------------------------------------- 1 | { 2 | "sys": { 3 | "type": "Error", 4 | "id": "SomeError" 5 | }, 6 | "message": "Some error occurred.", 7 | "requestId": "85f-351076632" 8 | } 9 | -------------------------------------------------------------------------------- /spec/fixtures/json_responses/404_details_string.json: -------------------------------------------------------------------------------- 1 | { 2 | "sys": { 3 | "type": "Error", 4 | "id": "NotFound" 5 | }, 6 | "details": "The resource could not be found", 7 | "requestId": "85f-351076632" 8 | } 9 | -------------------------------------------------------------------------------- /spec/fixtures/json_responses/404_type.json: -------------------------------------------------------------------------------- 1 | { 2 | "sys": { 3 | "type": "Error", 4 | "id": "NotFound" 5 | }, 6 | "details": { 7 | "type": "Asset" 8 | }, 9 | "requestId": "85f-351076632" 10 | } 11 | -------------------------------------------------------------------------------- /spec/fixtures/json_responses/other_error.json: -------------------------------------------------------------------------------- 1 | { 2 | "sys": { 3 | "type": "Error", 4 | "id": "SomeError" 5 | }, 6 | "details": "some text", 7 | "message": "Some error occurred.", 8 | "requestId": "85f-351076632" 9 | } 10 | -------------------------------------------------------------------------------- /spec/fixtures/json_responses/404_id.json: -------------------------------------------------------------------------------- 1 | { 2 | "sys": { 3 | "type": "Error", 4 | "id": "NotFound" 5 | }, 6 | "details": { 7 | "type": "Asset", 8 | "id": "foobar" 9 | }, 10 | "requestId": "85f-351076632" 11 | } 12 | -------------------------------------------------------------------------------- /lib/contentful/management/version.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Contentful Namespace 4 | module Contentful 5 | # Management Namespace 6 | module Management 7 | # Gem Version 8 | VERSION = '3.12.1' 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /spec/fixtures/json_responses/400_details_errors_string.json: -------------------------------------------------------------------------------- 1 | { 2 | "sys": { 3 | "type": "Error", 4 | "id": "BadRequest" 5 | }, 6 | "details": { 7 | "errors": [ 8 | "some error" 9 | ] 10 | }, 11 | "requestId": "85f-351076632" 12 | } 13 | -------------------------------------------------------------------------------- /RELEASE.md: -------------------------------------------------------------------------------- 1 | # Releasing new versions: 2 | 3 | Make sure all points are taken care of: 4 | 5 | - [ ] Make sure tests are green. 6 | - [ ] Update Changelog: http://keepachangelog.com/ 7 | - [ ] Bump version number: http://semver.org/ 8 | - [ ] Release gem and communicate updates 9 | -------------------------------------------------------------------------------- /spec/fixtures/json_responses/403_reasons.json: -------------------------------------------------------------------------------- 1 | { 2 | "sys": { 3 | "type": "Error", 4 | "id": "AccessDenied" 5 | }, 6 | "details": { 7 | "reasons": [ 8 | "foo", 9 | "bar" 10 | ] 11 | }, 12 | "requestId": "85f-351076632" 13 | } 14 | -------------------------------------------------------------------------------- /spec/fixtures/json_responses/400_details_errors_object.json: -------------------------------------------------------------------------------- 1 | { 2 | "sys": { 3 | "type": "Error", 4 | "id": "BadRequest" 5 | }, 6 | "details": { 7 | "errors": [ 8 | { 9 | "details": "some error" 10 | } 11 | ] 12 | }, 13 | "requestId": "85f-351076632" 14 | } 15 | -------------------------------------------------------------------------------- /spec/fixtures/json_responses/not_found.json: -------------------------------------------------------------------------------- 1 | { 2 | "sys": { 3 | "type": "Error", 4 | "id": "NotFound" 5 | }, 6 | "details": { 7 | "type": "Entry", 8 | "space": "cfexampleapi", 9 | "id": "not found" 10 | }, 11 | "message": "The resource could not be found.", 12 | "requestId": "85f-351076632" 13 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.gem 2 | *.rbc 3 | .bundle 4 | .config 5 | .yardoc 6 | Gemfile.lock 7 | InstalledFiles 8 | _yardoc 9 | coverage 10 | doc/ 11 | lib/bundler/man 12 | pkg 13 | rdoc 14 | spec/reports 15 | test/tmp 16 | test/version_tmp 17 | tmp 18 | *.bundle 19 | *.so 20 | *.o 21 | *.a 22 | mkmf.log 23 | .idea 24 | .idea/**/* 25 | .DS_STORE -------------------------------------------------------------------------------- /spec/fixtures/json_responses/unparsable.json: -------------------------------------------------------------------------------- 1 | { 2 | "sys": { 3 | "type": "Error", 4 | "id": "NotFound" 5 | }, 6 | "details": { 7 | "type": "Entry", 8 | "space": "cfexampleapi", 9 | "id": "not found" 10 | }, 11 | "message": "The resource could not be found.", 12 | "requestId": "85f-351076632", 13 | "missing": "braceright" 14 | -------------------------------------------------------------------------------- /lib/contentful/management/resource/entry_fields.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Contentful 4 | module Management 5 | module Resource 6 | # Adds Field Coercions for Entries 7 | module EntryFields 8 | # Special fields for Entry. 9 | def fields_coercions 10 | {} 11 | end 12 | end 13 | end 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /lib/contentful/management/client_tag_methods_factory.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative 'client_association_methods_factory' 4 | 5 | module Contentful 6 | module Management 7 | # Wrapper for Tag API for usage from within Client 8 | # @private 9 | class ClientTagMethodsFactory 10 | include Contentful::Management::ClientAssociationMethodsFactory 11 | end 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /lib/contentful/management/client_asset_methods_factory.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative 'client_association_methods_factory' 4 | 5 | module Contentful 6 | module Management 7 | # Wrapper for Asset API for usage from within Client 8 | # @private 9 | class ClientAssetMethodsFactory 10 | include Contentful::Management::ClientAssociationMethodsFactory 11 | end 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /.reek: -------------------------------------------------------------------------------- 1 | --- 2 | IrresponsibleModule: 3 | enabled: false 4 | TooManyStatements: 5 | exclude: 6 | - initialize 7 | - entries 8 | - assets 9 | - content_types 10 | max_statements: 11 11 | NestedIterators: 12 | enabled: false 13 | PrimaDonnaMethod: 14 | enabled: false 15 | FeatureEnvy: 16 | enabled: true 17 | exclude: 18 | - initialize 19 | NilCheck: 20 | enabled: true 21 | exclude: 22 | - save 23 | - create 24 | -------------------------------------------------------------------------------- /lib/contentful/management/file.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative 'resource' 4 | 5 | module Contentful 6 | module Management 7 | # An Asset's file schema 8 | class File 9 | include Contentful::Management::Resource 10 | 11 | property :details 12 | property :url, :string 13 | property :fileName, :string 14 | property :contentType, :string 15 | end 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /lib/contentful/management/space_environment_methods_factory.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative 'space_association_methods_factory' 4 | 5 | module Contentful 6 | module Management 7 | # Wrapper for Environment API for usage from within Space 8 | # @private 9 | class SpaceEnvironmentMethodsFactory 10 | include Contentful::Management::SpaceAssociationMethodsFactory 11 | end 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /lib/contentful/management/environment_tag_methods_factory.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative 'environment_association_methods_factory' 4 | 5 | module Contentful 6 | module Management 7 | # Wrapper for Tag API for usage from within Environment 8 | # @private 9 | class EnvironmentTagMethodsFactory 10 | include Contentful::Management::EnvironmentAssociationMethodsFactory 11 | end 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /lib/contentful/management/environment_asset_methods_factory.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative 'environment_association_methods_factory' 4 | 5 | module Contentful 6 | module Management 7 | # Wrapper for Asset API for usage from within Environment 8 | # @private 9 | class EnvironmentAssetMethodsFactory 10 | include Contentful::Management::EnvironmentAssociationMethodsFactory 11 | end 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /lib/contentful/management/environment_entry_methods_factory.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative 'environment_association_methods_factory' 4 | 5 | module Contentful 6 | module Management 7 | # Wrapper for Entry API for usage from within Environment 8 | # @private 9 | class EnvironmentEntryMethodsFactory 10 | include Contentful::Management::EnvironmentAssociationMethodsFactory 11 | end 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /lib/contentful/management/environment_locale_methods_factory.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative 'environment_association_methods_factory' 4 | 5 | module Contentful 6 | module Management 7 | # Wrapper for Locale API for usage from within Environment 8 | # @private 9 | class EnvironmentLocaleMethodsFactory 10 | include Contentful::Management::EnvironmentAssociationMethodsFactory 11 | end 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /catalog-info.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: backstage.io/v1alpha1 2 | kind: Component 3 | metadata: 4 | name: contentful-management.rb 5 | description: Ruby client for the Contentful Content Management API. 6 | annotations: 7 | github.com/project-slug: contentful/contentful-management.rb 8 | contentful.com/service-tier: "4" 9 | tags: 10 | - tier-4 11 | spec: 12 | type: library 13 | lifecycle: production 14 | owner: group:team-developer-experience 15 | -------------------------------------------------------------------------------- /lib/contentful/management/environment_content_type_methods_factory.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative 'environment_association_methods_factory' 4 | 5 | module Contentful 6 | module Management 7 | # Wrapper for Content Type API for usage from within Environment 8 | # @private 9 | class EnvironmentContentTypeMethodsFactory 10 | include Contentful::Management::EnvironmentAssociationMethodsFactory 11 | end 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /lib/contentful/management/environment_ui_extension_methods_factory.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative 'environment_association_methods_factory' 4 | 5 | module Contentful 6 | module Management 7 | # Wrapper for UI Extensions API for usage from within Environment 8 | # @private 9 | class EnvironmentUIExtensionMethodsFactory 10 | include Contentful::Management::EnvironmentAssociationMethodsFactory 11 | end 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /lib/contentful/management/space_role_methods_factory.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative 'space_association_methods_factory' 4 | 5 | module Contentful 6 | module Management 7 | # Wrapper for Role API for usage from within Space 8 | # @private 9 | class SpaceRoleMethodsFactory 10 | include Contentful::Management::SpaceAssociationMethodsFactory 11 | 12 | def new 13 | fail 'Not supported' 14 | end 15 | end 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /lib/contentful/management/space_api_key_methods_factory.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative 'space_association_methods_factory' 4 | 5 | module Contentful 6 | module Management 7 | # Wrapper for ApiKey API for usage from within Space 8 | # @private 9 | class SpaceApiKeyMethodsFactory 10 | include Contentful::Management::SpaceAssociationMethodsFactory 11 | 12 | def new 13 | fail 'Not supported' 14 | end 15 | end 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /lib/contentful/management/space_webhook_methods_factory.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative 'space_association_methods_factory' 4 | 5 | module Contentful 6 | module Management 7 | # Wrapper for Webhook API for usage from within Space 8 | # @private 9 | class SpaceWebhookMethodsFactory 10 | include Contentful::Management::SpaceAssociationMethodsFactory 11 | 12 | def new 13 | fail 'Not supported' 14 | end 15 | end 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /lib/contentful/management/client_locale_methods_factory.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative 'client_association_methods_factory' 4 | 5 | module Contentful 6 | module Management 7 | # Wrapper for Locale API for usage from within Client 8 | # @private 9 | class ClientLocaleMethodsFactory 10 | include Contentful::Management::ClientAssociationMethodsFactory 11 | 12 | def new(*) 13 | fail 'Not supported' 14 | end 15 | end 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /lib/contentful/management/location.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative 'resource' 4 | 5 | module Contentful 6 | module Management 7 | # Location Field Type 8 | # @see _ You can directly query for them: https://www.contentful.com/developers/documentation/content-management-api/#search-filter-geo 9 | class Location 10 | include Contentful::Management::Resource 11 | 12 | property :lat, :float 13 | property :lon, :float 14 | end 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /lib/contentful/management/resource/asset_fields.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Contentful 4 | module Management 5 | module Resource 6 | # Adds Field Coercions for [Asset] 7 | module AssetFields 8 | # Special fields for Asset. 9 | def fields_coercions 10 | { 11 | title: :hash, 12 | description: :hash, 13 | file: Contentful::Management::File 14 | } 15 | end 16 | end 17 | end 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /lib/contentful/management/client_ui_extension_methods_factory.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative 'client_association_methods_factory' 4 | 5 | module Contentful 6 | module Management 7 | # Wrapper for UI Extension API for usage from within Client 8 | # @private 9 | class ClientUIExtensionMethodsFactory 10 | include Contentful::Management::ClientAssociationMethodsFactory 11 | 12 | def new(*) 13 | fail 'Not supported' 14 | end 15 | end 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /lib/contentful/management/space_space_membership_methods_factory.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative 'space_association_methods_factory' 4 | 5 | module Contentful 6 | module Management 7 | # Wrapper for Space Membership API for usage from within Space 8 | # @private 9 | class SpaceSpaceMembershipMethodsFactory 10 | include Contentful::Management::SpaceAssociationMethodsFactory 11 | 12 | def new(*) 13 | fail 'Not supported' 14 | end 15 | end 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | require 'simplecov' 2 | SimpleCov.start unless RUBY_PLATFORM == 'java' 3 | 4 | require 'rspec' 5 | require 'contentful/management' 6 | require 'pry' 7 | require 'rspec/its' 8 | 9 | Dir[File.dirname(__FILE__) + '/support/**/*.rb'].each { |f| require f } 10 | 11 | RSpec.configure do |config| 12 | config.filter_run :focus => true 13 | config.run_all_when_everything_filtered = true 14 | end 15 | 16 | class RequestDouble 17 | attr_reader :url 18 | 19 | def initialize(url) 20 | @url = url 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /.rubocop.yml: -------------------------------------------------------------------------------- 1 | inherit_from: .rubocop_todo.yml 2 | 3 | Encoding: 4 | Enabled: false 5 | 6 | Metrics/ClassLength: 7 | CountComments: false 8 | 9 | AllCops: 10 | Exclude: 11 | - contentful-management.gemspec 12 | - bin/cma-console 13 | - spec/**/* 14 | - examples/**/* 15 | - Guardfile 16 | - Gemfile 17 | - Rakefile 18 | 19 | Metrics/LineLength: 20 | Max: 135 21 | 22 | Metrics/ClassLength: 23 | Max: 350 24 | 25 | Metrics/ModuleLength: 26 | Max: 350 27 | 28 | Style/SignalException: 29 | EnforcedStyle: 'semantic' 30 | -------------------------------------------------------------------------------- /spec/fixtures/json_responses/422_details.json: -------------------------------------------------------------------------------- 1 | { 2 | "requestId": "044bb23356babe4f11a3f7f1e77c762a", 3 | "message":"The resource you sent in the body is invalid.", 4 | "details":{ 5 | "errors":[ 6 | { 7 | "name":"taken", 8 | "path":"display_code", 9 | "value":"en-US" 10 | }, 11 | { 12 | "name":"fallback locale creates a loop", 13 | "path":"fallback_code", 14 | "value":"en-US" 15 | } 16 | ] 17 | }, 18 | "sys":{ 19 | "type":"Error", 20 | "id":"ValidationFailed" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2.1 2 | 3 | jobs: 4 | test_and_lint: 5 | parameters: 6 | ruby-version: 7 | type: string 8 | docker: 9 | - image: cimg/ruby:<< parameters.ruby-version >> 10 | steps: 11 | - checkout 12 | - run: gem install bundler:2.3.26 13 | - run: bundle install 14 | - run: bundle exec rake rspec_rubocop 15 | 16 | workflows: 17 | version: 2 18 | workflow: 19 | jobs: 20 | - test_and_lint: 21 | matrix: 22 | parameters: 23 | ruby-version: ["3.2", "3.3", "3.4"] 24 | -------------------------------------------------------------------------------- /lib/contentful/management/space_preview_api_key_methods_factory.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative 'space_association_methods_factory' 4 | 5 | module Contentful 6 | module Management 7 | # Wrapper for PreviewApiKey API for usage from within Space 8 | # @private 9 | class SpacePreviewApiKeyMethodsFactory 10 | include Contentful::Management::SpaceAssociationMethodsFactory 11 | 12 | def new 13 | fail 'Not supported' 14 | end 15 | 16 | def create 17 | fail 'Not supported' 18 | end 19 | end 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /lib/contentful/management/environment_editor_interface_methods_factory.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative 'environment_association_methods_factory' 4 | 5 | module Contentful 6 | module Management 7 | # Wrapper for Editor Interface API for usage from within Environment 8 | # @private 9 | class EnvironmentEditorInterfaceMethodsFactory 10 | include Contentful::Management::EnvironmentAssociationMethodsFactory 11 | 12 | def default(content_type_id) 13 | associated_class.default(environment.client, environment.space.id, environment.id, content_type_id) 14 | end 15 | end 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /lib/contentful/management/client_organization_methods_factory.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative 'client_association_methods_factory' 4 | 5 | module Contentful 6 | module Management 7 | # Wrapper for Organizations API for usage from within Client 8 | # @private 9 | class ClientOrganizationMethodsFactory 10 | include Contentful::Management::ClientAssociationMethodsFactory 11 | 12 | def new(*) 13 | fail 'Not supported' 14 | end 15 | 16 | def find(*) 17 | fail 'Not supported' 18 | end 19 | 20 | def all(*) 21 | super 22 | end 23 | end 24 | end 25 | end 26 | -------------------------------------------------------------------------------- /lib/contentful/management/entry_snapshot_methods_factory.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative 'entry_association_methods_factory' 4 | 5 | module Contentful 6 | module Management 7 | # Wrapper for Snapshot API for usage from within Space 8 | # @private 9 | class EntrySnapshotMethodsFactory 10 | include Contentful::Management::EntryAssociationMethodsFactory 11 | 12 | def new 13 | fail 'Not supported' 14 | end 15 | 16 | def create(*) 17 | fail 'Not supported' 18 | end 19 | 20 | def update(*) 21 | fail 'Not supported' 22 | end 23 | end 24 | end 25 | end 26 | -------------------------------------------------------------------------------- /lib/contentful/management/space_user_methods_factory.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative 'space_association_methods_factory' 4 | 5 | module Contentful 6 | module Management 7 | # Wrapper for User API for usage from within Space 8 | # @private 9 | class SpaceUserMethodsFactory 10 | attr_reader :space 11 | 12 | def initialize(space) 13 | @space = space 14 | end 15 | 16 | def find(id) 17 | User.find(space.client, space.id, nil, id) 18 | end 19 | 20 | def all(params = {}) 21 | User.all(space.client, space.id, nil, params, nil) 22 | end 23 | end 24 | end 25 | end 26 | -------------------------------------------------------------------------------- /lib/contentful/management/client_entry_methods_factory.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative 'client_association_methods_factory' 4 | 5 | module Contentful 6 | module Management 7 | # Wrapper for Entry API for usage from within Client 8 | # @private 9 | class ClientEntryMethodsFactory 10 | include Contentful::Management::ClientAssociationMethodsFactory 11 | 12 | def create(content_type, attributes) 13 | associated_class.create(client, @space_id, @environment_id, attributes.merge(content_type: content_type)) 14 | end 15 | 16 | def new(*) 17 | fail 'Not supported' 18 | end 19 | end 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /Guardfile: -------------------------------------------------------------------------------- 1 | group :green_red_refactor, halt_on_fail: true do 2 | guard :rspec, cmd: "bundle exec rspec --format documentation" do 3 | require "guard/rspec/dsl" 4 | dsl = Guard::RSpec::Dsl.new(self) 5 | 6 | # Feel free to open issues for suggestions and improvements 7 | 8 | # RSpec files 9 | rspec = dsl.rspec 10 | watch(rspec.spec_helper) { rspec.spec_dir } 11 | watch(rspec.spec_support) { rspec.spec_dir } 12 | watch(rspec.spec_files) 13 | 14 | # Ruby files 15 | ruby = dsl.ruby 16 | dsl.watch_spec_files_for(ruby.lib_files) 17 | end 18 | 19 | guard :rubocop, cmd: "rubocop" do 20 | end 21 | 22 | guard :yard, cmd: "yard doc" do 23 | end 24 | end 25 | -------------------------------------------------------------------------------- /lib/contentful/management/organization_user_methods_factory.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Contentful 4 | module Management 5 | # Wrapper for Users API for usage from within Organization 6 | # @private 7 | class OrganizationUserMethodsFactory 8 | attr_reader :client 9 | 10 | def initialize(client, organization_id) 11 | @client = client 12 | @organization_id = organization_id 13 | end 14 | 15 | def find(id) 16 | User.find(client, nil, nil, id, @organization_id) 17 | end 18 | 19 | def all(params = {}) 20 | User.all(client, nil, nil, params, @organization_id) 21 | end 22 | end 23 | end 24 | end 25 | -------------------------------------------------------------------------------- /spec/support/json_responses.rb: -------------------------------------------------------------------------------- 1 | require 'multi_json' 2 | 3 | def raw_fixture(which, status = 200, _as_json = false, headers = {}) 4 | object = Object.new 5 | allow(object).to receive(:status) { status } 6 | allow(object).to receive(:headers) { headers } 7 | allow(object).to receive(:to_s) { File.read File.dirname(__FILE__) + "/../fixtures/json_responses/#{which}.json" } 8 | allow(object).to receive(:body) { object.to_s } 9 | allow(object).to receive(:[]) { |key| object.headers[key] } 10 | 11 | object 12 | end 13 | 14 | def json_fixture(which, _as_json = false) 15 | MultiJson.load( 16 | File.read File.dirname(__FILE__) + "/../fixtures/json_responses/#{which}.json" 17 | ) 18 | end 19 | -------------------------------------------------------------------------------- /lib/contentful/management/client_user_methods_factory.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative 'client_association_methods_factory' 4 | 5 | module Contentful 6 | module Management 7 | # Wrapper for Users API for usage from within Client 8 | # @private 9 | class ClientUserMethodsFactory 10 | include Contentful::Management::ClientAssociationMethodsFactory 11 | 12 | def new(*) 13 | fail 'Not supported' 14 | end 15 | 16 | def find(user_id) 17 | super(user_id) 18 | end 19 | 20 | def me 21 | find('me') 22 | end 23 | 24 | def all(*) 25 | fail 'Not supported' 26 | end 27 | end 28 | end 29 | end 30 | -------------------------------------------------------------------------------- /lib/contentful/management/client_preview_api_key_methods_factory.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative 'client_association_methods_factory' 4 | 5 | module Contentful 6 | module Management 7 | # Wrapper for PreviewApiKey API for usage from within Client 8 | # @private 9 | class ClientPreviewApiKeyMethodsFactory 10 | include Contentful::Management::ClientAssociationMethodsFactory 11 | 12 | def new(*) 13 | fail 'Not supported' 14 | end 15 | 16 | def find(resource_id) 17 | associated_class.find(client, @space_id, resource_id) 18 | end 19 | 20 | def create(*) 21 | fail 'Not supported' 22 | end 23 | end 24 | end 25 | end 26 | -------------------------------------------------------------------------------- /lib/contentful/management/client_role_methods_factory.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative 'client_association_methods_factory' 4 | 5 | module Contentful 6 | module Management 7 | # Wrapper for Role API for usage from within Client 8 | # @private 9 | class ClientRoleMethodsFactory 10 | include Contentful::Management::ClientAssociationMethodsFactory 11 | 12 | def new(*) 13 | fail 'Not supported' 14 | end 15 | 16 | def find(resource_id) 17 | associated_class.find(client, @space_id, resource_id) 18 | end 19 | 20 | def create(attributes) 21 | associated_class.create(client, @space_id, attributes) 22 | end 23 | end 24 | end 25 | end 26 | -------------------------------------------------------------------------------- /lib/contentful/management/client_api_key_methods_factory.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative 'client_association_methods_factory' 4 | 5 | module Contentful 6 | module Management 7 | # Wrapper for ApiKey API for usage from within Client 8 | # @private 9 | class ClientApiKeyMethodsFactory 10 | include Contentful::Management::ClientAssociationMethodsFactory 11 | 12 | def new(*) 13 | fail 'Not supported' 14 | end 15 | 16 | def find(resource_id) 17 | associated_class.find(client, @space_id, resource_id) 18 | end 19 | 20 | def create(attributes) 21 | associated_class.create(client, @space_id, attributes) 22 | end 23 | end 24 | end 25 | end 26 | -------------------------------------------------------------------------------- /lib/contentful/management/client_webhook_methods_factory.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative 'client_association_methods_factory' 4 | 5 | module Contentful 6 | module Management 7 | # Wrapper for Webhook API for usage from within Client 8 | # @private 9 | class ClientWebhookMethodsFactory 10 | include Contentful::Management::ClientAssociationMethodsFactory 11 | 12 | def new(*) 13 | fail 'Not supported' 14 | end 15 | 16 | def find(resource_id) 17 | associated_class.find(client, @space_id, resource_id) 18 | end 19 | 20 | def create(attributes) 21 | associated_class.create(client, @space_id, attributes) 22 | end 23 | end 24 | end 25 | end 26 | -------------------------------------------------------------------------------- /spec/support/vcr.rb: -------------------------------------------------------------------------------- 1 | require 'vcr' 2 | 3 | VCR.configure do |c| 4 | c.cassette_library_dir = 'spec/fixtures/vcr_cassettes' 5 | c.ignore_localhost = true 6 | c.hook_into :webmock 7 | c.default_cassette_options = {record: :once} 8 | 9 | # Redact Contentful Management API tokens from VCR recordings 10 | c.filter_sensitive_data('') do |interaction| 11 | if (auths = interaction.request.headers['Authorization']&.first) 12 | if (match = auths.match(/^Bearer\s+([^,\s]+)/)) 13 | match.captures.first 14 | end 15 | end 16 | end 17 | end 18 | 19 | def vcr(name, &block) 20 | VCR.use_cassette(name, &block) 21 | end 22 | 23 | def expect_vcr(name, &block) 24 | expect { VCR.use_cassette(name, &block) } 25 | end 26 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require 'bundler/gem_tasks' 2 | require 'rubygems' 3 | require 'rake' 4 | 5 | begin 6 | require 'bundler' 7 | rescue LoadError => e 8 | warn e.message 9 | warn 'Run `gem install bundler` to install Bundler.' 10 | exit 1 11 | end 12 | 13 | begin 14 | Bundler.setup(:development) 15 | rescue Bundler::BundlerError => e 16 | warn e.message 17 | warn 'Run `bundle install` to install missing gems.' 18 | exit e.status_code 19 | end 20 | 21 | require 'rspec/core/rake_task' 22 | RSpec::Core::RakeTask.new 23 | 24 | require 'rubocop/rake_task' 25 | RuboCop::RakeTask.new 26 | 27 | desc 'Run specs, rubocop and reek' 28 | task ci: %w(spec reek rubocop) 29 | 30 | task rspec_rubocop: %w(spec rubocop) 31 | 32 | task test: :spec 33 | task default: :spec 34 | -------------------------------------------------------------------------------- /lib/contentful/management/client_space_membership_methods_factory.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative 'client_association_methods_factory' 4 | 5 | module Contentful 6 | module Management 7 | # Wrapper for Space Membership API for usage from within Client 8 | # @private 9 | class ClientSpaceMembershipMethodsFactory 10 | include Contentful::Management::ClientAssociationMethodsFactory 11 | 12 | def new(*) 13 | fail 'Not supported' 14 | end 15 | 16 | def find(resource_id) 17 | associated_class.find(client, @space_id, resource_id) 18 | end 19 | 20 | def create(attributes) 21 | associated_class.create(client, @space_id, attributes) 22 | end 23 | end 24 | end 25 | end 26 | -------------------------------------------------------------------------------- /lib/contentful/management/client_webhook_health_methods_factory.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative 'client_association_methods_factory' 4 | 5 | module Contentful 6 | module Management 7 | # Wrapper for Webhook Health API for usage from within Client 8 | # @private 9 | class ClientWebhookHealthMethodsFactory 10 | include Contentful::Management::ClientAssociationMethodsFactory 11 | 12 | # Not supported 13 | def all(*) 14 | fail 'Not supported' 15 | end 16 | 17 | def find(webhook_id) 18 | @resource_requester.find( 19 | space_id: @space_id, 20 | webhook_id: webhook_id 21 | ) 22 | end 23 | 24 | def new(*) 25 | fail 'Not supported' 26 | end 27 | end 28 | end 29 | end 30 | -------------------------------------------------------------------------------- /lib/contentful/management/client_personal_access_tokens_methods_factory.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative 'client_association_methods_factory' 4 | 5 | module Contentful 6 | module Management 7 | # Wrapper for Personal Access Token API for usage from within Client 8 | # @private 9 | class ClientPersonalAccessTokenMethodsFactory 10 | include Contentful::Management::ClientAssociationMethodsFactory 11 | 12 | def new(*) 13 | fail 'Not supported' 14 | end 15 | 16 | def all(params = {}) 17 | super(params) 18 | end 19 | 20 | def find(personal_access_token_id) 21 | super(personal_access_token_id) 22 | end 23 | 24 | def create(attributes) 25 | super(attributes) 26 | end 27 | end 28 | end 29 | end 30 | -------------------------------------------------------------------------------- /lib/contentful/management/client_upload_methods_factory.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative 'client_association_methods_factory' 4 | 5 | module Contentful 6 | module Management 7 | # Wrapper for Upload API for usage from within Client 8 | # @private 9 | class ClientUploadMethodsFactory 10 | include Contentful::Management::ClientAssociationMethodsFactory 11 | 12 | def new(*) 13 | fail 'Not supported' 14 | end 15 | 16 | def all(*) 17 | fail 'Not supported' 18 | end 19 | 20 | def find(resource_id) 21 | associated_class.find(client, @space_id, resource_id) 22 | end 23 | 24 | def create(attributes) 25 | associated_class.create(client, @space_id, attributes) 26 | end 27 | end 28 | end 29 | end 30 | -------------------------------------------------------------------------------- /.github/workflows/codeql.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: "CodeQL Scan for GitHub Actions Workflows" 3 | 4 | on: 5 | push: 6 | branches: [master] 7 | paths: [".github/workflows/**"] 8 | pull_request: 9 | branches: [master] 10 | paths: [".github/workflows/**"] 11 | 12 | jobs: 13 | analyze: 14 | name: Analyze GitHub Actions workflows 15 | runs-on: ubuntu-latest 16 | permissions: 17 | actions: read 18 | contents: read 19 | security-events: write 20 | 21 | steps: 22 | - uses: actions/checkout@v4 23 | 24 | - name: Initialize CodeQL 25 | uses: github/codeql-action/init@v3 26 | with: 27 | languages: actions 28 | 29 | - name: Run CodeQL Analysis 30 | uses: github/codeql-action/analyze@v3 31 | with: 32 | category: actions 33 | -------------------------------------------------------------------------------- /lib/contentful/management/resource/environment_aware.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Contentful 4 | module Management 5 | module Resource 6 | # Mixin for environment aware resources 7 | module EnvironmentAware 8 | # Gets the environment ID for the resource. 9 | def environment_id 10 | env = sys.fetch(:environment, {}) 11 | env_from_sys = 12 | case env 13 | when ::Hash 14 | env.fetch(:id, nil) 15 | when ::Contentful::Management::Link, ::Contentful::Management::Environment 16 | env.id 17 | end 18 | 19 | return env_from_sys if env_from_sys 20 | 21 | respond_to?(:content_type) && content_type && content_type.environment_id || 'master' 22 | end 23 | end 24 | end 25 | end 26 | end 27 | -------------------------------------------------------------------------------- /lib/contentful/management/webhook_webhook_health_methods_factory.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative 'resource_requester' 4 | 5 | module Contentful 6 | module Management 7 | # Wrapper for webhook health information for a specific webhook. 8 | # @private 9 | class WebhookWebhookHealthMethodsFactory 10 | attr_reader :webhook 11 | 12 | # @private 13 | def initialize(webhook) 14 | @webhook = webhook 15 | end 16 | 17 | # Not supported 18 | def all(*) 19 | fail 'Not supported' 20 | end 21 | 22 | # Gets a webhook call detail for a specific webhook by ID. 23 | # 24 | # @return [Contentful::Management::WebhookCall] 25 | def find 26 | WebhookHealth.find(webhook.client, webhook.space.id, webhook.id) 27 | end 28 | end 29 | end 30 | end 31 | -------------------------------------------------------------------------------- /lib/contentful/management/client_content_type_methods_factory.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative 'client_association_methods_factory' 4 | require_relative 'client_association_all_published_method_factory' 5 | 6 | module Contentful 7 | module Management 8 | # Wrapper for ContentType API for usage from within Client 9 | # @private 10 | class ClientContentTypeMethodsFactory 11 | include Contentful::Management::ClientAssociationMethodsFactory 12 | include Contentful::Management::ClientAssociationAllPublishedMethodsFactory 13 | 14 | def all(query = {}) 15 | content_types = super(query) 16 | client.update_dynamic_entry_cache!(content_types) 17 | content_types 18 | end 19 | 20 | def all_published(params = {}) 21 | super({ suppress_warning: true }.merge(params)) 22 | end 23 | end 24 | end 25 | end 26 | -------------------------------------------------------------------------------- /lib/contentful/management/content_type_editor_interface_methods_factory.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative 'client_editor_interface_methods_factory' 4 | require_relative 'editor_interface' 5 | 6 | module Contentful 7 | module Management 8 | # Wrapper for Editor Interface API for a specific Content Type 9 | # @private 10 | class ContentTypeEditorInterfaceMethodsFactory 11 | attr_reader :content_type, :editor_interfaces_client 12 | 13 | # @private 14 | def initialize(content_type) 15 | @editor_interfaces_client = ClientEditorInterfaceMethodsFactory.new( 16 | content_type.client, 17 | content_type.space.id, 18 | content_type.environment_id, 19 | content_type.id 20 | ) 21 | end 22 | 23 | def default 24 | editor_interfaces_client.default 25 | end 26 | end 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /lib/contentful/management/resource/array_like.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Contentful 4 | module Management 5 | module Resource 6 | # Useful methods for array-like resources that can be included if an 7 | # [#items] property exists 8 | module ArrayLike 9 | include Enumerable 10 | 11 | # Returns true for array-like resources 12 | def array? 13 | true 14 | end 15 | 16 | # Delegates to items#each 17 | def each_item(&block) 18 | items.each(&block) 19 | end 20 | 21 | alias each each_item 22 | 23 | # Delegates to items#empty? 24 | def empty? 25 | items.empty? 26 | end 27 | 28 | # Delegetes to items#size 29 | def size 30 | items.size 31 | end 32 | 33 | alias length size 34 | end 35 | end 36 | end 37 | end 38 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/delete_request.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: delete 5 | uri: http://example.com/?foo=bar 6 | body: 7 | encoding: US-ASCII 8 | string: '' 9 | headers: 10 | Connection: 11 | - close 12 | Host: 13 | - example.com 14 | User-Agent: 15 | - http.rb/0.9.8 16 | response: 17 | status: 18 | code: 405 19 | message: Method Not Allowed 20 | headers: 21 | Cache-Control: 22 | - max-age=604800 23 | Date: 24 | - Fri, 11 Mar 2016 10:16:02 GMT 25 | Expires: 26 | - Fri, 18 Mar 2016 10:16:02 GMT 27 | Server: 28 | - EOS (lax004/45C0) 29 | Content-Length: 30 | - '0' 31 | Connection: 32 | - close 33 | body: 34 | encoding: UTF-8 35 | string: '' 36 | http_version: 37 | recorded_at: Fri, 11 Mar 2016 10:16:01 GMT 38 | recorded_with: VCR 2.9.3 39 | -------------------------------------------------------------------------------- /examples/create_space.rb: -------------------------------------------------------------------------------- 1 | require 'pry' 2 | 3 | access_token = 'access token' 4 | organization = 'organization id' 5 | 6 | require 'contentful/management' 7 | 8 | client = Contentful::Management::Client.new(access_token) 9 | 10 | spaces = Contentful::Management::Space.all 11 | 12 | my_space = Contentful::Management::Space.create(name: 'MySpace', organization_id: organization) 13 | 14 | my_space.update(name: 'MyNewSpace') 15 | 16 | dat_space = Contentful::Management::Space.find(my_space.id) 17 | 18 | dat_space.locales.create(name: 'English', code: 'en-US') 19 | 20 | locales = dat_space.locales.all 21 | # locales.map(&:destroy) # not implemented yet? 22 | 23 | dat_space.destroy 24 | 25 | # XXX: This does not set the organization_id when a space should be created 26 | # 27 | your_space = Contentful::Management::Space.new 28 | your_space.organization = organization 29 | your_space.name = 'YourSpace' 30 | your_space.save 31 | 32 | your_space.destroy 33 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/put_request.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: put 5 | uri: http://example.com/ 6 | body: 7 | encoding: UTF-8 8 | string: '{"foo":"bar"}' 9 | headers: 10 | Connection: 11 | - close 12 | Content-Type: 13 | - application/json 14 | Host: 15 | - example.com 16 | User-Agent: 17 | - http.rb/0.9.8 18 | response: 19 | status: 20 | code: 405 21 | message: Method Not Allowed 22 | headers: 23 | Cache-Control: 24 | - max-age=604800 25 | Date: 26 | - Fri, 11 Mar 2016 10:16:00 GMT 27 | Expires: 28 | - Fri, 18 Mar 2016 10:16:00 GMT 29 | Server: 30 | - EOS (lax004/45C0) 31 | Content-Length: 32 | - '0' 33 | Connection: 34 | - close 35 | body: 36 | encoding: UTF-8 37 | string: '' 38 | http_version: 39 | recorded_at: Fri, 11 Mar 2016 10:16:01 GMT 40 | recorded_with: VCR 2.9.3 41 | -------------------------------------------------------------------------------- /lib/contentful/management/entry_association_methods_factory.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative 'resource_requester' 4 | 5 | module Contentful 6 | module Management 7 | # Wrapper for Entry Association Methods 8 | # @private 9 | module EntryAssociationMethodsFactory 10 | attr_reader :entry 11 | 12 | def initialize(entry) 13 | @entry = entry 14 | end 15 | 16 | def all(_params = {}) 17 | associated_class.all(entry.client, entry.sys[:space].id, entry.environment_id, entry.id) 18 | end 19 | 20 | def find(id) 21 | associated_class.find(entry.client, entry.sys[:space].id, entry.environment_id, entry.id, id) 22 | end 23 | 24 | def associated_class 25 | class_name = /\A(.+)Entry(.+)MethodsFactory\z/.match(self.class.name).captures.join 26 | class_name.split('::').reduce(Object) do |mod, actual_class_name| 27 | mod.const_get(actual_class_name) 28 | end 29 | end 30 | end 31 | end 32 | end 33 | -------------------------------------------------------------------------------- /lib/contentful/management/client_space_periodic_usage_methods_factory.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative 'client_association_methods_factory' 4 | 5 | module Contentful 6 | module Management 7 | # Wrapper for Space Periodic Usages for usage from within Client 8 | # @private 9 | class ClientSpacePeriodicUsageMethodsFactory 10 | include Contentful::Management::ClientAssociationMethodsFactory 11 | 12 | def initialize(client, organization_id) 13 | super(client) 14 | @organization_id = organization_id 15 | end 16 | 17 | def all(params = {}) 18 | @resource_requester.all( 19 | { 20 | organization_id: @organization_id 21 | }, 22 | params 23 | ) 24 | end 25 | 26 | def new(*) 27 | fail 'Not supported' 28 | end 29 | 30 | def find(*) 31 | fail 'Not supported' 32 | end 33 | 34 | def create(*) 35 | fail 'Not supported' 36 | end 37 | end 38 | end 39 | end 40 | -------------------------------------------------------------------------------- /lib/contentful/management/client_webhook_call_methods_factory.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative 'client_association_methods_factory' 4 | 5 | module Contentful 6 | module Management 7 | # Wrapper for Webhook Call API for usage from within Client 8 | # @private 9 | class ClientWebhookCallMethodsFactory 10 | include Contentful::Management::ClientAssociationMethodsFactory 11 | 12 | def initialize(client, space_id, webhook_id) 13 | super(client, space_id) 14 | @webhook_id = webhook_id 15 | end 16 | 17 | def all(_params = {}) 18 | @resource_requester.find( 19 | space_id: @space_id, 20 | webhook_id: @webhook_id 21 | ) 22 | end 23 | 24 | def find(call_id) 25 | @resource_requester.find( 26 | space_id: @space_id, 27 | webhook_id: @webhook_id, 28 | call_id: call_id 29 | ) 30 | end 31 | 32 | def new(*) 33 | fail 'Not supported' 34 | end 35 | end 36 | end 37 | end 38 | -------------------------------------------------------------------------------- /lib/contentful/management/client_organization_periodic_usage_methods_factory.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative 'client_association_methods_factory' 4 | 5 | module Contentful 6 | module Management 7 | # Wrapper for Organization Periodic Usages for usage from within Client 8 | # @private 9 | class ClientOrganizationPeriodicUsageMethodsFactory 10 | include Contentful::Management::ClientAssociationMethodsFactory 11 | 12 | def initialize(client, organization_id) 13 | super(client) 14 | @organization_id = organization_id 15 | end 16 | 17 | def all(params = {}) 18 | @resource_requester.all( 19 | { 20 | organization_id: @organization_id 21 | }, 22 | params 23 | ) 24 | end 25 | 26 | def new(*) 27 | fail 'Not supported' 28 | end 29 | 30 | def find(*) 31 | fail 'Not supported' 32 | end 33 | 34 | def create(*) 35 | fail 'Not supported' 36 | end 37 | end 38 | end 39 | end 40 | -------------------------------------------------------------------------------- /lib/contentful/management/client_taxonomy_concept_methods_factory.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative 'client_association_methods_factory' 4 | 5 | module Contentful 6 | module Management 7 | # Wrapper for Taxonomy Concept API for usage from within Client 8 | # @private 9 | class ClientTaxonomyConceptMethodsFactory 10 | include Contentful::Management::ClientAssociationMethodsFactory 11 | 12 | def initialize(client, organization_id) 13 | super(client) 14 | @organization_id = organization_id 15 | end 16 | 17 | def find(resource_id) 18 | associated_class.find(client, @organization_id, resource_id) 19 | end 20 | 21 | def all(query = {}) 22 | associated_class.all(client, @organization_id, query) 23 | end 24 | 25 | def create(attributes) 26 | associated_class.create(client, @organization_id, attributes) 27 | end 28 | 29 | def total 30 | associated_class.total(client, @organization_id) 31 | end 32 | end 33 | end 34 | end 35 | -------------------------------------------------------------------------------- /lib/contentful/management/webhook_webhook_call_methods_factory.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative 'resource_requester' 4 | 5 | module Contentful 6 | module Management 7 | # Wrapper for webhook call detail manipulation for a specific webhook. 8 | # @private 9 | class WebhookWebhookCallMethodsFactory 10 | attr_reader :webhook 11 | 12 | # @private 13 | def initialize(webhook) 14 | @webhook = webhook 15 | end 16 | 17 | # Gets all webhook call details for a specific webhook. 18 | # 19 | # @return [Contentful::Management::Array] 20 | def all(_params = {}) 21 | WebhookCall.all(webhook.client, webhook.space.id, webhook.id) 22 | end 23 | 24 | # Gets a webhook call detail for a specific webhook by ID. 25 | # 26 | # @return [Contentful::Management::WebhookCall] 27 | def find(call_id) 28 | WebhookCall.find(webhook.client, webhook.space.id, webhook.id, call_id) 29 | end 30 | end 31 | end 32 | end 33 | -------------------------------------------------------------------------------- /lib/contentful/management/client_taxonomy_concept_scheme_methods_factory.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative 'client_association_methods_factory' 4 | 5 | module Contentful 6 | module Management 7 | # Wrapper for Taxonomy Concept Scheme API for usage from within Client 8 | # @private 9 | class ClientTaxonomyConceptSchemeMethodsFactory 10 | include Contentful::Management::ClientAssociationMethodsFactory 11 | 12 | def initialize(client, organization_id) 13 | super(client) 14 | @organization_id = organization_id 15 | end 16 | 17 | def find(resource_id) 18 | associated_class.find(client, @organization_id, resource_id) 19 | end 20 | 21 | def all(query = {}) 22 | associated_class.all(client, @organization_id, query) 23 | end 24 | 25 | def create(attributes) 26 | associated_class.create(client, @organization_id, attributes) 27 | end 28 | 29 | def total 30 | associated_class.total(client, @organization_id) 31 | end 32 | end 33 | end 34 | end 35 | -------------------------------------------------------------------------------- /lib/contentful/management/preview_api_key.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative 'resource' 4 | 5 | module Contentful 6 | module Management 7 | # Resource class for PreviewApiKey. 8 | # @see _ https://www.contentful.com/developers/docs/references/content-management-api/#/reference/api-keys/preview-api-key/get-a-single-preview-api-key 9 | class PreviewApiKey 10 | include Contentful::Management::Resource 11 | include Contentful::Management::Resource::Refresher 12 | include Contentful::Management::Resource::SystemProperties 13 | 14 | property :name 15 | property :description 16 | property :accessToken 17 | property :environments 18 | 19 | # Finds a Preview API Key by ID. 20 | # 21 | # @param [Contentful::Management::Client] client 22 | # @param [String] space_id 23 | # @param [String] preview_api_key_id 24 | # 25 | # @return [Contentful::Management::PreviewApiKey] 26 | def self.find(client, space_id, preview_api_key_id) 27 | super(client, space_id, nil, preview_api_key_id) 28 | end 29 | end 30 | end 31 | end 32 | -------------------------------------------------------------------------------- /examples/content_types.rb: -------------------------------------------------------------------------------- 1 | require 'pry' 2 | 3 | access_token = 'access token' 4 | organization = 'organization id' 5 | 6 | require 'contentful/management' 7 | 8 | client = Contentful::Management::Client.new(access_token) 9 | space = Contentful::Management::Space.create(name: 'MySpace', organization_id: organization) 10 | 11 | p space.content_types 12 | 13 | type1 = space.content_types.create(name: 'ContentType 1') 14 | 15 | p space.content_types.all 16 | 17 | field = Contentful::Management::Field.new 18 | field.id = 'such_content' 19 | field.name = 'Such Content' 20 | field.type = 'Text' # content types maybe as symbol? 21 | 22 | type2 = space.content_types.new 23 | type2.name = 'ContentType 2' 24 | type2.fields = [field] 25 | type2.save 26 | 27 | field2 = Contentful::Management::Field.new 28 | field2.id = 'wow_content' 29 | field2.name = 'Wow Content' 30 | field2.type = 'Location' # content types maybe as symbol? 31 | 32 | type2.update(name: 'whoat', fields: [field, field2]) 33 | 34 | type2.fields.add(field2) 35 | 36 | type2.activate 37 | p type2.active? 38 | type2.deactivate 39 | 40 | type1.destroy 41 | 42 | # clean up afterwards! 43 | space.destroy 44 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Contentful GmbH 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /lib/contentful/management/client_association_all_published_method_factory.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Contentful 4 | module Management 5 | # Wrapper for /public API for usage from within Client Wrapper Classes 6 | # @private 7 | module ClientAssociationAllPublishedMethodsFactory 8 | # Gets a collection of published resources. 9 | # 10 | # @param [Hash] params 11 | # @see _ For complete option list: https://www.contentful.com/developers/docs/references/content-delivery-api/#/reference/search-parameters 12 | # @deprecated This call will be soon removed from the API except for Content Types 13 | # 14 | # @return [Contentful::Management::Array] 15 | def all_published(params = {}) 16 | warn('This call will soon be removed from the API except for Content Types') unless params.key?(:suppress_warning) 17 | params.delete(:suppress_warning) if params.key?(:suppress_warning) 18 | 19 | @resource_requester.all( 20 | { space_id: @space_id, environment_id: @environment_id, public: true }, 21 | params 22 | ) 23 | end 24 | end 25 | end 26 | end 27 | -------------------------------------------------------------------------------- /lib/contentful/management/resource/all_published.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Contentful 4 | module Management 5 | module Resource 6 | # Wrapper Class for Resources with '/public' API calls 7 | module AllPublished 8 | # Gets a collection of published resources. 9 | # 10 | # @param [Contentful::Management::Client] client 11 | # @param [String] space_id 12 | # @param [Hash] parameters 13 | # @see _ For complete option list: https://www.contentful.com/developers/docs/references/content-delivery-api/#/reference/search-parameters 14 | # @option parameters [String] 'sys.id' Entry ID 15 | # @option parameters [String] :content_type 16 | # @option parameters [Integer] :limit 17 | # @option parameters [Integer] :skip 18 | # @deprecated This call will be soon removed from the API except for Content Types 19 | # 20 | # @return [Contentful::Management::Array] 21 | def all_published(client, space_id, environment_id, parameters = {}) 22 | client_association_class.new(client, space_id, environment_id).all_published(parameters) 23 | end 24 | end 25 | end 26 | end 27 | end 28 | -------------------------------------------------------------------------------- /lib/contentful/management/space_association_methods_factory.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative 'resource_requester' 4 | 5 | module Contentful 6 | module Management 7 | # Wrapper for Space Association Methods 8 | # @private 9 | module SpaceAssociationMethodsFactory 10 | attr_reader :space 11 | 12 | def initialize(space) 13 | @space = space 14 | end 15 | 16 | def all(params = {}) 17 | associated_class.all(space.client, space.id, nil, params) 18 | end 19 | 20 | def find(id) 21 | associated_class.find(space.client, space.id, id) 22 | end 23 | 24 | def create(attributes) 25 | associated_class.create(space.client, space.id, attributes) 26 | end 27 | 28 | def new 29 | object = associated_class.new 30 | object.sys[:space] = space 31 | object.client = space.client 32 | object 33 | end 34 | 35 | def associated_class 36 | class_name = /\A(.+)Space(.+)MethodsFactory\z/.match(self.class.name).captures.join 37 | class_name.split('::').reduce(Object) do |mod, actual_class_name| 38 | mod.const_get(actual_class_name) 39 | end 40 | end 41 | end 42 | end 43 | end 44 | -------------------------------------------------------------------------------- /lib/contentful/management/link.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative 'resource' 4 | 5 | module Contentful 6 | module Management 7 | # Resource Class for Links 8 | # https://www.contentful.com/developers/documentation/content-delivery-api/#links 9 | class Link 10 | include Contentful::Management::Resource 11 | include Contentful::Management::Resource::SystemProperties 12 | 13 | # Queries contentful for the Resource the Link is referring to 14 | # @param [String] space_id 15 | # @param [String] environment_id 16 | def resolve(space_id = nil, environment_id = nil) 17 | return client.spaces.find(id) if link_type == 'Space' 18 | 19 | method = Contentful::Management::Support.base_path_for(link_type).to_sym 20 | 21 | if space_id && environment_id.nil? 22 | return client.public_send( 23 | method, 24 | space_id 25 | ).find(id) 26 | elsif space_id && environment_id 27 | return client.public_send( 28 | method, 29 | space_id, 30 | environment_id 31 | ).find(id) 32 | end 33 | 34 | client.public_send(method).find(id) 35 | end 36 | end 37 | end 38 | end 39 | -------------------------------------------------------------------------------- /lib/contentful/management/resource/refresher.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Contentful 4 | module Management 5 | module Resource 6 | # Adds the feature to have properties and system data reload for Resource. 7 | module Refresher 8 | # Reload an object 9 | # Updates the current version of the object to the version on the system 10 | def reload 11 | resource = refresh_find 12 | refresh_data(resource) if resource.is_a? self.class 13 | end 14 | 15 | # @private 16 | def refresh_find 17 | return self.class.find(client, space.id, environment_id, id) if environment_id 18 | 19 | self.class.find(client, space.id, id) 20 | end 21 | 22 | # @private 23 | def refresh_data(resource) 24 | if resource.is_a? Error 25 | resource 26 | else 27 | @properties = resource.instance_variable_get(:@properties) 28 | @fields = resource.instance_variable_get(:@fields) 29 | @sys = resource.instance_variable_get(:@sys).merge(locale: locale) 30 | @_metadata = resource.instance_variable_get(:@_metadata) 31 | self 32 | end 33 | end 34 | end 35 | end 36 | end 37 | end 38 | -------------------------------------------------------------------------------- /lib/contentful/management/user.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative 'resource' 4 | 5 | module Contentful 6 | module Management 7 | # Resource class for User. 8 | # @see _ https://www.contentful.com/developers/docs/references/content-management-api/#/reference/users 9 | class User 10 | include Contentful::Management::Resource 11 | include Contentful::Management::Resource::Refresher 12 | include Contentful::Management::Resource::SystemProperties 13 | 14 | property :email, :string 15 | property :lastName, :string 16 | property :firstName, :string 17 | property :avatarUrl, :string 18 | property :activated, :boolean 19 | property :confirmed, :boolean 20 | property :signInCount, :integer 21 | 22 | # @private 23 | def self.build_endpoint(endpoint_options) 24 | endpoint = if endpoint_options[:space_id] 25 | "spaces/#{endpoint_options[:space_id]}/users" 26 | elsif endpoint_options[:organization_id] 27 | "organizations/#{endpoint_options[:organization_id]}/users" 28 | else 29 | 'users' 30 | end 31 | endpoint = "#{endpoint}/#{endpoint_options[:resource_id]}" if endpoint_options[:resource_id] 32 | endpoint 33 | end 34 | end 35 | end 36 | end 37 | -------------------------------------------------------------------------------- /lib/contentful/management/array.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative 'resource' 4 | require_relative 'resource/array_like' 5 | 6 | module Contentful 7 | module Management 8 | # Resource Class for Arrays (e.g. search results) 9 | # @see _ https://www.contentful.com/developers/documentation/content-delivery-api/#arrays 10 | # @note It also provides an #each method and includes Ruby's Enumerable module (gives you methods like #min, #first, etc) 11 | class Array 12 | # @private 13 | DEFAULT_LIMIT = 100 14 | 15 | include Contentful::Management::Resource 16 | include Contentful::Management::Resource::ArrayLike 17 | include Contentful::Management::Resource::SystemProperties 18 | 19 | property :items 20 | property :skip, :integer 21 | property :total, :integer 22 | property :limit, :integer 23 | 24 | # Simplifies pagination 25 | def next_page 26 | if request 27 | new_skip = (skip || 0) + (limit || DEFAULT_LIMIT) 28 | new_request = request.copy 29 | new_request.instance_variable_set(:@query, {}) if new_request.query.nil? 30 | new_request.query[:skip] = new_skip 31 | response = new_request.get 32 | ResourceBuilder.new(response, client).run 33 | else 34 | false 35 | end 36 | end 37 | end 38 | end 39 | end 40 | -------------------------------------------------------------------------------- /lib/contentful/management/tag.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative 'resource' 4 | require_relative 'resource/environment_aware' 5 | 6 | module Contentful 7 | module Management 8 | # Resource Class for Tags 9 | # https://www.contentful.com/developers/docs/references/content-management-api/#/reference/content-tags 10 | class Tag 11 | include Contentful::Management::Resource 12 | include Contentful::Management::Resource::Refresher 13 | include Contentful::Management::Resource::SystemProperties 14 | include Contentful::Management::Resource::EnvironmentAware 15 | 16 | property :name 17 | 18 | # @private 19 | def self.create_attributes(_client, attributes) 20 | return {} if attributes.nil? || attributes.empty? 21 | 22 | { 23 | 'name' => attributes.fetch(:name), 24 | 'sys' => { 25 | 'visibility' => attributes.fetch(:visibility, 'private'), 26 | 'id' => attributes.fetch(:id), 27 | 'type' => 'Tag' 28 | } 29 | } 30 | end 31 | 32 | def destroy 33 | ResourceRequester.new(client, self.class).destroy( 34 | { space_id: space.id, 35 | environment_id: environment_id, 36 | resource_id: id }, 37 | {}, 38 | version: sys[:version] 39 | ) 40 | end 41 | end 42 | end 43 | end 44 | -------------------------------------------------------------------------------- /lib/contentful/management/client_editor_interface_methods_factory.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative 'editor_interface' 4 | require_relative 'client_association_methods_factory' 5 | 6 | module Contentful 7 | module Management 8 | # Wrapper for EditorInterface API for usage from within Client 9 | # @private 10 | class ClientEditorInterfaceMethodsFactory 11 | attr_reader :client 12 | 13 | def initialize(client, space_id, environment_id, content_type_id) 14 | @client = client 15 | @resource_requester = ResourceRequester.new(client, associated_class) 16 | @space_id = space_id 17 | @environment_id = environment_id 18 | @content_type_id = content_type_id 19 | end 20 | 21 | # Gets the Default Editor Interface 22 | # 23 | # @see _ For complete option list: https://www.contentful.com/developers/docs/references/content-delivery-api/#/reference/search-parameters 24 | # 25 | # @return [Contentful::Management::EditorInterface] 26 | def default 27 | @resource_requester.all( 28 | space_id: @space_id, 29 | environment_id: @environment_id, 30 | content_type_id: @content_type_id, 31 | editor_id: 'default' 32 | ) 33 | end 34 | 35 | private 36 | 37 | def associated_class 38 | EditorInterface 39 | end 40 | end 41 | end 42 | end 43 | -------------------------------------------------------------------------------- /lib/contentful/management/client_snapshot_methods_factory.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative 'client_association_methods_factory' 4 | 5 | module Contentful 6 | module Management 7 | # Wrapper for Webhook API for usage from within Client 8 | # @private 9 | class ClientSnapshotMethodsFactory 10 | include Contentful::Management::ClientAssociationMethodsFactory 11 | 12 | def initialize(client, space_id, environment_id, resource_type) 13 | super(client, space_id, environment_id) 14 | @resource_type = resource_type 15 | end 16 | 17 | def create(*) 18 | fail 'Not supported' 19 | end 20 | 21 | def all(resource_id, params = {}) 22 | @resource_requester.all( 23 | { 24 | resource_type: @resource_type, 25 | space_id: @space_id, 26 | environment_id: @environment_id, 27 | resource_id: resource_id 28 | }, 29 | params 30 | ) 31 | end 32 | 33 | def find(resource_id, snapshot_id) 34 | @resource_requester.find( 35 | resource_type: @resource_type, 36 | space_id: @space_id, 37 | environment_id: @environment_id, 38 | resource_id: resource_id, 39 | snapshot_id: snapshot_id 40 | ) 41 | end 42 | 43 | def new(*) 44 | fail 'Not supported' 45 | end 46 | end 47 | end 48 | end 49 | -------------------------------------------------------------------------------- /lib/contentful/management/resource/archiver.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Contentful 4 | module Management 5 | module Resource 6 | # Wrapper for Resources with /archived API 7 | module Archiver 8 | # Archives a resource. 9 | # 10 | # @return [Contentful::Management::Resource] 11 | def archive 12 | ResourceRequester.new(client, self.class).archive( 13 | self, 14 | { 15 | space_id: space.id, 16 | environment_id: environment_id, 17 | resource_id: id, 18 | suffix: '/archived' 19 | }, 20 | version: sys[:version] 21 | ) 22 | end 23 | 24 | # Unarchives a resource. 25 | # 26 | # @return [Contentful::Management::Resource] 27 | def unarchive 28 | ResourceRequester.new(client, self.class).unarchive( 29 | self, 30 | { 31 | space_id: space.id, 32 | environment_id: environment_id, 33 | resource_id: id, 34 | suffix: '/archived' 35 | }, 36 | version: sys[:version] 37 | ) 38 | end 39 | 40 | # Checks if a resource is archived. 41 | # 42 | # @return [Boolean] 43 | def archived? 44 | sys[:archivedAt] ? true : false 45 | end 46 | end 47 | end 48 | end 49 | end 50 | -------------------------------------------------------------------------------- /lib/contentful/management/environment_association_methods_factory.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative 'resource_requester' 4 | 5 | module Contentful 6 | module Management 7 | # Wrapper for Environment Association Methods 8 | # @private 9 | module EnvironmentAssociationMethodsFactory 10 | attr_reader :environment 11 | 12 | def initialize(environment) 13 | @environment = environment 14 | end 15 | 16 | def all(params = {}) 17 | associated_class.all(environment.client, environment.sys[:space].id, environment.id, params) 18 | end 19 | 20 | def find(id) 21 | associated_class.find(environment.client, environment.sys[:space].id, environment.id, id) 22 | end 23 | 24 | def create(attributes = {}) 25 | associated_class.create(environment.client, environment.sys[:space].id, environment.id, attributes) 26 | end 27 | 28 | def new 29 | object = associated_class.new 30 | object.sys[:space] = environment.space 31 | object.sys[:environment] = environment 32 | object.client = environment.client 33 | object 34 | end 35 | 36 | def associated_class 37 | class_name = /\A(.+)Environment(.+)MethodsFactory\z/.match(self.class.name).captures.join 38 | class_name.split('::').reduce(Object) do |mod, actual_class_name| 39 | mod.const_get(actual_class_name) 40 | end 41 | end 42 | end 43 | end 44 | end 45 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/get_request.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: get 5 | uri: http://mockbin.org/bin/be499b1d-286a-4d22-8d26-00a014b83817?foo=bar 6 | body: 7 | encoding: US-ASCII 8 | string: '' 9 | headers: 10 | X-Contentful-User-Agent: 11 | - sdk contentful-management.rb/1.8.1; platform ruby/2.4.1; os macOS/16; 12 | Authorization: 13 | - Bearer 14 | Content-Type: 15 | - application/vnd.contentful.management.v1+json 16 | Connection: 17 | - close 18 | Host: 19 | - mockbin.org 20 | User-Agent: 21 | - http.rb/2.2.2 22 | response: 23 | status: 24 | code: 200 25 | message: OK 26 | headers: 27 | Date: 28 | - Tue, 03 Oct 2017 20:23:30 GMT 29 | Content-Type: 30 | - text/html; charset=utf-8 31 | Transfer-Encoding: 32 | - chunked 33 | Connection: 34 | - close 35 | Set-Cookie: 36 | - __cfduid=df1794ea112f7de36ff53566fc22ece8b1507062210; expires=Wed, 03-Oct-18 37 | 20:23:30 GMT; path=/; domain=.mockbin.org; HttpOnly 38 | Vary: 39 | - Accept-Encoding 40 | Via: 41 | - 1.1 vegur 42 | Server: 43 | - cloudflare-nginx 44 | Cf-Ray: 45 | - 3a829e9fb15c52f0-MIA 46 | body: 47 | encoding: UTF-8 48 | string: |- 49 | { 50 | "status": "ok" 51 | } 52 | http_version: 53 | recorded_at: Tue, 03 Oct 2017 20:23:30 GMT 54 | recorded_with: VCR 3.0.3 55 | -------------------------------------------------------------------------------- /lib/contentful/management/locale.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative 'resource' 4 | require_relative 'resource/environment_aware' 5 | 6 | module Contentful 7 | module Management 8 | # Resource class for Locale. 9 | class Locale 10 | include Contentful::Management::Resource 11 | include Contentful::Management::Resource::SystemProperties 12 | include Contentful::Management::Resource::Refresher 13 | include Contentful::Management::Resource::EnvironmentAware 14 | 15 | property :code, :string 16 | property :name, :string 17 | property :publish, :boolean 18 | property :default, :boolean 19 | property :optional, :boolean 20 | property :fallbackCode, :string 21 | property :contentDeliveryApi, :boolean 22 | property :contentManagementApi, :boolean 23 | 24 | # @private 25 | def self.create_attributes(_client, attributes) 26 | { 27 | 'name' => attributes.fetch(:name), 28 | 'code' => attributes.fetch(:code), 29 | 'optional' => attributes.fetch(:optional, false), 30 | 'fallbackCode' => attributes.fetch(:fallback_code, nil) 31 | } 32 | end 33 | 34 | protected 35 | 36 | def query_attributes(attributes) 37 | { 38 | name: name, 39 | code: code, 40 | optional: optional, 41 | fallbackCode: fallback_code 42 | }.merge( 43 | attributes.transform_keys(&:to_sym) 44 | ) 45 | end 46 | end 47 | end 48 | end 49 | -------------------------------------------------------------------------------- /lib/contentful/management/validation.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative 'resource' 4 | 5 | module Contentful 6 | module Management 7 | # A ContentType's validations schema 8 | class Validation 9 | # Properties not specific to a field type validation 10 | NON_TYPE_PROPERTIES = %i[validations message].freeze 11 | 12 | include Contentful::Management::Resource 13 | 14 | property :in, :array 15 | property :size, :hash 16 | property :range, :hash 17 | property :regexp, :hash 18 | property :unique, :boolean 19 | property :present, :boolean 20 | property :linkField, :boolean 21 | property :assetFileSize, :hash 22 | property :linkContentType, :array 23 | property :linkMimetypeGroup, :string 24 | property :assetImageDimensions, :hash 25 | property :enabledNodeTypes, :array 26 | property :enabledMarks, :array 27 | property :nodes, :hash 28 | property :message, :string 29 | 30 | # @private 31 | def properties_to_hash 32 | properties.each_with_object({}) do |(key, value), results| 33 | results[key] = value if Field.value_exists?(value) 34 | end 35 | end 36 | 37 | # Returns type of validation 38 | # @return [Symbol] 39 | def type 40 | properties.keys.reject { |key| NON_TYPE_PROPERTIES.include?(key) }.each do |type| 41 | value = send(Support.snakify(type)) 42 | return type if !value.nil? && value 43 | end 44 | end 45 | end 46 | end 47 | end 48 | -------------------------------------------------------------------------------- /lib/contentful/management/personal_access_token.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative 'resource' 4 | 5 | module Contentful 6 | module Management 7 | # Resource class for PersonalAccessToken. 8 | # @see _ https://www.contentful.com/developers/docs/references/content-management-api/#/reference/personal-access-tokens 9 | class PersonalAccessToken 10 | include Contentful::Management::Resource 11 | include Contentful::Management::Resource::Refresher 12 | include Contentful::Management::Resource::SystemProperties 13 | 14 | property :name, :string 15 | property :scopes, :array 16 | property :token, :string 17 | property :revokedAt, :date 18 | 19 | # @private 20 | def self.build_endpoint(endpoint_options) 21 | endpoint = 'users/me/access_tokens' 22 | endpoint = "#{endpoint}/#{endpoint_options[:resource_id]}" if endpoint_options[:resource_id] 23 | endpoint = "#{endpoint}#{endpoint_options[:suffix]}" if endpoint_options[:suffix] 24 | endpoint 25 | end 26 | 27 | # @private 28 | def self.create_attributes(_client, attributes) 29 | attributes 30 | end 31 | 32 | # Not supported 33 | def destroy 34 | fail 'Not supported' 35 | end 36 | 37 | # Revokes the personal access token. 38 | def revoke 39 | ResourceRequester.new(client, self.class).update( 40 | self, 41 | resource_id: id, 42 | suffix: '/revoked' 43 | ) 44 | end 45 | end 46 | end 47 | end 48 | -------------------------------------------------------------------------------- /spec/lib/contentful/management/space_periodic_usage_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | require 'contentful/management/space' 3 | require 'contentful/management/client' 4 | 5 | module Contentful 6 | module Management 7 | describe SpacePeriodicUsage do 8 | let(:token) { ENV.fetch('CF_TEST_CMA_TOKEN', '') } 9 | let(:organization_id) { 'org_id' } 10 | 11 | let!(:client) { Client.new(token) } 12 | 13 | subject { client.space_periodic_usages(organization_id) } 14 | 15 | describe '.all' do 16 | it 'class method also works' do 17 | vcr('space_periodic_usage/all') { expect(Contentful::Management::SpacePeriodicUsage.all(client, organization_id)).to be_kind_of Contentful::Management::Array } 18 | end 19 | it 'returns a Contentful::Array' do 20 | vcr('space_periodic_usage/all') { expect(subject.all).to be_kind_of Contentful::Management::Array } 21 | end 22 | it 'builds a Contentful::Management::SpacePeriodicUsage object' do 23 | vcr('space_periodic_usage/all') { expect(subject.all.first).to be_kind_of Contentful::Management::SpacePeriodicUsage } 24 | end 25 | it 'builds a Contentful::Management::SpacePeriodicUsage object' do 26 | vcr('space_periodic_usage/filters') { 27 | result = subject.all('metric[in]' => 'cda') 28 | expect(result.all? { |pu| pu.metric == 'cda' }).to be_truthy 29 | expect(result.first).to be_kind_of Contentful::Management::SpacePeriodicUsage 30 | expect(result.first.metric).to eq 'cda' 31 | } 32 | end 33 | end 34 | end 35 | end 36 | end 37 | -------------------------------------------------------------------------------- /lib/contentful/management/client_space_methods_factory.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative 'resource_requester' 4 | 5 | module Contentful 6 | module Management 7 | # Wrapper for Space API for usage from within Client 8 | # @private 9 | class ClientSpaceMethodsFactory 10 | attr_reader :client 11 | 12 | def initialize(client) 13 | @client = client 14 | @resource_requester = ResourceRequester.new(client, associated_class) 15 | end 16 | 17 | # Gets a collection of spaces. 18 | # 19 | # @return [Contentful::Management::Array] 20 | def all(query = {}) 21 | @resource_requester.all({}, query) 22 | end 23 | 24 | # Gets a specific space. 25 | # 26 | # @param [String] space_id 27 | # 28 | # @return [Contentful::Management::Space] 29 | def find(space_id) 30 | @resource_requester.find(space_id: space_id) 31 | end 32 | 33 | # Create a space. 34 | # 35 | # @param [Hash] attributes 36 | # @option attributes [String] :name 37 | # @option attributes [String] :default_locale 38 | # @option attributes [String] :organization_id Required if user has more than one organization 39 | # 40 | # @return [Contentful::Management::Space] 41 | def create(attributes) 42 | associated_class.create(client, attributes) 43 | end 44 | 45 | def new 46 | object = associated_class.new 47 | object.client = client 48 | object 49 | end 50 | 51 | def associated_class 52 | ::Contentful::Management::Space 53 | end 54 | end 55 | end 56 | end 57 | -------------------------------------------------------------------------------- /spec/lib/contentful/management/organization_periodic_usage_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | require 'contentful/management/space' 3 | require 'contentful/management/client' 4 | 5 | module Contentful 6 | module Management 7 | describe OrganizationPeriodicUsage do 8 | let(:token) { ENV.fetch('CF_TEST_CMA_TOKEN', '') } 9 | let(:organization_id) { 'org_id' } 10 | 11 | let!(:client) { Client.new(token) } 12 | 13 | subject { client.organization_periodic_usages(organization_id) } 14 | 15 | describe '.all' do 16 | it 'class method also works' do 17 | vcr('organization_periodic_usage/all') { expect(Contentful::Management::OrganizationPeriodicUsage.all(client, organization_id)).to be_kind_of Contentful::Management::Array } 18 | end 19 | it 'returns a Contentful::Array' do 20 | vcr('organization_periodic_usage/all') { expect(subject.all).to be_kind_of Contentful::Management::Array } 21 | end 22 | it 'builds a Contentful::Management::OrganizationPeriodicUsage object' do 23 | vcr('organization_periodic_usage/all') { expect(subject.all.first).to be_kind_of Contentful::Management::OrganizationPeriodicUsage } 24 | end 25 | it 'builds a Contentful::Management::OrganizationPeriodicUsage object' do 26 | vcr('organization_periodic_usage/filters') { 27 | result = subject.all('metric[in]' => 'cda') 28 | expect(result.size).to eq 1 29 | expect(result.first).to be_kind_of Contentful::Management::OrganizationPeriodicUsage 30 | expect(result.first.metric).to eq 'cda' 31 | } 32 | end 33 | end 34 | end 35 | end 36 | end 37 | -------------------------------------------------------------------------------- /lib/contentful/management/resource/metadata.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Contentful 4 | module Management 5 | module Resource 6 | # Adds metadata logic for [Resource] classes 7 | module Metadata 8 | # Returns the metadata hash 9 | attr_reader :_metadata 10 | 11 | # @private 12 | def initialize(object = nil, *) 13 | super 14 | @_metadata = {} 15 | extract_metadata_from_object! object if object 16 | end 17 | 18 | # @private 19 | def inspect(info = nil) 20 | if _metadata.empty? 21 | super(info) 22 | else 23 | super("#{info} @_metadata=#{_metadata.inspect}") 24 | end 25 | end 26 | 27 | private 28 | 29 | def extract_metadata_from_object!(object) 30 | return unless object.key?('metadata') 31 | 32 | object['metadata'].each do |key, value| 33 | @_metadata[key.to_sym] = case key 34 | when 'tags' 35 | coerce_tags(value) 36 | when 'concepts' 37 | coerce_concepts(value) 38 | else 39 | value 40 | end 41 | end 42 | end 43 | 44 | def coerce_tags(tags) 45 | tags.map { |tag| Contentful::Management::Link.new(tag) } 46 | end 47 | 48 | def coerce_concepts(concepts) 49 | concepts.map { |concept| Contentful::Management::Link.new(concept) } 50 | end 51 | end 52 | end 53 | end 54 | end 55 | -------------------------------------------------------------------------------- /spec/lib/contentful/management/array_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | require 'contentful/management/space' 3 | require 'contentful/management/client' 4 | 5 | describe Contentful::Management::Array do 6 | let(:token) { '' } 7 | let(:space_id) { 'yr5m0jky5hsh' } 8 | let!(:client) { Contentful::Management::Client.new(token) } 9 | let(:array) { vcr('space/all') { client.spaces.all } } 10 | 11 | describe 'SystemProperties' do 12 | it 'has a #sys getter returning a hash with symbol keys' do 13 | expect(array.sys).to be_a Hash 14 | expect(array.sys.keys.sample).to be_a Symbol 15 | end 16 | 17 | it 'has #type' do 18 | expect(array.type).to eq 'Array' 19 | end 20 | end 21 | 22 | describe 'Properties' do 23 | it 'has a #properties getter returning a hash with symbol keys' do 24 | expect(array.properties).to be_a Hash 25 | expect(array.properties.keys.sample).to be_a Symbol 26 | end 27 | 28 | it 'has #total' do 29 | expect(array.total).to eq 6 30 | end 31 | 32 | it 'has #skip' do 33 | expect(array.skip).to eq 0 34 | end 35 | 36 | it 'has #limit' do 37 | expect(array.limit).to eq 25 38 | end 39 | 40 | it 'has #items which contain resources' do 41 | expect(array.items).to be_a Array 42 | expect(array.items.sample).to be_a Contentful::Management::Resource 43 | end 44 | end 45 | 46 | describe '#each' do 47 | it 'is an Enumerator' do 48 | expect(array.each).to be_a Enumerator 49 | end 50 | 51 | it 'iterates over items' do 52 | expect(array.each.to_a).to eq array.items 53 | end 54 | 55 | it 'includes Enumerable' do 56 | expect(array.map { |r| r.type }).to eq array.items.map { |r| r.type } 57 | end 58 | end 59 | end 60 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/entry/service_unavailable.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: get 5 | uri: https://api.contentful.com/spaces/yr5m0jky5hsh/environments/master/entries/not_exist 6 | body: 7 | encoding: US-ASCII 8 | string: '' 9 | headers: 10 | User-Agent: 11 | - RubyContenfulManagementGem/0.0.1 12 | Authorization: 13 | - Bearer 14 | Content-Type: 15 | - application/vnd.contentful.management.v1+json 16 | Content-Length: 17 | - '0' 18 | Host: 19 | - api.contentful.com 20 | response: 21 | status: 22 | code: 503 23 | message: Service Unavailable 24 | headers: 25 | Server: 26 | - nginx 27 | Date: 28 | - Wed, 30 Jul 2014 12:43:14 GMT 29 | Content-Type: 30 | - application/vnd.contentful.management.v1+json 31 | Transfer-Encoding: 32 | - chunked 33 | Connection: 34 | - keep-alive 35 | X-Powered-By: 36 | - Express 37 | Access-Control-Allow-Origin: 38 | - "*" 39 | Access-Control-Allow-Headers: 40 | - Accept,Accept-Language,Authorization,Cache-Control,Content-Length,Content-Range,Content-Type,DNT,Destination,Expires,If-Match,If-Modified-Since,If-None-Match,Keep-Alive,Last-Modified,Origin,Pragma,Range,User-Agent,X-Http-Method-Override,X-Mx-ReqToken,X-Requested-With,X-Contentful-Version,X-Contentful-Content-Type,X-Contentful-Organization 41 | Access-Control-Allow-Methods: 42 | - DELETE,GET,HEAD,POST,PUT,OPTIONS 43 | "^access-Control-Expose-Headers": 44 | - Etag 45 | Access-Control-Max-Age: 46 | - '1728000' 47 | body: 48 | encoding: UTF-8 49 | string: '' 50 | http_version: 51 | recorded_at: Wed, 30 Jul 2014 12:43:14 GMT 52 | recorded_with: VCR 2.9.2 53 | -------------------------------------------------------------------------------- /lib/contentful/management/content_type_snapshot_methods_factory.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative 'resource_requester' 4 | 5 | module Contentful 6 | module Management 7 | # Wrapper for Entry manipulation for a specific Content Type 8 | # @private 9 | class ContentTypeSnapshotMethodsFactory 10 | attr_reader :content_type 11 | 12 | # @private 13 | def initialize(content_type) 14 | @content_type = content_type 15 | end 16 | 17 | # Gets all snapshot for a specific content type. 18 | # 19 | # @see _ For complete option list: https://www.contentful.com/developers/docs/references/content-management-api/#/reference/snapshots/content-type-snapshots-collection 20 | # 21 | # @return [Contentful::Management::Array] 22 | def all(params = {}) 23 | Snapshot.all( 24 | content_type.client, 25 | content_type.space.id, 26 | content_type.environment_id, 27 | content_type.id, 28 | 'content_types', 29 | params 30 | ) 31 | end 32 | 33 | # Gets a snapshot by ID for a specific content type. 34 | # 35 | # @param [String] snapshot_id 36 | # @see _ For complete option list: https://www.contentful.com/developers/docs/references/content-management-api/#/reference/snapshots/content-type-snapshots-collection 37 | # 38 | # @return [Contentful::Management::Array] 39 | def find(snapshot_id) 40 | Snapshot.find( 41 | content_type.client, 42 | content_type.space.id, 43 | content_type.environment_id, 44 | content_type.id, 45 | snapshot_id, 46 | 'content_types' 47 | ) 48 | end 49 | end 50 | end 51 | end 52 | -------------------------------------------------------------------------------- /lib/contentful/management/organization.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative 'resource' 4 | require 'contentful/management/organization_user_methods_factory' 5 | 6 | module Contentful 7 | module Management 8 | # Resource class for Organization. 9 | # @see _ https://www.contentful.com/developers/docs/references/content-management-api/#/reference/organizations 10 | class Organization 11 | include Contentful::Management::Resource 12 | include Contentful::Management::Resource::Refresher 13 | include Contentful::Management::Resource::SystemProperties 14 | 15 | property :name 16 | 17 | # @private 18 | def self.build_endpoint(_endpoint_options) 19 | 'organizations' 20 | end 21 | 22 | # Allows listing all usage periods for organization grouped by organization or space. 23 | # @see _ README for details. 24 | # 25 | # @return [Contentful::Management::ClientOrganizationPeriodicUsageMethodsFactory] 26 | def periodic_usages 27 | ClientOrganizationPeriodicUsageMethodsFactory.new(client, id) 28 | end 29 | 30 | # Allows listing all usage periods for organization grouped by organization or space. 31 | # @see _ README for details. 32 | # 33 | # @return [Contentful::Management::ClientSpacePeriodicUsageMethodsFactory] 34 | def space_periodic_usages 35 | ClientSpacePeriodicUsageMethodsFactory.new(client, id) 36 | end 37 | 38 | # Allows viewing of users in context of an organization 39 | # Allows listing all users for an organization, and finding one by ID. 40 | # @see _ README for details. 41 | # 42 | # @return [Contentful::Management::OrganizationUserMethodsFactory] 43 | def users 44 | OrganizationUserMethodsFactory.new(client, id) 45 | end 46 | end 47 | end 48 | end 49 | -------------------------------------------------------------------------------- /spec/lib/contentful/management/user_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | require 'contentful/management/space' 3 | require 'contentful/management/client' 4 | 5 | module Contentful 6 | module Management 7 | describe User do 8 | let(:token) { ENV.fetch('CF_TEST_CMA_TOKEN', '') } 9 | let!(:client) { Client.new(token) } 10 | 11 | subject { client.users } 12 | 13 | describe '.all' do 14 | it 'is not supported' do 15 | expect { subject.all }.to raise_error 'Not supported' 16 | end 17 | end 18 | 19 | describe '.find' do 20 | it 'fetches the current user' do 21 | vcr('user/find') { 22 | user = subject.find('me') 23 | expect(user).to be_a Contentful::Management::User 24 | expect(user.first_name).to eq 'David' 25 | expect(user.last_name).to eq 'Test' 26 | expect(user.email).to eq 'david.test@testytest.com' 27 | expect(user.activated).to eq true 28 | expect(user.confirmed).to eq true 29 | expect(user.sign_in_count).to eq 26 30 | expect(user.avatar_url).to be_truthy 31 | } 32 | end 33 | end 34 | 35 | describe '.me' do 36 | it 'is an alias to .find("me")' do 37 | vcr('user/find') { 38 | user = subject.me 39 | expect(user).to be_a Contentful::Management::User 40 | expect(user.first_name).to eq 'David' 41 | expect(user.last_name).to eq 'Test' 42 | expect(user.email).to eq 'david.test@testytest.com' 43 | expect(user.activated).to eq true 44 | expect(user.confirmed).to eq true 45 | expect(user.sign_in_count).to eq 26 46 | expect(user.avatar_url).to be_truthy 47 | } 48 | end 49 | end 50 | end 51 | end 52 | end 53 | -------------------------------------------------------------------------------- /lib/contentful/management/client_environment_methods_factory.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative 'environment' 4 | require_relative 'resource_requester' 5 | 6 | module Contentful 7 | module Management 8 | # Wrapper for Environment API for usage from within Client 9 | # @private 10 | class ClientEnvironmentMethodsFactory 11 | attr_reader :client 12 | 13 | def initialize(client, space_id) 14 | @client = client 15 | @space_id = space_id 16 | @resource_requester = ResourceRequester.new(client, associated_class) 17 | end 18 | 19 | # Gets a collection of environments. 20 | # 21 | # @return [Contentful::Management::Array] 22 | def all(params = {}) 23 | @resource_requester.all( 24 | { 25 | space_id: @space_id 26 | }, 27 | params 28 | ) 29 | end 30 | 31 | # Gets a specific environment. 32 | # 33 | # @param [String] environment_id 34 | # 35 | # @return [Contentful::Management::Environment] 36 | def find(environment_id) 37 | @resource_requester.find( 38 | space_id: @space_id, 39 | environment_id: environment_id 40 | ) 41 | end 42 | 43 | # Create an environment. 44 | # 45 | # @param [Hash] attributes 46 | # @option attributes [String] :name 47 | # 48 | # @return [Contentful::Management::Environment] 49 | def create(attributes) 50 | associated_class.create(client, @space_id, attributes) 51 | end 52 | 53 | def new 54 | object = associated_class.new 55 | object.client = client 56 | object 57 | end 58 | 59 | def associated_class 60 | ::Contentful::Management::Environment 61 | end 62 | end 63 | end 64 | end 65 | -------------------------------------------------------------------------------- /spec/lib/contentful/management/webhook_health_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | require 'contentful/management/space' 3 | require 'contentful/management/client' 4 | 5 | module Contentful 6 | module Management 7 | describe WebhookHealth do 8 | let(:token) { ENV.fetch('CF_TEST_CMA_TOKEN', '') } 9 | let(:space_id) { 'orzkxlxlq59d' } 10 | let(:webhook_id) { '16ypL3XjNK6oreLPPoVBxI' } 11 | let!(:client) { Client.new(token) } 12 | 13 | subject { client.webhook_health(space_id) } 14 | 15 | describe '.all' do 16 | it 'is not supported' do 17 | expect { subject.all }.to raise_error 'Not supported' 18 | end 19 | end 20 | 21 | describe '.find' do 22 | it 'class method also works' do 23 | vcr('webhook_health/find') { 24 | expect(Contentful::Management::WebhookHealth.find( 25 | client, 26 | space_id, 27 | webhook_id 28 | )).to be_kind_of Contentful::Management::WebhookHealth 29 | } 30 | end 31 | it 'returns a Contentful::Management::WebhookHealth' do 32 | vcr('webhook_health/find') { expect(subject.find(webhook_id)).to be_kind_of Contentful::Management::WebhookHealth } 33 | end 34 | it 'returns webhook for a given id' do 35 | vcr('webhook_health/find') do 36 | webhook_health = subject.find(webhook_id) 37 | expect(webhook_health.calls).to be_a ::Hash 38 | 39 | expect(webhook_health.calls['total']).to eq 2 40 | expect(webhook_health.calls['healthy']).to eq 2 41 | 42 | expect(webhook_health.healthy).to eq 2 43 | expect(webhook_health.total).to eq 2 44 | expect(webhook_health.errors?).to eq false 45 | expect(webhook_health.healthy?).to eq true 46 | end 47 | end 48 | end 49 | end 50 | end 51 | end 52 | -------------------------------------------------------------------------------- /lib/contentful/management/resource/system_properties.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Contentful 4 | module Management 5 | module Resource 6 | # Adds the feature to have system properties to a Resource. 7 | module SystemProperties 8 | # @private 9 | # Coercions for System Properties to native types 10 | SYS_COERCIONS = { 11 | type: :string, 12 | id: :string, 13 | space: nil, 14 | contentType: nil, 15 | linkType: :string, 16 | revision: :integer, 17 | createdAt: :date, 18 | updatedAt: :date, 19 | publishedAt: :date, 20 | locale: :string 21 | }.freeze 22 | 23 | attr_reader :sys 24 | 25 | # @private 26 | def initialize(object = { 'sys' => nil }, *) 27 | super 28 | object ||= { 'sys' => nil } 29 | @sys = extract_from_object object['sys'], :sys 30 | end 31 | 32 | # @private 33 | def inspect(info = nil) 34 | if sys.empty? 35 | super(info) 36 | else 37 | super("#{info} @sys=#{sys.inspect}") 38 | end 39 | end 40 | 41 | # @private 42 | module ClassMethods 43 | # @private 44 | def sys_coercions 45 | SYS_COERCIONS 46 | end 47 | end 48 | 49 | # @private 50 | def self.included(base) 51 | base.extend(ClassMethods) 52 | 53 | base.sys_coercions.each_key do |name| 54 | accessor_name = Contentful::Management::Support.snakify(name) 55 | base.send :define_method, accessor_name do 56 | sys[name.to_sym] 57 | end 58 | base.send :define_method, "#{accessor_name}=" do |value| 59 | sys[name.to_sym] = value 60 | end 61 | end 62 | end 63 | end 64 | end 65 | end 66 | end 67 | -------------------------------------------------------------------------------- /lib/contentful/management/client_association_methods_factory.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative 'resource_requester' 4 | 5 | module Contentful 6 | module Management 7 | # Wrapper for Space Association Methods 8 | # @private 9 | module ClientAssociationMethodsFactory 10 | attr_reader :client 11 | 12 | def initialize(client, space_id = nil, environment_id = nil) 13 | @client = client 14 | @resource_requester = ResourceRequester.new(client, associated_class) 15 | @space_id = space_id 16 | @environment_id = environment_id 17 | end 18 | 19 | # Gets a collection of resources. 20 | # 21 | # @param [Hash] params 22 | # @see _ For complete option list: https://www.contentful.com/developers/docs/references/content-delivery-api/#/reference/search-parameters 23 | # 24 | # @return [Contentful::Management::Array] 25 | def all(params = {}) 26 | associated_class.all(client, @space_id, @environment_id, params) 27 | end 28 | 29 | # Gets a specific resource. 30 | # 31 | # @param [String] resource_id 32 | # 33 | # @return [Contentful::Management::Resource] 34 | def find(resource_id) 35 | associated_class.find(client, @space_id, @environment_id, resource_id) 36 | end 37 | 38 | def create(attributes) 39 | associated_class.create(client, @space_id, @environment_id, attributes) 40 | end 41 | 42 | def new 43 | object = associated_class.new 44 | object.client = client 45 | object 46 | end 47 | 48 | def associated_class 49 | class_name = /\A(.+)Client(.+)MethodsFactory\z/.match(self.class.name).captures.join 50 | class_name.split('::').reduce(Object) do |mod, actual_class_name| 51 | mod.const_get(actual_class_name) 52 | end 53 | end 54 | end 55 | end 56 | end 57 | -------------------------------------------------------------------------------- /contentful-management.gemspec: -------------------------------------------------------------------------------- 1 | lib = File.expand_path('../lib', __FILE__) 2 | $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) 3 | require 'contentful/management/version' 4 | 5 | Gem::Specification.new do |spec| 6 | spec.name = 'contentful-management' 7 | spec.version = Contentful::Management::VERSION 8 | spec.authors = ['Piotr Protas','Tomasz Warkocki','Contentful GmbH (Andreas Tiefenthaler)'] 9 | spec.email = ['piotrek@codequest.com','warkocz@gmail.com', 'rubygems@contentful.com'] 10 | spec.summary = %q{contentful management api} 11 | spec.description = %q{Ruby client for the https://www.contentful.com Content Management API} 12 | spec.homepage = 'https://github.com/contentful/contentful-management.rb' 13 | spec.license = 'MIT' 14 | spec.required_ruby_version = '>= 3.0' 15 | 16 | spec.files = `git ls-files -z`.split("\x0") 17 | spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) } 18 | spec.test_files = spec.files.grep(%r{^(test|spec|features)/}) 19 | spec.require_paths = ['lib'] 20 | 21 | spec.add_dependency 'http', '~> 5.0' 22 | spec.add_dependency 'multi_json', '~> 1.15' 23 | spec.add_dependency 'json', '>= 1.8', '< 3.0' 24 | 25 | spec.add_development_dependency 'bundler' 26 | spec.add_development_dependency 'rake', '>= 12.3.3' 27 | spec.add_development_dependency 'public_suffix', '< 1.5' 28 | spec.add_development_dependency 'rspec', '~> 3' 29 | spec.add_development_dependency 'rspec-its' 30 | spec.add_development_dependency 'guard' 31 | spec.add_development_dependency 'guard-rspec' 32 | spec.add_development_dependency 'guard-rubocop' 33 | spec.add_development_dependency 'guard-yard' 34 | spec.add_development_dependency 'rubocop', '~> 1.56.2' 35 | spec.add_development_dependency 'listen', '~> 3.0' 36 | spec.add_development_dependency 'vcr', '~> 6.2.0' 37 | spec.add_development_dependency 'webmock' 38 | spec.add_development_dependency 'tins', '~> 1.6.0' 39 | spec.add_development_dependency 'simplecov' 40 | end 41 | -------------------------------------------------------------------------------- /lib/contentful/management/space_periodic_usage.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative 'resource' 4 | 5 | module Contentful 6 | module Management 7 | # Resource class for SpacePeriodicUsage. 8 | # @see _ https://www.contentful.com/developers/docs/references/content-management-api/#/reference/usage/space-usage/get-space-usage/console/curl 9 | class SpacePeriodicUsage 10 | include Contentful::Management::Resource 11 | include Contentful::Management::Resource::Refresher 12 | include Contentful::Management::Resource::SystemProperties 13 | 14 | property :metric, :string 15 | property :usage, :integer 16 | property :usagePerDay, :object 17 | property :unitOfMeasure, :string 18 | property :dateRange, :object 19 | 20 | # @private 21 | def self.build_endpoint(endpoint_options) 22 | organization_id = endpoint_options[:organization_id] 23 | 24 | "organizations/#{organization_id}/space_periodic_usages" 25 | end 26 | 27 | # Gets all space periodic usages for a given organization. 28 | # 29 | # @param [Contentful::Management::Client] client 30 | # @param [String] organization_id 31 | # @param [Hash] params 32 | # 33 | # @return [Contentful::Management::Array] 34 | def self.all(client, organization_id, params = {}) 35 | ClientSpacePeriodicUsageMethodsFactory.new(client, organization_id).all(params) 36 | end 37 | 38 | # Not supported 39 | def self.find(*) 40 | fail 'Not supported' 41 | end 42 | 43 | # @private 44 | def self.endpoint 45 | 'usages' 46 | end 47 | 48 | # Not supported 49 | def self.create(*) 50 | fail 'Not supported' 51 | end 52 | 53 | # Not supported 54 | def destroy 55 | fail 'Not supported' 56 | end 57 | 58 | # Not supported 59 | def update(*) 60 | fail 'Not supported' 61 | end 62 | end 63 | end 64 | end 65 | -------------------------------------------------------------------------------- /lib/contentful/management/dynamic_entry.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative 'resource' 4 | require_relative 'location' 5 | require_relative 'resource/fields' 6 | 7 | module Contentful 8 | module Management 9 | # Wrapper for Entries with Cached Content Types 10 | class DynamicEntry < Contentful::Management::Entry 11 | # Coercions from Contentful Types to Ruby native types 12 | KNOWN_TYPES = { 13 | 'String' => :string, 14 | 'Text' => :string, 15 | 'Symbol' => :string, 16 | 'Integer' => :integer, 17 | 'Float' => :float, 18 | 'Boolean' => :boolean, 19 | 'Date' => :date, 20 | 'Location' => Location 21 | }.freeze 22 | 23 | # @private 24 | def self.define_singleton_properties(entry_class, content_type, client) 25 | entry_class.class_eval do 26 | define_singleton_method :content_type do 27 | content_type 28 | end 29 | 30 | define_singleton_method :client do 31 | client 32 | end 33 | 34 | define_singleton_method :fields_coercions do 35 | Hash[ 36 | content_type.fields.map do |field| 37 | [field.id.to_sym, KNOWN_TYPES[field.type]] 38 | end 39 | ] 40 | end 41 | 42 | define_singleton_method :to_s do 43 | "Contentful::Management::DynamicEntry[#{content_type.id}]" 44 | end 45 | 46 | define_singleton_method :inspect do 47 | "Contentful::Management::DynamicEntry[#{content_type.id}]" 48 | end 49 | end 50 | end 51 | 52 | # @private 53 | def self.create(content_type, client) 54 | content_type = ContentType.new(content_type) unless content_type.is_a? ContentType 55 | 56 | Class.new DynamicEntry do 57 | DynamicEntry.define_singleton_properties(self, content_type, client) 58 | FieldAware.create_fields_for_content_type(self, :class) 59 | end 60 | end 61 | end 62 | end 63 | end 64 | -------------------------------------------------------------------------------- /lib/contentful/management/organization_periodic_usage.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative 'resource' 4 | 5 | module Contentful 6 | module Management 7 | # Resource class for OrganizationPeriodicUsage. 8 | # @see _ https://www.contentful.com/developers/docs/references/content-management-api/#/reference/usage/organization-usage/get-organization-usage/console/curl 9 | class OrganizationPeriodicUsage 10 | include Contentful::Management::Resource 11 | include Contentful::Management::Resource::Refresher 12 | include Contentful::Management::Resource::SystemProperties 13 | 14 | property :metric, :string 15 | property :usage, :integer 16 | property :usagePerDay, :object 17 | property :unitOfMeasure, :string 18 | property :dateRange, :object 19 | 20 | # @private 21 | def self.build_endpoint(endpoint_options) 22 | organization_id = endpoint_options[:organization_id] 23 | 24 | "organizations/#{organization_id}/organization_periodic_usages" 25 | end 26 | 27 | # Gets all organization periodic usages for a given organization. 28 | # 29 | # @param [Contentful::Management::Client] client 30 | # @param [String] organization_id 31 | # @param [Hash] params 32 | # 33 | # @return [Contentful::Management::Array] 34 | def self.all(client, organization_id, params = {}) 35 | ClientOrganizationPeriodicUsageMethodsFactory.new(client, organization_id).all(params) 36 | end 37 | 38 | # Not supported 39 | def self.find(*) 40 | fail 'Not supported' 41 | end 42 | 43 | # @private 44 | def self.endpoint 45 | 'usages' 46 | end 47 | 48 | # Not supported 49 | def self.create(*) 50 | fail 'Not supported' 51 | end 52 | 53 | # Not supported 54 | def destroy 55 | fail 'Not supported' 56 | end 57 | 58 | # Not supported 59 | def update(*) 60 | fail 'Not supported' 61 | end 62 | end 63 | end 64 | end 65 | -------------------------------------------------------------------------------- /lib/contentful/management/role.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative 'resource' 4 | 5 | module Contentful 6 | module Management 7 | # Resource class for Role. 8 | class Role 9 | include Contentful::Management::Resource 10 | include Contentful::Management::Resource::Refresher 11 | include Contentful::Management::Resource::SystemProperties 12 | 13 | property :name, :string 14 | property :policies, :array 15 | property :description, :string 16 | property :permissions, :hash 17 | 18 | # @private 19 | def self.create_attributes(_client, attributes) 20 | { 21 | 'name' => attributes.fetch(:name), 22 | 'description' => attributes.fetch(:description), 23 | 'permissions' => attributes.fetch(:permissions), 24 | 'policies' => attributes.fetch(:policies) 25 | } 26 | end 27 | 28 | # Creates a role. 29 | # 30 | # @param [Contentful::Management::Client] client 31 | # @param [String] space_id 32 | # @param [Hash] attributes 33 | # 34 | # @return [Contentful::Management::Role] 35 | def self.create(client, space_id, attributes = {}) 36 | super(client, space_id, nil, attributes) 37 | end 38 | 39 | # Finds a role by ID. 40 | # 41 | # @param [Contentful::Management::Client] client 42 | # @param [String] space_id 43 | # @param [String] role_id 44 | # 45 | # @return [Contentful::Management::Role] 46 | def self.find(client, space_id, role_id) 47 | super(client, space_id, nil, role_id) 48 | end 49 | 50 | protected 51 | 52 | def query_attributes(attributes) 53 | { 54 | name: name, 55 | description: description, 56 | permissions: permissions, 57 | policies: policies 58 | }.merge( 59 | attributes.transform_keys(&:to_sym) 60 | ) 61 | end 62 | 63 | # @private 64 | def refresh_find 65 | self.class.find(client, space.id, id) 66 | end 67 | end 68 | end 69 | end 70 | -------------------------------------------------------------------------------- /lib/contentful/management/content_type_entry_methods_factory.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative 'resource_requester' 4 | 5 | module Contentful 6 | module Management 7 | # Wrapper for Entry manipulation for a specific Content Type 8 | # @private 9 | class ContentTypeEntryMethodsFactory 10 | attr_reader :content_type 11 | 12 | # @private 13 | def initialize(content_type) 14 | @content_type = content_type 15 | end 16 | 17 | # Gets all entries for a specific ContentType 18 | # 19 | # @param [Hash] params 20 | # @see _ For complete option list: https://www.contentful.com/developers/docs/references/content-delivery-api/#/reference/search-parameters 21 | # @option params [String] 'sys.id' 22 | # @option params [String] :limit 23 | # @option params [String] :skip 24 | # @option params [String] :order 25 | # 26 | # @return [Contentful::Management::Array] 27 | def all(params = {}) 28 | Entry.all(content_type.client, content_type.space.id, content_type.environment_id, params.merge(content_type: content_type.id)) 29 | end 30 | 31 | # Creates an entry for a content type. 32 | # 33 | # @param [Hash] attributes 34 | # 35 | # @return [Contentful::Management::Entry] 36 | def create(attributes) 37 | attributes[:content_type] = content_type 38 | Entry.create(content_type.client, content_type.space.id, content_type.environment_id, attributes) 39 | end 40 | 41 | # Instantiates an empty entry for a content type. 42 | # 43 | # @return [Contentful::Management::Entry] 44 | def new 45 | dynamic_entry_class = content_type.client.register_dynamic_entry( 46 | content_type.id, 47 | DynamicEntry.create(content_type, content_type.client) 48 | ) 49 | dynamic_entry = dynamic_entry_class.new 50 | dynamic_entry.space = content_type.space 51 | dynamic_entry.content_type = content_type 52 | dynamic_entry 53 | end 54 | end 55 | end 56 | end 57 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/asset/find_not_found.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: get 5 | uri: https://api.contentful.com/spaces/yr5m0jky5hsh/environments/master/assets/not_exist 6 | body: 7 | encoding: US-ASCII 8 | string: '' 9 | headers: 10 | User-Agent: 11 | - RubyContenfulManagementGem/0.0.1 12 | Authorization: 13 | - Bearer 14 | Content-Type: 15 | - application/vnd.contentful.management.v1+json 16 | Content-Length: 17 | - '0' 18 | Host: 19 | - api.contentful.com 20 | response: 21 | status: 22 | code: 404 23 | message: Not Found 24 | headers: 25 | Server: 26 | - nginx 27 | Date: 28 | - Thu, 31 Jul 2014 07:27:40 GMT 29 | Content-Type: 30 | - application/vnd.contentful.management.v1+json 31 | Transfer-Encoding: 32 | - chunked 33 | Connection: 34 | - keep-alive 35 | X-Powered-By: 36 | - Express 37 | Access-Control-Allow-Origin: 38 | - "*" 39 | Access-Control-Allow-Headers: 40 | - Accept,Accept-Language,Authorization,Cache-Control,Content-Length,Content-Range,Content-Type,DNT,Destination,Expires,If-Match,If-Modified-Since,If-None-Match,Keep-Alive,Last-Modified,Origin,Pragma,Range,User-Agent,X-Http-Method-Override,X-Mx-ReqToken,X-Requested-With,X-Contentful-Version,X-Contentful-Content-Type,X-Contentful-Organization 41 | Access-Control-Allow-Methods: 42 | - DELETE,GET,HEAD,POST,PUT,OPTIONS 43 | "^access-Control-Expose-Headers": 44 | - Etag 45 | Access-Control-Max-Age: 46 | - '1728000' 47 | body: 48 | encoding: UTF-8 49 | string: | 50 | { 51 | "sys": { 52 | "type": "Error", 53 | "id": "NotFound" 54 | }, 55 | "message": "The resource could not be found.", 56 | "details": { 57 | "type": "Asset", 58 | "space": "yr5m0jky5hsh", 59 | "id": "not_exist" 60 | } 61 | } 62 | http_version: 63 | recorded_at: Thu, 31 Jul 2014 07:27:40 GMT 64 | recorded_with: VCR 2.9.2 65 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/entry/find_not_found.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: get 5 | uri: https://api.contentful.com/spaces/yr5m0jky5hsh/environments/master/entries/not_exist 6 | body: 7 | encoding: US-ASCII 8 | string: '' 9 | headers: 10 | User-Agent: 11 | - RubyContenfulManagementGem/0.0.1 12 | Authorization: 13 | - Bearer 14 | Content-Type: 15 | - application/vnd.contentful.management.v1+json 16 | Content-Length: 17 | - '0' 18 | Host: 19 | - api.contentful.com 20 | response: 21 | status: 22 | code: 404 23 | message: Not Found 24 | headers: 25 | Server: 26 | - nginx 27 | Date: 28 | - Wed, 30 Jul 2014 12:43:14 GMT 29 | Content-Type: 30 | - application/vnd.contentful.management.v1+json 31 | Transfer-Encoding: 32 | - chunked 33 | Connection: 34 | - keep-alive 35 | X-Powered-By: 36 | - Express 37 | Access-Control-Allow-Origin: 38 | - "*" 39 | Access-Control-Allow-Headers: 40 | - Accept,Accept-Language,Authorization,Cache-Control,Content-Length,Content-Range,Content-Type,DNT,Destination,Expires,If-Match,If-Modified-Since,If-None-Match,Keep-Alive,Last-Modified,Origin,Pragma,Range,User-Agent,X-Http-Method-Override,X-Mx-ReqToken,X-Requested-With,X-Contentful-Version,X-Contentful-Content-Type,X-Contentful-Organization 41 | Access-Control-Allow-Methods: 42 | - DELETE,GET,HEAD,POST,PUT,OPTIONS 43 | "^access-Control-Expose-Headers": 44 | - Etag 45 | Access-Control-Max-Age: 46 | - '1728000' 47 | body: 48 | encoding: UTF-8 49 | string: | 50 | { 51 | "sys": { 52 | "type": "Error", 53 | "id": "NotFound" 54 | }, 55 | "message": "The resource could not be found.", 56 | "details": { 57 | "type": "Entry", 58 | "space": "yr5m0jky5hsh", 59 | "id": "not_exist" 60 | } 61 | } 62 | http_version: 63 | recorded_at: Wed, 30 Jul 2014 12:43:14 GMT 64 | recorded_with: VCR 2.9.2 65 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/content_type/find_not_found.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: get 5 | uri: https://api.contentful.com/spaces/yr5m0jky5hsh/environments/master/content_types/not_exist 6 | body: 7 | encoding: US-ASCII 8 | string: '' 9 | headers: 10 | User-Agent: 11 | - RubyContenfulManagementGem/0.0.1 12 | Authorization: 13 | - Bearer 14 | Content-Type: 15 | - application/vnd.contentful.management.v1+json 16 | Content-Length: 17 | - '0' 18 | Host: 19 | - api.contentful.com 20 | response: 21 | status: 22 | code: 404 23 | message: Not Found 24 | headers: 25 | Server: 26 | - nginx 27 | Date: 28 | - Thu, 31 Jul 2014 08:40:47 GMT 29 | Content-Type: 30 | - application/vnd.contentful.management.v1+json 31 | Transfer-Encoding: 32 | - chunked 33 | Connection: 34 | - keep-alive 35 | X-Powered-By: 36 | - Express 37 | Access-Control-Allow-Origin: 38 | - "*" 39 | Access-Control-Allow-Headers: 40 | - Accept,Accept-Language,Authorization,Cache-Control,Content-Length,Content-Range,Content-Type,DNT,Destination,Expires,If-Match,If-Modified-Since,If-None-Match,Keep-Alive,Last-Modified,Origin,Pragma,Range,User-Agent,X-Http-Method-Override,X-Mx-ReqToken,X-Requested-With,X-Contentful-Version,X-Contentful-Content-Type,X-Contentful-Organization 41 | Access-Control-Allow-Methods: 42 | - DELETE,GET,HEAD,POST,PUT,OPTIONS 43 | "^access-Control-Expose-Headers": 44 | - Etag 45 | Access-Control-Max-Age: 46 | - '1728000' 47 | body: 48 | encoding: UTF-8 49 | string: | 50 | { 51 | "sys": { 52 | "type": "Error", 53 | "id": "NotFound" 54 | }, 55 | "message": "The resource could not be found.", 56 | "details": { 57 | "type": "ContentType", 58 | "space": "yr5m0jky5hsh", 59 | "id": "not_exist" 60 | } 61 | } 62 | http_version: 63 | recorded_at: Thu, 31 Jul 2014 08:40:47 GMT 64 | recorded_with: VCR 2.9.2 65 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/asset/create_with_already_used_id.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: put 5 | uri: https://api.contentful.com/spaces/yr5m0jky5hsh/environments/master/assets/codequest_id_test_custom_id 6 | body: 7 | encoding: UTF-8 8 | string: '{"fields":{"title":{"en-US":"titlebyCreateAPI_custom_id"},"description":{"en-US":"descByAPI_custom_id"},"file":{"en-US":{"contentType":"image/jpeg","fileName":"codequest.jpg","upload":"http://static.goldenline.pl/firm_logo/082/firm_225106_22f37f_small.jpg"}}}}' 9 | headers: 10 | User-Agent: 11 | - RubyContenfulManagementGem/0.0.1 12 | Authorization: 13 | - Bearer 14 | Content-Type: 15 | - application/vnd.contentful.management.v1+json 16 | Host: 17 | - api.contentful.com 18 | response: 19 | status: 20 | code: 409 21 | message: Conflict 22 | headers: 23 | Server: 24 | - nginx 25 | Date: 26 | - Thu, 31 Jul 2014 07:39:06 GMT 27 | Content-Type: 28 | - application/vnd.contentful.management.v1+json 29 | Transfer-Encoding: 30 | - chunked 31 | Connection: 32 | - keep-alive 33 | X-Powered-By: 34 | - Express 35 | Access-Control-Allow-Origin: 36 | - "*" 37 | Access-Control-Allow-Headers: 38 | - Accept,Accept-Language,Authorization,Cache-Control,Content-Length,Content-Range,Content-Type,DNT,Destination,Expires,If-Match,If-Modified-Since,If-None-Match,Keep-Alive,Last-Modified,Origin,Pragma,Range,User-Agent,X-Http-Method-Override,X-Mx-ReqToken,X-Requested-With,X-Contentful-Version,X-Contentful-Content-Type,X-Contentful-Organization 39 | Access-Control-Allow-Methods: 40 | - DELETE,GET,HEAD,POST,PUT,OPTIONS 41 | "^access-Control-Expose-Headers": 42 | - Etag 43 | Access-Control-Max-Age: 44 | - '1728000' 45 | body: 46 | encoding: UTF-8 47 | string: | 48 | { 49 | "sys": { 50 | "type": "Error", 51 | "id": "VersionMismatch" 52 | } 53 | } 54 | http_version: 55 | recorded_at: Thu, 31 Jul 2014 07:39:06 GMT 56 | recorded_with: VCR 2.9.2 57 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/space/find_not_found.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: get 5 | uri: https://api.contentful.com/spaces/not_exist 6 | body: 7 | encoding: US-ASCII 8 | string: '' 9 | headers: 10 | User-Agent: 11 | - RubyContenfulManagementGem/0.0.1 12 | Authorization: 13 | - Bearer 14 | Content-Type: 15 | - application/vnd.contentful.management.v1+json 16 | Content-Length: 17 | - '0' 18 | Host: 19 | - api.contentful.com 20 | response: 21 | status: 22 | code: 404 23 | message: Not Found 24 | headers: 25 | Server: 26 | - nginx 27 | Date: 28 | - Thu, 31 Jul 2014 06:48:51 GMT 29 | Content-Type: 30 | - application/vnd.contentful.management.v1+json 31 | Content-Length: 32 | - '137' 33 | Connection: 34 | - keep-alive 35 | Status: 36 | - 404 Not Found 37 | X-Contentful-Request-Id: 38 | - 85f-1334430569 39 | X-Ua-Compatible: 40 | - IE=Edge,chrome=1 41 | Accept-Ranges: 42 | - bytes 43 | Cache-Control: 44 | - max-age=0 45 | Access-Control-Allow-Origin: 46 | - "*" 47 | Access-Control-Allow-Headers: 48 | - Accept,Accept-Language,Authorization,Cache-Control,Content-Length,Content-Range,Content-Type,DNT,Destination,Expires,If-Match,If-Modified-Since,If-None-Match,Keep-Alive,Last-Modified,Origin,Pragma,Range,User-Agent,X-Http-Method-Override,X-Mx-ReqToken,X-Requested-With,X-Contentful-Version,X-Contentful-Content-Type,X-Contentful-Organization 49 | Access-Control-Allow-Methods: 50 | - DELETE,GET,HEAD,POST,PUT,OPTIONS 51 | "^access-Control-Expose-Headers": 52 | - Etag 53 | Access-Control-Max-Age: 54 | - '1728000' 55 | body: 56 | encoding: UTF-8 57 | string: | 58 | { 59 | "sys":{ 60 | "type":"Error", 61 | "id":"NotFound" 62 | }, 63 | "requestId":"85f-1334430569", 64 | "message":"The resource could not be found."} 65 | http_version: 66 | recorded_at: Thu, 31 Jul 2014 06:48:51 GMT 67 | recorded_with: VCR 2.9.2 68 | -------------------------------------------------------------------------------- /lib/contentful/management/upload.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative 'resource' 4 | 5 | module Contentful 6 | module Management 7 | # Resource class for Upload. 8 | # @see _ https://www.contentful.com/developers/docs/references/content-management-api/#/reference/uploads 9 | class Upload 10 | include Contentful::Management::Resource 11 | include Contentful::Management::Resource::Refresher 12 | include Contentful::Management::Resource::SystemProperties 13 | 14 | # @private 15 | def self.create_headers(_client, _attributes) 16 | { 'Content-Type' => 'application/octet-stream' } 17 | end 18 | 19 | # Creates an upload. 20 | # 21 | # @param [Contentful::Management::Client] client 22 | # @param [String] space_id 23 | # @param [Hash] attributes 24 | # @see _ README for full attribute list for each resource. 25 | # 26 | # @return [Contentful::Management::Upload] 27 | def self.create(client, space_id, attributes = {}) 28 | super(client, space_id, nil, attributes) 29 | end 30 | 31 | # Finds an upload by ID. 32 | # 33 | # @param [Contentful::Management::Client] client 34 | # @param [String] space_id 35 | # @param [String] upload_id 36 | # 37 | # @return [Contentful::Management::Upload] 38 | def self.find(client, space_id, upload_id) 39 | super(client, space_id, nil, upload_id) 40 | end 41 | 42 | # @private 43 | def self.create_attributes(_client, path_or_file) 44 | case path_or_file 45 | when ::String 46 | ::File.binread(path_or_file) 47 | when ::IO 48 | path_or_file.read 49 | end 50 | end 51 | 52 | # Gets [Contentful::Management::Link]-like representation of the upload 53 | # This is used in particular for associating the upload with an asset 54 | # 55 | # @return [Hash] link-like representation of the upload 56 | def to_link_json 57 | { 58 | sys: { 59 | type: 'Link', 60 | linkType: 'Upload', 61 | id: id 62 | } 63 | } 64 | end 65 | end 66 | end 67 | end 68 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/space/save_new_space.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: post 5 | uri: https://api.contentful.com/spaces 6 | body: 7 | encoding: UTF-8 8 | string: '{"name":"SaveNewName"}' 9 | headers: 10 | User-Agent: 11 | - RubyContenfulManagementGem/0.0.1 12 | Authorization: 13 | - Bearer 14 | Content-Type: 15 | - application/vnd.contentful.management.v1+json 16 | X-Contentful-Organization: 17 | - '' 18 | Host: 19 | - api.contentful.com 20 | response: 21 | status: 22 | code: 404 23 | message: Not Found 24 | headers: 25 | Server: 26 | - nginx 27 | Date: 28 | - Thu, 31 Jul 2014 07:14:40 GMT 29 | Content-Type: 30 | - application/vnd.contentful.management.v1+json 31 | Content-Length: 32 | - '137' 33 | Connection: 34 | - keep-alive 35 | Status: 36 | - 404 Not Found 37 | X-Contentful-Request-Id: 38 | - 85f-1334431698 39 | X-Ua-Compatible: 40 | - IE=Edge,chrome=1 41 | Accept-Ranges: 42 | - bytes 43 | Cache-Control: 44 | - max-age=0 45 | Access-Control-Allow-Origin: 46 | - "*" 47 | Access-Control-Allow-Headers: 48 | - Accept,Accept-Language,Authorization,Cache-Control,Content-Length,Content-Range,Content-Type,DNT,Destination,Expires,If-Match,If-Modified-Since,If-None-Match,Keep-Alive,Last-Modified,Origin,Pragma,Range,User-Agent,X-Http-Method-Override,X-Mx-ReqToken,X-Requested-With,X-Contentful-Version,X-Contentful-Content-Type,X-Contentful-Organization 49 | Access-Control-Allow-Methods: 50 | - DELETE,GET,HEAD,POST,PUT,OPTIONS 51 | "^access-Control-Expose-Headers": 52 | - Etag 53 | Access-Control-Max-Age: 54 | - '1728000' 55 | body: 56 | encoding: UTF-8 57 | string: | 58 | { 59 | "sys":{ 60 | "type":"Error", 61 | "id":"NotFound" 62 | }, 63 | "requestId":"85f-1334431698", 64 | "message":"The resource could not be found."} 65 | http_version: 66 | recorded_at: Thu, 31 Jul 2014 07:14:40 GMT 67 | recorded_with: VCR 2.9.2 68 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/webhook/find_not_found.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: get 5 | uri: https://api.contentful.com/spaces/bfsvtul0c41g/webhook_definitions/not_exist 6 | body: 7 | encoding: US-ASCII 8 | string: '' 9 | headers: 10 | User-Agent: 11 | - RubyContenfulManagementGem/0.0.3 12 | Authorization: 13 | - Bearer 14 | Content-Type: 15 | - application/vnd.contentful.management.v1+json 16 | Content-Length: 17 | - '0' 18 | Host: 19 | - api.contentful.com 20 | response: 21 | status: 22 | code: 404 23 | message: Not Found 24 | headers: 25 | Server: 26 | - nginx 27 | Date: 28 | - Thu, 21 Aug 2014 12:11:27 GMT 29 | Content-Type: 30 | - application/vnd.contentful.management.v1+json 31 | Content-Length: 32 | - '136' 33 | Connection: 34 | - keep-alive 35 | Status: 36 | - 404 Not Found 37 | X-Contentful-Request-Id: 38 | - 85f-929390361 39 | X-Ua-Compatible: 40 | - IE=Edge,chrome=1 41 | Accept-Ranges: 42 | - bytes 43 | Cache-Control: 44 | - max-age=0 45 | Access-Control-Allow-Origin: 46 | - "*" 47 | Access-Control-Allow-Headers: 48 | - Accept,Accept-Language,Authorization,Cache-Control,Content-Length,Content-Range,Content-Type,DNT,Destination,Expires,If-Match,If-Modified-Since,If-None-Match,Keep-Alive,Last-Modified,Origin,Pragma,Range,User-Agent,X-Http-Method-Override,X-Mx-ReqToken,X-Requested-With,X-Contentful-Version,X-Contentful-Content-Type,X-Contentful-Organization 49 | Access-Control-Allow-Methods: 50 | - DELETE,GET,HEAD,POST,PUT,OPTIONS 51 | "^access-Control-Expose-Headers": 52 | - Etag 53 | Access-Control-Max-Age: 54 | - '1728000' 55 | body: 56 | encoding: UTF-8 57 | string: | 58 | { 59 | "sys":{ 60 | "type":"Error", 61 | "id":"NotFound" 62 | }, 63 | "requestId":"85f-929390361", 64 | "message":"The resource could not be found."} 65 | http_version: 66 | recorded_at: Thu, 21 Aug 2014 12:11:22 GMT 67 | recorded_with: VCR 2.9.2 68 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/locale/find_for_space_not_found.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: get 5 | uri: https://api.contentful.com/spaces/n6spjc167pc2/environments/master/locales/not_exist 6 | body: 7 | encoding: US-ASCII 8 | string: '' 9 | headers: 10 | User-Agent: 11 | - RubyContenfulManagementGem/0.0.1 12 | Authorization: 13 | - Bearer 14 | Content-Type: 15 | - application/vnd.contentful.management.v1+json 16 | Content-Length: 17 | - '0' 18 | Host: 19 | - api.contentful.com 20 | response: 21 | status: 22 | code: 404 23 | message: Not Found 24 | headers: 25 | Server: 26 | - nginx 27 | Date: 28 | - Mon, 14 Jul 2014 07:52:50 GMT 29 | Content-Type: 30 | - application/vnd.contentful.management.v1+json 31 | Content-Length: 32 | - '137' 33 | Connection: 34 | - keep-alive 35 | Status: 36 | - 404 Not Found 37 | X-Contentful-Request-Id: 38 | - 85f-1209864561 39 | X-Ua-Compatible: 40 | - IE=Edge,chrome=1 41 | Accept-Ranges: 42 | - bytes 43 | Cache-Control: 44 | - max-age=0 45 | Access-Control-Allow-Origin: 46 | - "*" 47 | Access-Control-Allow-Headers: 48 | - Accept,Accept-Language,Authorization,Cache-Control,Content-Length,Content-Range,Content-Type,DNT,Destination,Expires,If-Match,If-Modified-Since,If-None-Match,Keep-Alive,Last-Modified,Origin,Pragma,Range,User-Agent,X-Http-Method-Override,X-Mx-ReqToken,X-Requested-With,X-Contentful-Version,X-Contentful-Content-Type,X-Contentful-Organization 49 | Access-Control-Allow-Methods: 50 | - DELETE,GET,HEAD,POST,PUT,OPTIONS 51 | "^access-Control-Expose-Headers": 52 | - Etag 53 | Access-Control-Max-Age: 54 | - '1728000' 55 | body: 56 | encoding: UTF-8 57 | string: | 58 | { 59 | "sys":{ 60 | "type":"Error", 61 | "id":"NotFound" 62 | }, 63 | "requestId":"85f-1209864561", 64 | "message":"The resource could not be found."} 65 | http_version: 66 | recorded_at: Mon, 14 Jul 2014 07:52:50 GMT 67 | recorded_with: VCR 2.9.2 68 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/upload/find_not_found.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: get 5 | uri: https://upload.contentful.com/spaces/facgnwwgj5fe/uploads/not_exist 6 | body: 7 | encoding: US-ASCII 8 | string: '' 9 | headers: 10 | User-Agent: 11 | - RubyContentfulManagementGem/1.5.0 12 | Authorization: 13 | - Bearer 14 | Content-Type: 15 | - application/vnd.contentful.management.v1+json 16 | Content-Length: 17 | - '0' 18 | Connection: 19 | - close 20 | Host: 21 | - upload.contentful.com 22 | response: 23 | status: 24 | code: 404 25 | message: Not Found 26 | headers: 27 | Access-Control-Allow-Headers: 28 | - Accept,Accept-Language,Authorization,Cache-Control,Content-Length,Content-Range,Content-Type,DNT,Destination,Expires,If-Match,If-Modified-Since,If-None-Match,Keep-Alive,Last-Modified,Origin,Pragma,Range,User-Agent,X-Http-Method-Override,X-Mx-ReqToken,X-Requested-With,X-Contentful-Version,X-Contentful-Content-Type,X-Contentful-Organization,X-Contentful-Skip-Transformation,X-Contentful-User-Agent 29 | Access-Control-Allow-Origin: 30 | - "*" 31 | Access-Control-Expose-Headers: 32 | - Etag 33 | Cache-Control: 34 | - no-cache 35 | Content-Type: 36 | - application/vnd.contentful.management.v1+json 37 | Date: 38 | - Fri, 21 Apr 2017 19:30:33 GMT 39 | Server: 40 | - Contentful 41 | Strict-Transport-Security: 42 | - max-age=15768000 43 | Vary: 44 | - accept-encoding 45 | X-Content-Type-Options: 46 | - nosniff 47 | X-Contentful-Request-Id: 48 | - 603120c101ac4f389bb7fdef94f292ff 49 | Content-Length: 50 | - '158' 51 | Connection: 52 | - Close 53 | body: 54 | encoding: ASCII-8BIT 55 | string: |- 56 | { 57 | "sys": { 58 | "type": "Error", 59 | "id": "NotFound" 60 | }, 61 | "message": "The resource could not be found.", 62 | "details": "The resource could not be found." 63 | } 64 | http_version: 65 | recorded_at: Fri, 21 Apr 2017 19:30:33 GMT 66 | recorded_with: VCR 3.0.3 67 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/api_key/find_for_space_not_found.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: get 5 | uri: https://api.contentful.com/spaces/bjwq7b86vgmm/api_keys/not_exist 6 | body: 7 | encoding: US-ASCII 8 | string: '' 9 | headers: 10 | User-Agent: 11 | - RubyContentfulManagementGem/0.8.0 12 | Authorization: 13 | - Bearer 14 | Content-Type: 15 | - application/vnd.contentful.management.v1+json 16 | Content-Length: 17 | - '0' 18 | Connection: 19 | - close 20 | Host: 21 | - api.contentful.com 22 | response: 23 | status: 24 | code: 404 25 | message: Not Found 26 | headers: 27 | Accept-Ranges: 28 | - bytes 29 | Access-Control-Allow-Headers: 30 | - Accept,Accept-Language,Authorization,Cache-Control,Content-Length,Content-Range,Content-Type,DNT,Destination,Expires,If-Match,If-Modified-Since,If-None-Match,Keep-Alive,Last-Modified,Origin,Pragma,Range,User-Agent,X-Http-Method-Override,X-Mx-ReqToken,X-Requested-With,X-Contentful-Version,X-Contentful-Content-Type,X-Contentful-Organization,X-Contentful-Skip-Transformation 31 | Access-Control-Allow-Methods: 32 | - DELETE,GET,HEAD,POST,PUT,OPTIONS 33 | Access-Control-Allow-Origin: 34 | - "*" 35 | Access-Control-Expose-Headers: 36 | - Etag 37 | Access-Control-Max-Age: 38 | - '1728000' 39 | Cache-Control: 40 | - max-age=0 41 | Content-Type: 42 | - application/vnd.contentful.management.v1+json 43 | Date: 44 | - Tue, 26 Jan 2016 13:11:04 GMT 45 | Server: 46 | - nginx 47 | Status: 48 | - 404 Not Found 49 | X-Contentful-Request-Id: 50 | - 9e1-668687226 51 | X-Ua-Compatible: 52 | - IE=Edge,chrome=1 53 | Content-Length: 54 | - '138' 55 | Connection: 56 | - Close 57 | body: 58 | encoding: UTF-8 59 | string: |+ 60 | { 61 | "sys":{ 62 | "type":"Error", 63 | "id":"NotFound" 64 | }, 65 | "requestId":"9e1-668687226", 66 | "message":"The resource could not be found." 67 | } 68 | 69 | http_version: 70 | recorded_at: Tue, 26 Jan 2016 13:11:04 GMT 71 | recorded_with: VCR 2.9.3 72 | -------------------------------------------------------------------------------- /lib/contentful/management/resource/publisher.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Contentful 4 | module Management 5 | module Resource 6 | # Wrapper for Resources with /published API 7 | module Publisher 8 | # Publishes a resource. 9 | # 10 | # @return [Contentful::Management::Resource] 11 | def publish 12 | ResourceRequester.new(client, self.class).publish( 13 | self, 14 | { 15 | space_id: space.id, 16 | environment_id: environment_id, 17 | resource_id: id, 18 | suffix: '/published' 19 | }, 20 | version: sys[:version] 21 | ) 22 | end 23 | 24 | # Unpublishes a resource. 25 | # 26 | # @return [Contentful::Management::Resource] 27 | def unpublish 28 | ResourceRequester.new(client, self.class).unpublish( 29 | self, 30 | { 31 | space_id: space.id, 32 | environment_id: environment_id, 33 | resource_id: id, 34 | suffix: '/published' 35 | }, 36 | version: sys[:version] 37 | ) 38 | end 39 | 40 | # Checks if a resource is published. 41 | # 42 | # @return [Boolean] 43 | def published? 44 | sys[:publishedAt] ? true : false 45 | end 46 | 47 | # Checks if a resource has been updated since last publish. 48 | # Returns false if resource has not been published before. 49 | # 50 | # @return [Boolean] 51 | def updated? 52 | return false unless sys[:publishedAt] 53 | 54 | sanitize_date(sys[:publishedAt]) < sanitize_date(sys[:updatedAt]) 55 | end 56 | 57 | private 58 | 59 | # In order to have a more accurate comparison due to minimal delays 60 | # upon publishing entries. We strip milliseconds from the dates we compare. 61 | # 62 | # @param date [::DateTime] 63 | # @return [::Time] without milliseconds. 64 | def sanitize_date(date) 65 | time = date.to_time 66 | 67 | ::Time.new(time.year, time.month, time.day, time.hour, time.min, time.sec, time.utc_offset) 68 | end 69 | end 70 | end 71 | end 72 | end 73 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/space/create_when_limit_has_been_reached.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: post 5 | uri: https://api.contentful.com/spaces 6 | body: 7 | encoding: UTF-8 8 | string: '{"name":"My Test Space"}' 9 | headers: 10 | User-Agent: 11 | - RubyContenfulManagementGem/0.0.1 12 | Authorization: 13 | - Bearer 3bccffbec4ce0e27bd360c0a8d10eff4c12aee9ecdfd243c372ddf972326c0d3 14 | Content-Type: 15 | - application/vnd.contentful.management.v1+json 16 | X-Contentful-Organization: 17 | - 0fV1n3ykR3arQQAa8aylMi 18 | Host: 19 | - api.contentful.com 20 | response: 21 | status: 22 | code: 403 23 | message: Forbidden 24 | headers: 25 | Server: 26 | - nginx 27 | Date: 28 | - Thu, 31 Jul 2014 06:59:42 GMT 29 | Content-Type: 30 | - application/vnd.contentful.management.v1+json 31 | Content-Length: 32 | - '176' 33 | Connection: 34 | - keep-alive 35 | Status: 36 | - 403 Forbidden 37 | X-Contentful-Request-Id: 38 | - 85f-1334430994 39 | X-Ua-Compatible: 40 | - IE=Edge,chrome=1 41 | Accept-Ranges: 42 | - bytes 43 | Cache-Control: 44 | - max-age=0 45 | Access-Control-Allow-Origin: 46 | - "*" 47 | Access-Control-Allow-Headers: 48 | - Accept,Accept-Language,Authorization,Cache-Control,Content-Length,Content-Range,Content-Type,DNT,Destination,Expires,If-Match,If-Modified-Since,If-None-Match,Keep-Alive,Last-Modified,Origin,Pragma,Range,User-Agent,X-Http-Method-Override,X-Mx-ReqToken,X-Requested-With,X-Contentful-Version,X-Contentful-Content-Type,X-Contentful-Organization 49 | Access-Control-Allow-Methods: 50 | - DELETE,GET,HEAD,POST,PUT,OPTIONS 51 | "^access-Control-Expose-Headers": 52 | - Etag 53 | Access-Control-Max-Age: 54 | - '1728000' 55 | body: 56 | encoding: UTF-8 57 | string: | 58 | { 59 | "sys":{ 60 | "type":"Error", 61 | "id":"Forbidden" 62 | }, 63 | "requestId":"85f-1334430994", 64 | "message":"You are not authorized to do this action or exceeded your plan limits."} 65 | http_version: 66 | recorded_at: Thu, 31 Jul 2014 06:59:42 GMT 67 | recorded_with: VCR 2.9.2 68 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/space/create_with_unknown_organization.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: post 5 | uri: https://api.contentful.com/spaces 6 | body: 7 | encoding: UTF-8 8 | string: '{"name":"My Test Space"}' 9 | headers: 10 | User-Agent: 11 | - RubyContenfulManagementGem/0.0.1 12 | Authorization: 13 | - Bearer 3bccffbec4ce0e27bd360c0a8d10eff4c12aee9ecdfd243c372ddf972326c0d3 14 | Content-Type: 15 | - application/vnd.contentful.management.v1+json 16 | Host: 17 | - api.contentful.com 18 | response: 19 | status: 20 | code: 404 21 | message: Not Found 22 | headers: 23 | Server: 24 | - nginx 25 | Date: 26 | - Thu, 31 Jul 2014 07:03:41 GMT 27 | Content-Type: 28 | - application/vnd.contentful.management.v1+json 29 | Content-Length: 30 | - '289' 31 | Connection: 32 | - keep-alive 33 | Status: 34 | - 404 Not Found 35 | X-Contentful-Request-Id: 36 | - 85f-1334431224 37 | X-Ua-Compatible: 38 | - IE=Edge,chrome=1 39 | Accept-Ranges: 40 | - bytes 41 | Cache-Control: 42 | - max-age=0 43 | Access-Control-Allow-Origin: 44 | - "*" 45 | Access-Control-Allow-Headers: 46 | - Accept,Accept-Language,Authorization,Cache-Control,Content-Length,Content-Range,Content-Type,DNT,Destination,Expires,If-Match,If-Modified-Since,If-None-Match,Keep-Alive,Last-Modified,Origin,Pragma,Range,User-Agent,X-Http-Method-Override,X-Mx-ReqToken,X-Requested-With,X-Contentful-Version,X-Contentful-Content-Type,X-Contentful-Organization 47 | Access-Control-Allow-Methods: 48 | - DELETE,GET,HEAD,POST,PUT,OPTIONS 49 | "^access-Control-Expose-Headers": 50 | - Etag 51 | Access-Control-Max-Age: 52 | - '1728000' 53 | body: 54 | encoding: UTF-8 55 | string: | 56 | { 57 | "sys":{ 58 | "type":"Error", 59 | "id":"MissingOrganizationParameter" 60 | }, 61 | "requestId":"85f-1334431224", 62 | "message":"This User has multiple Organizations with permissions to create a Space. Please pass the X-Contentful-Organization header in which Organization to create the Space."} 63 | http_version: 64 | recorded_at: Thu, 31 Jul 2014 07:03:41 GMT 65 | recorded_with: VCR 2.9.2 66 | -------------------------------------------------------------------------------- /lib/contentful/management/request.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Contentful 4 | module Management 5 | # This object represents a request that is to be made. It gets initialized by the client 6 | # with domain specific logic. The client later uses the Request's #url and #query methods 7 | # to execute the HTTP request. 8 | class Request 9 | attr_reader :client, :type, :query, :id, :endpoint, :headers 10 | 11 | def initialize(client, endpoint, query = {}, id = nil, headers = {}) 12 | @headers = headers 13 | @initial_id = id 14 | @client = client 15 | @client.version = headers[:version] 16 | @client.organization_id = headers[:organization_id] 17 | @client.content_type_id = headers[:content_type_id] 18 | @endpoint = endpoint 19 | 20 | case query 21 | when Hash 22 | @query = normalize_query(query) if query && !query.empty? 23 | else 24 | @query = query 25 | end 26 | 27 | if id 28 | @type = :single 29 | @id = URI.encode_www_form_component(id) 30 | else 31 | @type = :multi 32 | @id = nil 33 | end 34 | end 35 | 36 | # Returns the final URL, relative to a contentful space 37 | def url 38 | "#{@endpoint}#{@type == :single ? "/#{id}" : ''}" 39 | end 40 | 41 | # Delegates the actual HTTP work to the client 42 | def get 43 | client.get(self) 44 | end 45 | 46 | # Delegates the actual HTTP POST request to the client 47 | def post 48 | client.post(self) 49 | end 50 | 51 | # Delegates the actual HTTP PUT request to the client 52 | def put 53 | client.put(self) 54 | end 55 | 56 | # Delegates the actual HTTP DELETE request to the client 57 | def delete 58 | client.delete(self) 59 | end 60 | 61 | # Returns true if endpoint is an absolute url 62 | # @return [Boolean] 63 | def absolute? 64 | @endpoint.start_with?('http') 65 | end 66 | 67 | # Returns a new Request object with the same data 68 | def copy 69 | self.class.new(@client, @endpoint, @query, @initial_id, @headers) 70 | end 71 | 72 | private 73 | 74 | def normalize_query(query) 75 | query.transform_keys(&:to_sym) 76 | end 77 | end 78 | end 79 | end 80 | -------------------------------------------------------------------------------- /lib/contentful/management/space_membership.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative 'resource' 4 | 5 | module Contentful 6 | module Management 7 | # Resource class for Space Membership. 8 | class SpaceMembership 9 | include Contentful::Management::Resource 10 | include Contentful::Management::Resource::Refresher 11 | include Contentful::Management::Resource::SystemProperties 12 | 13 | property :user, Link 14 | property :roles, :array 15 | property :admin, :boolean 16 | 17 | # Returns the list of roles for this membership. 18 | def roles 19 | (properties[:roles] || []).map { |r| r.is_a?(Link) ? r : Link.new(r, nil, client) } 20 | end 21 | 22 | # @private 23 | def self.clean_roles(roles) 24 | roles.map { |r| r.is_a?(Link) ? r.raw_object : r } 25 | end 26 | 27 | # @private 28 | def self.create_attributes(_client, attributes) 29 | { 30 | 'admin' => attributes['admin'] || attributes.fetch(:admin), 31 | 'roles' => clean_roles(attributes['roles'] || attributes.fetch(:roles)), 32 | 'email' => attributes['email'] || attributes.fetch(:email) 33 | } 34 | end 35 | 36 | # Creates an Space Membership 37 | # 38 | # @param [Contentful::Management::Client] client 39 | # @param [String] space_id 40 | # @param [Hash] attributes 41 | # @see _ README for full attribute list for each resource. 42 | # 43 | # @return [Contentful::Management::SpaceMembership] 44 | def self.create(client, space_id, attributes = {}) 45 | super(client, space_id, nil, attributes) 46 | end 47 | 48 | # Finds an Space Membership by ID. 49 | # 50 | # @param [Contentful::Management::Client] client 51 | # @param [String] space_id 52 | # @param [String] space_membership_id 53 | # 54 | # @return [Contentful::Management::SpaceMembership] 55 | def self.find(client, space_id, space_membership_id) 56 | super(client, space_id, nil, space_membership_id) 57 | end 58 | 59 | # @private 60 | def query_attributes(attributes) 61 | { 62 | 'admin' => attributes['admin'] || attributes[:admin], 63 | 'roles' => self.class.clean_roles(attributes['roles'] || attributes[:roles]) 64 | }.reject { |_k, v| v.nil? } 65 | end 66 | end 67 | end 68 | end 69 | -------------------------------------------------------------------------------- /lib/contentful/management/webhook_health.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative 'resource' 4 | 5 | module Contentful 6 | module Management 7 | # Resource class for WebhookHealth. 8 | # @see _ https://www.contentful.com/developers/docs/references/content-management-api/#/reference/webhook-calls/webhook-health 9 | class WebhookHealth 10 | include Contentful::Management::Resource 11 | include Contentful::Management::Resource::Refresher 12 | include Contentful::Management::Resource::SystemProperties 13 | 14 | property :calls, :hash 15 | 16 | # Gets a webhook's health details by ID 17 | # 18 | # @param [Contentful::Management::Client] client 19 | # @param [String] space_id 20 | # @param [String] webhook_id 21 | # 22 | # @return [Contentful::Management::WebhookHealth] 23 | def self.find(client, space_id, webhook_id) 24 | ClientWebhookHealthMethodsFactory.new(client, space_id).find(webhook_id) 25 | end 26 | 27 | # Not supported 28 | def self.create(*) 29 | fail 'Not supported' 30 | end 31 | 32 | # Not supported 33 | def self.all(*) 34 | fail 'Not supported' 35 | end 36 | 37 | # @private 38 | def self.endpoint 39 | 'webhooks' 40 | end 41 | 42 | # @private 43 | def self.build_endpoint(endpoint_options) 44 | space_id = endpoint_options.fetch(:space_id) 45 | webhook_id = endpoint_options.fetch(:webhook_id) 46 | 47 | "spaces/#{space_id}/webhooks/#{webhook_id}/health" 48 | end 49 | 50 | # Not supported 51 | def destroy 52 | fail 'Not supported' 53 | end 54 | 55 | # Not supported 56 | def update(*) 57 | fail 'Not supported' 58 | end 59 | 60 | # Returns the total calls made by the webhook. 61 | def total 62 | calls['total'] 63 | end 64 | 65 | # Returns the amount of healthy calls made by the webhook. 66 | def healthy 67 | calls['healthy'] 68 | end 69 | 70 | # Returns wether or not there was an error on the webhook calls on the last 30 days. 71 | def errors? 72 | total != healthy 73 | end 74 | 75 | # Returns whether or not all the webhook calls on the last 30 days were successful. 76 | def healthy? 77 | total == healthy 78 | end 79 | end 80 | end 81 | end 82 | -------------------------------------------------------------------------------- /spec/lib/contentful/management/organization_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | require 'contentful/management/space' 3 | require 'contentful/management/client' 4 | 5 | module Contentful 6 | module Management 7 | describe Organization do 8 | let(:token) { ENV.fetch('CF_TEST_CMA_TOKEN', '') } 9 | let!(:client) { Client.new(token) } 10 | 11 | subject { client.organizations } 12 | 13 | describe '.all' do 14 | it 'fetches the list of organizations belonging to the user' do 15 | vcr('organization/all') { 16 | organizations = subject.all 17 | expect(organizations).to be_a Contentful::Management::Array 18 | 19 | expect(organizations.first).to be_a Contentful::Management::Organization 20 | expect(organizations.first.name).to eq 'My Test Organization' 21 | expect(organizations.first.id).to be_truthy 22 | } 23 | end 24 | end 25 | 26 | describe '.find' do 27 | it 'is not supported' do 28 | expect { subject.find }.to raise_error 'Not supported' 29 | end 30 | end 31 | 32 | describe "users" do 33 | describe '.find' do 34 | it "should fetch the user if under the organizaton id" do 35 | vcr('organization/user') { 36 | organization = subject.all.first 37 | user = organization.users.find('user_id') 38 | 39 | expect(user).to be_a Contentful::Management::User 40 | expect(user.first_name).to eq 'Bhushan' 41 | expect(user.last_name).to eq 'Lodha' 42 | expect(user.email).to eq 'bhushanlodha@gmail.com' 43 | expect(user.activated).to eq true 44 | expect(user.confirmed).to eq true 45 | expect(user.sign_in_count).to eq 42 46 | expect(user.avatar_url).to be_truthy 47 | } 48 | end 49 | 50 | describe "all" do 51 | it 'returns a Contentful::Array' do 52 | vcr('organization/users') { expect(subject.all.first.users.all).to be_kind_of Contentful::Management::Array } 53 | end 54 | 55 | it 'builds a Contentful::Management::Space object' do 56 | vcr('organization/users') { expect(subject.all.first.users.all.first).to be_kind_of Contentful::Management::User } 57 | end 58 | end 59 | end 60 | end 61 | end 62 | end 63 | end 64 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/webhook/create_with_taken_url.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: put 5 | uri: https://api.contentful.com/spaces/bfsvtul0c41g/webhook_definitions/taken_webhook 6 | body: 7 | encoding: UTF-8 8 | string: '{"url":"https://www.example3.com"}' 9 | headers: 10 | User-Agent: 11 | - RubyContenfulManagementGem/0.0.3 12 | Authorization: 13 | - Bearer 14 | Content-Type: 15 | - application/vnd.contentful.management.v1+json 16 | Host: 17 | - api.contentful.com 18 | response: 19 | status: 20 | code: 422 21 | message: Unprocessable Entity 22 | headers: 23 | Server: 24 | - nginx 25 | Date: 26 | - Thu, 21 Aug 2014 11:32:16 GMT 27 | Content-Type: 28 | - application/vnd.contentful.management.v1+json 29 | Content-Length: 30 | - '302' 31 | Connection: 32 | - keep-alive 33 | Status: 34 | - 422 Unprocessable Entity 35 | X-Contentful-Request-Id: 36 | - 85f-929382323 37 | Accept-Ranges: 38 | - bytes 39 | Cache-Control: 40 | - max-age=0 41 | Access-Control-Allow-Origin: 42 | - "*" 43 | Access-Control-Allow-Headers: 44 | - Accept,Accept-Language,Authorization,Cache-Control,Content-Length,Content-Range,Content-Type,DNT,Destination,Expires,If-Match,If-Modified-Since,If-None-Match,Keep-Alive,Last-Modified,Origin,Pragma,Range,User-Agent,X-Http-Method-Override,X-Mx-ReqToken,X-Requested-With,X-Contentful-Version,X-Contentful-Content-Type,X-Contentful-Organization 45 | Access-Control-Allow-Methods: 46 | - DELETE,GET,HEAD,POST,PUT,OPTIONS 47 | "^access-Control-Expose-Headers": 48 | - Etag 49 | Access-Control-Max-Age: 50 | - '1728000' 51 | body: 52 | encoding: UTF-8 53 | string: | 54 | { 55 | "sys":{ 56 | "type":"Error", 57 | "id":"ValidationFailed" 58 | }, 59 | "requestId":"85f-929382323", 60 | "message":"The resource you sent in the body is invalid.", 61 | "details":{ 62 | "errors":[ 63 | { 64 | "name":"taken", 65 | "path":"url", 66 | "value":"https://www.example3.com" 67 | } 68 | ] 69 | }} 70 | http_version: 71 | recorded_at: Thu, 21 Aug 2014 11:32:11 GMT 72 | recorded_with: VCR 2.9.2 73 | -------------------------------------------------------------------------------- /lib/contentful/management/support.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Contentful 4 | module Management 5 | # Utility methods used by the contentful management gem 6 | module Support 7 | class << self 8 | # Transforms CamelCase into snake_case (taken from zucker) 9 | def snakify(object) 10 | snake = String(object).gsub(/(? 'roles', 42 | 'Space' => 'spaces', 43 | 'Asset' => 'assets', 44 | 'Entry' => 'entries', 45 | 'Locale' => 'locales', 46 | 'Upload' => 'uploads', 47 | 'ApiKey' => 'api_keys', 48 | 'UIExtension' => 'extensions', 49 | 'Environment' => 'environments', 50 | 'ContentType' => 'content_types', 51 | 'PreviewApiKey' => 'preview_api_keys', 52 | 'SpaceMembership' => 'space_memberships' 53 | }[resource_name] 54 | end 55 | end 56 | end 57 | end 58 | end 59 | -------------------------------------------------------------------------------- /lib/contentful/management/webhook_call.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative 'resource' 4 | 5 | module Contentful 6 | module Management 7 | # Resource class for WebhookCall. 8 | # @see _ https://www.contentful.com/developers/docs/references/content-management-api/#/reference/webhook-calls 9 | class WebhookCall 10 | include Contentful::Management::Resource 11 | include Contentful::Management::Resource::Refresher 12 | include Contentful::Management::Resource::SystemProperties 13 | 14 | property :url, :array 15 | property :errors, :array 16 | property :request, :hash 17 | property :response, :hash 18 | property :requestAt, :date 19 | property :responseAt, :date 20 | property :eventType, :string 21 | property :statusCode, :integer 22 | 23 | # Gets all webhook call details for a webhook. 24 | # 25 | # @param [Contentful::Management::Client] client 26 | # @param [String] space_id 27 | # @param [String] webhook_id 28 | # 29 | # @return [Contentful::Management::Array] 30 | def self.all(client, space_id, webhook_id) 31 | ClientWebhookCallMethodsFactory.new(client, space_id, webhook_id).all 32 | end 33 | 34 | # Gets a webhook's call details by ID 35 | # 36 | # @param [Contentful::Management::Client] client 37 | # @param [String] space_id 38 | # @param [String] webhook_id 39 | # @param [String] call_id 40 | # 41 | # @return [Contentful::Management::WebhookCall] 42 | def self.find(client, space_id, webhook_id, call_id) 43 | ClientWebhookCallMethodsFactory.new(client, space_id, webhook_id).find(call_id) 44 | end 45 | 46 | # Not supported 47 | def self.create(*) 48 | fail 'Not supported' 49 | end 50 | 51 | # @private 52 | def self.endpoint 53 | 'webhooks' 54 | end 55 | 56 | # @private 57 | def self.build_endpoint(endpoint_options) 58 | space_id = endpoint_options.fetch(:space_id) 59 | webhook_id = endpoint_options.fetch(:webhook_id) 60 | call_id = endpoint_options.fetch(:call_id, nil) 61 | 62 | endpoint = "spaces/#{space_id}/webhooks/#{webhook_id}/calls" 63 | endpoint = "#{endpoint}/#{call_id}" unless call_id.nil? 64 | 65 | endpoint 66 | end 67 | 68 | # Not supported 69 | def destroy 70 | fail 'Not supported' 71 | end 72 | 73 | # Not supported 74 | def update(*) 75 | fail 'Not supported' 76 | end 77 | end 78 | end 79 | end 80 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/post_request.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: post 5 | uri: http://example.com/ 6 | body: 7 | encoding: UTF-8 8 | string: '{"foo":"bar"}' 9 | headers: 10 | Connection: 11 | - close 12 | Content-Type: 13 | - application/json 14 | Host: 15 | - example.com 16 | User-Agent: 17 | - http.rb/0.9.8 18 | response: 19 | status: 20 | code: 200 21 | message: OK 22 | headers: 23 | Accept-Ranges: 24 | - bytes 25 | Cache-Control: 26 | - max-age=604800 27 | Content-Type: 28 | - text/html 29 | Date: 30 | - Fri, 11 Mar 2016 10:16:02 GMT 31 | Etag: 32 | - '"359670651"' 33 | Expires: 34 | - Fri, 18 Mar 2016 10:16:02 GMT 35 | Last-Modified: 36 | - Fri, 09 Aug 2013 23:54:35 GMT 37 | Server: 38 | - EOS (lax004/45C0) 39 | Content-Length: 40 | - '1270' 41 | Connection: 42 | - close 43 | body: 44 | encoding: UTF-8 45 | string: "\n\n\n Example Domain\n\n 46 | \ \n \n \n \n\n\n\n
\n

Example Domain

\n 58 | \

This domain is established to be used for illustrative examples in 59 | documents. You may use this\n domain in examples without prior coordination 60 | or asking for permission.

\n

More 61 | information...

\n
\n\n\n" 62 | http_version: 63 | recorded_at: Fri, 11 Mar 2016 10:16:01 GMT 64 | recorded_with: VCR 2.9.3 65 | -------------------------------------------------------------------------------- /lib/contentful/management/api_key.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative 'resource' 4 | 5 | module Contentful 6 | module Management 7 | # Resource class for ApiKey. 8 | # @see _ https://www.contentful.com/developers/docs/references/content-management-api/#/reference/api-keys 9 | class ApiKey 10 | include Contentful::Management::Resource 11 | include Contentful::Management::Resource::Refresher 12 | include Contentful::Management::Resource::SystemProperties 13 | 14 | property :name 15 | property :policies 16 | property :description 17 | property :accessToken 18 | property :environments 19 | property :preview_api_key, Link 20 | 21 | # @private 22 | def self.create_attributes(_client, attributes) 23 | { 24 | 'name' => attributes.fetch(:name), 25 | 'description' => attributes.fetch(:description, nil), 26 | 'environments' => attributes.fetch(:environments, []) # Will default to master if empty 27 | } 28 | end 29 | 30 | # Creates an API Key. 31 | # 32 | # @param [Contentful::Management::Client] client 33 | # @param [String] space_id 34 | # @param [Hash] attributes 35 | # @see _ README for full attribute list for each resource. 36 | # 37 | # @return [Contentful::Management::ApiKey] 38 | def self.create(client, space_id, attributes = {}) 39 | super(client, space_id, nil, attributes) 40 | end 41 | 42 | # Finds an API Key by ID. 43 | # 44 | # @param [Contentful::Management::Client] client 45 | # @param [String] space_id 46 | # @param [String] api_key_id 47 | # 48 | # @return [Contentful::Management::ApiKey] 49 | def self.find(client, space_id, api_key_id) 50 | super(client, space_id, nil, api_key_id) 51 | end 52 | 53 | # Returns the environment links associated to this Api Key 54 | def environments 55 | properties[:environments].map { |environment| Link.new(environment, nil, client) } 56 | end 57 | 58 | # Finds the Preview API Key associated to this API Key 59 | # 60 | # @return [Contentful::Management::PreviewApiKey] 61 | def preview_api_key 62 | client.preview_api_keys(space.id).find(properties[:preview_api_key].id) 63 | end 64 | 65 | protected 66 | 67 | def query_attributes(attributes) 68 | self.class.create_attributes( 69 | nil, 70 | { 71 | name: name, 72 | description: description, 73 | environments: environments 74 | }.merge(attributes) 75 | ) 76 | end 77 | end 78 | end 79 | end 80 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/upload/find.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: get 5 | uri: https://upload.contentful.com/spaces/facgnwwgj5fe/uploads/IUMb6WLjk9fjQ0WZfG971 6 | body: 7 | encoding: US-ASCII 8 | string: '' 9 | headers: 10 | User-Agent: 11 | - RubyContentfulManagementGem/1.5.0 12 | Authorization: 13 | - Bearer 14 | Content-Type: 15 | - application/vnd.contentful.management.v1+json 16 | Content-Length: 17 | - '0' 18 | Connection: 19 | - close 20 | Host: 21 | - upload.contentful.com 22 | response: 23 | status: 24 | code: 200 25 | message: OK 26 | headers: 27 | Accept-Ranges: 28 | - bytes 29 | Access-Control-Allow-Headers: 30 | - Accept,Accept-Language,Authorization,Cache-Control,Content-Length,Content-Range,Content-Type,DNT,Destination,Expires,If-Match,If-Modified-Since,If-None-Match,Keep-Alive,Last-Modified,Origin,Pragma,Range,User-Agent,X-Http-Method-Override,X-Mx-ReqToken,X-Requested-With,X-Contentful-Version,X-Contentful-Content-Type,X-Contentful-Organization,X-Contentful-Skip-Transformation,X-Contentful-User-Agent 31 | Access-Control-Allow-Origin: 32 | - "*" 33 | Access-Control-Expose-Headers: 34 | - Etag 35 | Cache-Control: 36 | - no-cache 37 | Content-Type: 38 | - application/vnd.contentful.management.v1+json 39 | Date: 40 | - Fri, 21 Apr 2017 19:32:04 GMT 41 | Server: 42 | - Contentful 43 | Strict-Transport-Security: 44 | - max-age=15768000 45 | Vary: 46 | - accept-encoding 47 | X-Content-Type-Options: 48 | - nosniff 49 | X-Contentful-Request-Id: 50 | - ae625a4c50deb387dcf74541abf01785 51 | Content-Length: 52 | - '431' 53 | Connection: 54 | - Close 55 | body: 56 | encoding: ASCII-8BIT 57 | string: |- 58 | { 59 | "sys": { 60 | "id": "IUMb6WLjk9fjQ0WZfG971", 61 | "type": "Upload", 62 | "createdAt": "2017-04-21T19:24:01.000Z", 63 | "expiresAt": "2017-04-23T00:00:00.000Z", 64 | "space": { 65 | "sys": { 66 | "type": "Link", 67 | "linkType": "Space", 68 | "id": "facgnwwgj5fe" 69 | } 70 | }, 71 | "createdBy": { 72 | "sys": { 73 | "type": "Link", 74 | "linkType": "User", 75 | "id": "4SejVrWT96dvL9IV4Nb7sQ" 76 | } 77 | } 78 | } 79 | } 80 | http_version: 81 | recorded_at: Fri, 21 Apr 2017 19:32:04 GMT 82 | recorded_with: VCR 3.0.3 83 | -------------------------------------------------------------------------------- /lib/contentful/management/resource/fields.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative '../file' 4 | 5 | module Contentful 6 | module Management 7 | module Resource 8 | # Adds fields logic for [Resource] classes 9 | module Fields 10 | # Returns the fields hash for the specified locale 11 | # 12 | # @param [String] wanted_locale 13 | # 14 | # @return [Hash] localized fields 15 | def fields(wanted_locale = nil) 16 | wanted_locale = internal_resource_locale if wanted_locale.nil? 17 | @fields.fetch(wanted_locale.to_s, {}) 18 | end 19 | 20 | # @private 21 | def initialize(object = nil, *) 22 | super 23 | @fields = {} 24 | extract_fields_from_object! object if object 25 | end 26 | 27 | # @private 28 | def inspect(info = nil) 29 | if fields.empty? 30 | super(info) 31 | else 32 | super("#{info} @fields=#{fields.inspect}") 33 | end 34 | end 35 | 36 | # Create accessors for content type, asset, entry objects. 37 | def self.included(base) 38 | base.fields_coercions.each_key do |name| 39 | accessor_name = Contentful::Management::Support.snakify(name) 40 | base.send :define_method, accessor_name do 41 | fields[name.to_sym] 42 | end 43 | base.send :define_method, "#{accessor_name}_with_locales" do 44 | fields_for_query[name.to_sym] 45 | end 46 | base.send :define_method, "#{accessor_name}=" do |value| 47 | fields[name.to_sym] = value 48 | end 49 | base.send :define_method, "#{accessor_name}_with_locales=" do |values| 50 | values.each do |locale, value| 51 | @fields[locale] = {} unless @fields[locale] 52 | @fields[locale][name.to_sym] = value 53 | end 54 | end 55 | end 56 | end 57 | 58 | private 59 | 60 | def extract_fields_from_object!(object) 61 | if nested_locale_fields? && !object['fields'].nil? 62 | object['fields'].each do |field_name, nested_child_object| 63 | nested_child_object.each do |object_locale, real_child_object| 64 | @fields[object_locale] ||= {} 65 | @fields[object_locale].merge! extract_from_object( 66 | { field_name => real_child_object }, :fields 67 | ) 68 | end 69 | end 70 | else 71 | @fields[locale || default_locale] = extract_from_object object['fields'], :fields 72 | end 73 | end 74 | end 75 | end 76 | end 77 | end 78 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/space/create.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: post 5 | uri: https://api.contentful.com/spaces 6 | body: 7 | encoding: UTF-8 8 | string: '{"name":"My Test Space"}' 9 | headers: 10 | User-Agent: 11 | - RubyContenfulManagementGem/0.0.1 12 | Authorization: 13 | - Bearer 14 | Content-Type: 15 | - application/vnd.contentful.management.v1+json 16 | X-Contentful-Organization: 17 | - 1EQPR5IHrPx94UY4AViTYO 18 | Host: 19 | - api.contentful.com 20 | response: 21 | status: 22 | code: 201 23 | message: Created 24 | headers: 25 | Server: 26 | - nginx 27 | Date: 28 | - Thu, 31 Jul 2014 06:49:55 GMT 29 | Content-Type: 30 | - application/vnd.contentful.management.v1+json 31 | Content-Length: 32 | - '454' 33 | Connection: 34 | - keep-alive 35 | Status: 36 | - 201 Created 37 | X-Contentful-Request-Id: 38 | - 85f-1334430631 39 | Location: 40 | - https://api.contentful.com/spaces/aopzqyf8j4yq 41 | Etag: 42 | - '"f933a71af2826311336cf87c02c211a8"' 43 | Accept-Ranges: 44 | - bytes 45 | Cache-Control: 46 | - max-age=0 47 | Access-Control-Allow-Origin: 48 | - "*" 49 | Access-Control-Allow-Headers: 50 | - Accept,Accept-Language,Authorization,Cache-Control,Content-Length,Content-Range,Content-Type,DNT,Destination,Expires,If-Match,If-Modified-Since,If-None-Match,Keep-Alive,Last-Modified,Origin,Pragma,Range,User-Agent,X-Http-Method-Override,X-Mx-ReqToken,X-Requested-With,X-Contentful-Version,X-Contentful-Content-Type,X-Contentful-Organization 51 | Access-Control-Allow-Methods: 52 | - DELETE,GET,HEAD,POST,PUT,OPTIONS 53 | "^access-Control-Expose-Headers": 54 | - Etag 55 | Access-Control-Max-Age: 56 | - '1728000' 57 | body: 58 | encoding: UTF-8 59 | string: | 60 | { 61 | "sys":{ 62 | "type":"Space", 63 | "id":"aopzqyf8j4yq", 64 | "version":1, 65 | "createdBy":{ 66 | "sys":{ 67 | "type":"Link", 68 | "linkType":"User", 69 | "id":"1E7acJL8I5XUXAMHQt9Grs" 70 | } 71 | }, 72 | "createdAt":"2014-07-31T06:49:50Z", 73 | "updatedBy":{ 74 | "sys":{ 75 | "type":"Link", 76 | "linkType":"User", 77 | "id":"1E7acJL8I5XUXAMHQt9Grs" 78 | } 79 | }, 80 | "updatedAt":"2014-07-31T06:49:50Z" 81 | }, 82 | "name":"My Test Space"} 83 | http_version: 84 | recorded_at: Thu, 31 Jul 2014 06:49:55 GMT 85 | recorded_with: VCR 2.9.2 86 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/space/create_without_organization.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: post 5 | uri: https://api.contentful.com/spaces 6 | body: 7 | encoding: UTF-8 8 | string: '{"name":"My Test Space"}' 9 | headers: 10 | User-Agent: 11 | - RubyContenfulManagementGem/0.0.1 12 | Authorization: 13 | - Bearer 3bccffbec4ce0e27bd360c0a8d10eff4c12aee9ecdfd243c372ddf972326c0d3 14 | Content-Type: 15 | - application/vnd.contentful.management.v1+json 16 | Host: 17 | - api.contentful.com 18 | response: 19 | status: 20 | code: 201 21 | message: Created 22 | headers: 23 | Server: 24 | - nginx 25 | Date: 26 | - Thu, 31 Jul 2014 07:02:05 GMT 27 | Content-Type: 28 | - application/vnd.contentful.management.v1+json 29 | Content-Length: 30 | - '454' 31 | Connection: 32 | - keep-alive 33 | Status: 34 | - 201 Created 35 | X-Contentful-Request-Id: 36 | - 85f-1334431117 37 | Location: 38 | - https://api.contentful.com/spaces/1jyhfyvahfio 39 | Etag: 40 | - '"f764b8fc66786031af1d7dd0795fe3bc"' 41 | Accept-Ranges: 42 | - bytes 43 | Cache-Control: 44 | - max-age=0 45 | Access-Control-Allow-Origin: 46 | - "*" 47 | Access-Control-Allow-Headers: 48 | - Accept,Accept-Language,Authorization,Cache-Control,Content-Length,Content-Range,Content-Type,DNT,Destination,Expires,If-Match,If-Modified-Since,If-None-Match,Keep-Alive,Last-Modified,Origin,Pragma,Range,User-Agent,X-Http-Method-Override,X-Mx-ReqToken,X-Requested-With,X-Contentful-Version,X-Contentful-Content-Type,X-Contentful-Organization 49 | Access-Control-Allow-Methods: 50 | - DELETE,GET,HEAD,POST,PUT,OPTIONS 51 | "^access-Control-Expose-Headers": 52 | - Etag 53 | Access-Control-Max-Age: 54 | - '1728000' 55 | body: 56 | encoding: UTF-8 57 | string: | 58 | { 59 | "sys":{ 60 | "type":"Space", 61 | "id":"1jyhfyvahfio", 62 | "version":1, 63 | "createdBy":{ 64 | "sys":{ 65 | "type":"Link", 66 | "linkType":"User", 67 | "id":"5CicedV35cE8xqfXKiq9PV" 68 | } 69 | }, 70 | "createdAt":"2014-07-31T07:02:02Z", 71 | "updatedBy":{ 72 | "sys":{ 73 | "type":"Link", 74 | "linkType":"User", 75 | "id":"5CicedV35cE8xqfXKiq9PV" 76 | } 77 | }, 78 | "updatedAt":"2014-07-31T07:02:02Z" 79 | }, 80 | "name":"My Test Space"} 81 | http_version: 82 | recorded_at: Thu, 31 Jul 2014 07:02:05 GMT 83 | recorded_with: VCR 2.9.2 84 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/roles/find_for_space_not_found.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: get 5 | uri: https://api.contentful.com/spaces/03vrieuz7eun/roles/not_exist 6 | body: 7 | encoding: US-ASCII 8 | string: '' 9 | headers: 10 | User-Agent: 11 | - RubyContentfulManagementGem/1.0.1 12 | Authorization: 13 | - Bearer 14 | Content-Type: 15 | - application/vnd.contentful.management.v1+json 16 | Content-Length: 17 | - '0' 18 | Connection: 19 | - close 20 | Host: 21 | - api.contentful.com 22 | response: 23 | status: 24 | code: 404 25 | message: Not Found 26 | headers: 27 | Accept-Ranges: 28 | - bytes 29 | Access-Control-Allow-Headers: 30 | - Accept,Accept-Language,Authorization,Cache-Control,Content-Length,Content-Range,Content-Type,DNT,Destination,Expires,If-Match,If-Modified-Since,If-None-Match,Keep-Alive,Last-Modified,Origin,Pragma,Range,User-Agent,X-Http-Method-Override,X-Mx-ReqToken,X-Requested-With,X-Contentful-Version,X-Contentful-Content-Type,X-Contentful-Organization,X-Contentful-Skip-Transformation,X-Contentful-User-Agent 31 | Access-Control-Allow-Methods: 32 | - DELETE,GET,HEAD,POST,PUT,OPTIONS 33 | Access-Control-Allow-Origin: 34 | - "*" 35 | Access-Control-Expose-Headers: 36 | - Etag 37 | Access-Control-Max-Age: 38 | - '1728000' 39 | Cache-Control: 40 | - max-age=0 41 | Content-Type: 42 | - application/vnd.contentful.management.v1+json 43 | Date: 44 | - Thu, 07 Apr 2016 20:46:44 GMT 45 | Server: 46 | - nginx 47 | Status: 48 | - 404 Not Found 49 | X-Contentful-Request-Id: 50 | - 9e1-1105916090 51 | X-Ua-Compatible: 52 | - IE=Edge,chrome=1 53 | Content-Length: 54 | - '139' 55 | Connection: 56 | - Close 57 | Set-Cookie: 58 | - incap_ses_298_673446=eTIdHQEZyFVoO9O9KrYiBDPHBlcAAAAA7Ai5D6V3h7P+lqe32MF4dg==; 59 | path=/; Domain=.contentful.com 60 | - nlbi_673446=2R0gEArbc3taQUSWaoBaJgAAAACis7c2leZOGOspK827IhCe; path=/; Domain=.contentful.com 61 | - visid_incap_673446=D6gR5LxMQvqeTMQWj4Q5iTPHBlcAAAAAQUIPAAAAAADb1SgkXsGcja808BOxWv7N; 62 | expires=Fri, 07 Apr 2017 09:48:46 GMT; path=/; Domain=.contentful.com 63 | X-Iinfo: 64 | - 10-33396145-33396185 NNNN CT(137 153 0) RT(1460062003224 97) q(0 0 3 -1) r(5 65 | 5) U5 66 | X-Cdn: 67 | - Incapsula 68 | body: 69 | encoding: UTF-8 70 | string: |+ 71 | { 72 | "requestId":"9e1-1105916090", 73 | "message":"The resource could not be found.", 74 | "sys":{ 75 | "type":"Error", 76 | "id":"NotFound" 77 | } 78 | } 79 | 80 | http_version: 81 | recorded_at: Thu, 07 Apr 2016 20:46:44 GMT 82 | recorded_with: VCR 2.9.3 83 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/content_type/create_content_type_with_id.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: put 5 | uri: https://api.contentful.com/spaces/yr5m0jky5hsh/environments/master/content_types/custom_id 6 | body: 7 | encoding: UTF-8 8 | string: '{"name":"Blog","description":null,"fields":[]}' 9 | headers: 10 | User-Agent: 11 | - RubyContenfulManagementGem/0.0.1 12 | Authorization: 13 | - Bearer 14 | Content-Type: 15 | - application/vnd.contentful.management.v1+json 16 | Host: 17 | - api.contentful.com 18 | response: 19 | status: 20 | code: 201 21 | message: Created 22 | headers: 23 | Server: 24 | - nginx 25 | Date: 26 | - Thu, 31 Jul 2014 10:04:34 GMT 27 | Content-Type: 28 | - application/vnd.contentful.management.v1+json 29 | Content-Length: 30 | - '640' 31 | Connection: 32 | - keep-alive 33 | X-Powered-By: 34 | - Express 35 | Cf-Space-Id: 36 | - yr5m0jky5hsh 37 | Etag: 38 | - '"bb3ea9125aefdc833b672dc2e87507d4"' 39 | Access-Control-Allow-Origin: 40 | - "*" 41 | Access-Control-Allow-Headers: 42 | - Accept,Accept-Language,Authorization,Cache-Control,Content-Length,Content-Range,Content-Type,DNT,Destination,Expires,If-Match,If-Modified-Since,If-None-Match,Keep-Alive,Last-Modified,Origin,Pragma,Range,User-Agent,X-Http-Method-Override,X-Mx-ReqToken,X-Requested-With,X-Contentful-Version,X-Contentful-Content-Type,X-Contentful-Organization 43 | Access-Control-Allow-Methods: 44 | - DELETE,GET,HEAD,POST,PUT,OPTIONS 45 | "^access-Control-Expose-Headers": 46 | - Etag 47 | Access-Control-Max-Age: 48 | - '1728000' 49 | body: 50 | encoding: UTF-8 51 | string: | 52 | { 53 | "name": "Blog", 54 | "description": null, 55 | "fields": [], 56 | "sys": { 57 | "id": "custom_id", 58 | "type": "ContentType", 59 | "version": 1, 60 | "createdAt": "2014-07-31T10:04:34.138Z", 61 | "createdBy": { 62 | "sys": { 63 | "type": "Link", 64 | "linkType": "User", 65 | "id": "0fn5fOWn4WsKFyYla1gI5h" 66 | } 67 | }, 68 | "space": { 69 | "sys": { 70 | "type": "Link", 71 | "linkType": "Space", 72 | "id": "yr5m0jky5hsh" 73 | } 74 | }, 75 | "updatedAt": "2014-07-31T10:04:34.138Z", 76 | "updatedBy": { 77 | "sys": { 78 | "type": "Link", 79 | "linkType": "User", 80 | "id": "0fn5fOWn4WsKFyYla1gI5h" 81 | } 82 | } 83 | } 84 | } 85 | http_version: 86 | recorded_at: Thu, 31 Jul 2014 10:04:34 GMT 87 | recorded_with: VCR 2.9.2 88 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/webhook/create.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: put 5 | uri: https://api.contentful.com/spaces/bfsvtul0c41g/webhook_definitions/test_webhook 6 | body: 7 | encoding: UTF-8 8 | string: '{"url":"https://www.example3.com"}' 9 | headers: 10 | User-Agent: 11 | - RubyContenfulManagementGem/0.0.3 12 | Authorization: 13 | - Bearer 14 | Content-Type: 15 | - application/vnd.contentful.management.v1+json 16 | Host: 17 | - api.contentful.com 18 | response: 19 | status: 20 | code: 200 21 | message: OK 22 | headers: 23 | Server: 24 | - nginx 25 | Date: 26 | - Thu, 21 Aug 2014 11:28:52 GMT 27 | Content-Type: 28 | - application/vnd.contentful.management.v1+json 29 | Content-Length: 30 | - '626' 31 | Connection: 32 | - keep-alive 33 | Status: 34 | - 200 OK 35 | X-Contentful-Request-Id: 36 | - 85f-929381571 37 | Etag: 38 | - '"0c4c4b7901c0c7db0df9cd944bf718e3"' 39 | Accept-Ranges: 40 | - bytes 41 | Cache-Control: 42 | - max-age=0 43 | Access-Control-Allow-Origin: 44 | - "*" 45 | Access-Control-Allow-Headers: 46 | - Accept,Accept-Language,Authorization,Cache-Control,Content-Length,Content-Range,Content-Type,DNT,Destination,Expires,If-Match,If-Modified-Since,If-None-Match,Keep-Alive,Last-Modified,Origin,Pragma,Range,User-Agent,X-Http-Method-Override,X-Mx-ReqToken,X-Requested-With,X-Contentful-Version,X-Contentful-Content-Type,X-Contentful-Organization 47 | Access-Control-Allow-Methods: 48 | - DELETE,GET,HEAD,POST,PUT,OPTIONS 49 | "^access-Control-Expose-Headers": 50 | - Etag 51 | Access-Control-Max-Age: 52 | - '1728000' 53 | body: 54 | encoding: UTF-8 55 | string: | 56 | { 57 | "sys":{ 58 | "type":"WebhookDefinition", 59 | "id":"test_webhook", 60 | "version":0, 61 | "space":{ 62 | "sys":{ 63 | "type":"Link", 64 | "linkType":"Space", 65 | "id":"bfsvtul0c41g" 66 | } 67 | }, 68 | "createdBy":{ 69 | "sys":{ 70 | "type":"Link", 71 | "linkType":"User", 72 | "id":"1E7acJL8I5XUXAMHQt9Grs" 73 | } 74 | }, 75 | "createdAt":"2014-08-21T11:28:52Z", 76 | "updatedBy":{ 77 | "sys":{ 78 | "type":"Link", 79 | "linkType":"User", 80 | "id":"1E7acJL8I5XUXAMHQt9Grs" 81 | } 82 | }, 83 | "updatedAt":"2014-08-21T11:28:52Z" 84 | }, 85 | "url":"https://www.example3.com", 86 | "httpBasicUsername":null} 87 | http_version: 88 | recorded_at: Thu, 21 Aug 2014 11:28:49 GMT 89 | recorded_with: VCR 2.9.2 90 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/content_type/create.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: post 5 | uri: https://api.contentful.com/spaces/yr5m0jky5hsh/environments/master/content_types 6 | body: 7 | encoding: UTF-8 8 | string: '{"name":"Blog","description":"Blog content type","fields":[]}' 9 | headers: 10 | User-Agent: 11 | - RubyContenfulManagementGem/0.0.1 12 | Authorization: 13 | - Bearer 14 | Content-Type: 15 | - application/vnd.contentful.management.v1+json 16 | Host: 17 | - api.contentful.com 18 | response: 19 | status: 20 | code: 201 21 | message: Created 22 | headers: 23 | Server: 24 | - nginx 25 | Date: 26 | - Thu, 31 Jul 2014 09:12:04 GMT 27 | Content-Type: 28 | - application/vnd.contentful.management.v1+json 29 | Content-Length: 30 | - '667' 31 | Connection: 32 | - keep-alive 33 | X-Powered-By: 34 | - Express 35 | Cf-Space-Id: 36 | - yr5m0jky5hsh 37 | Etag: 38 | - '"aed3e6d4eba159414ceb1c95467ce7d7"' 39 | Access-Control-Allow-Origin: 40 | - "*" 41 | Access-Control-Allow-Headers: 42 | - Accept,Accept-Language,Authorization,Cache-Control,Content-Length,Content-Range,Content-Type,DNT,Destination,Expires,If-Match,If-Modified-Since,If-None-Match,Keep-Alive,Last-Modified,Origin,Pragma,Range,User-Agent,X-Http-Method-Override,X-Mx-ReqToken,X-Requested-With,X-Contentful-Version,X-Contentful-Content-Type,X-Contentful-Organization 43 | Access-Control-Allow-Methods: 44 | - DELETE,GET,HEAD,POST,PUT,OPTIONS 45 | "^access-Control-Expose-Headers": 46 | - Etag 47 | Access-Control-Max-Age: 48 | - '1728000' 49 | body: 50 | encoding: UTF-8 51 | string: | 52 | { 53 | "name": "Blog", 54 | "description": "Blog content type", 55 | "fields": [], 56 | "sys": { 57 | "id": "qw3F2rn3FeoOiceqAiCSC", 58 | "type": "ContentType", 59 | "version": 1, 60 | "createdAt": "2014-07-31T09:12:04.064Z", 61 | "createdBy": { 62 | "sys": { 63 | "type": "Link", 64 | "linkType": "User", 65 | "id": "0fn5fOWn4WsKFyYla1gI5h" 66 | } 67 | }, 68 | "space": { 69 | "sys": { 70 | "type": "Link", 71 | "linkType": "Space", 72 | "id": "yr5m0jky5hsh" 73 | } 74 | }, 75 | "updatedAt": "2014-07-31T09:12:04.064Z", 76 | "updatedBy": { 77 | "sys": { 78 | "type": "Link", 79 | "linkType": "User", 80 | "id": "0fn5fOWn4WsKFyYla1gI5h" 81 | } 82 | } 83 | } 84 | } 85 | http_version: 86 | recorded_at: Thu, 31 Jul 2014 09:12:04 GMT 87 | recorded_with: VCR 2.9.2 88 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/webhook/find.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: get 5 | uri: https://api.contentful.com/spaces/bfsvtul0c41g/webhook_definitions/0rK8ZNEOWLgYnO5gaah2pp 6 | body: 7 | encoding: US-ASCII 8 | string: '' 9 | headers: 10 | User-Agent: 11 | - RubyContenfulManagementGem/0.0.3 12 | Authorization: 13 | - Bearer 14 | Content-Type: 15 | - application/vnd.contentful.management.v1+json 16 | Content-Length: 17 | - '0' 18 | Host: 19 | - api.contentful.com 20 | response: 21 | status: 22 | code: 200 23 | message: OK 24 | headers: 25 | Server: 26 | - nginx 27 | Date: 28 | - Thu, 21 Aug 2014 12:10:50 GMT 29 | Content-Type: 30 | - application/vnd.contentful.management.v1+json 31 | Content-Length: 32 | - '646' 33 | Connection: 34 | - keep-alive 35 | Status: 36 | - 200 OK 37 | X-Contentful-Request-Id: 38 | - 85f-929390178 39 | Etag: 40 | - '"c36f93465aaba9a426e41e82fe853312"' 41 | Accept-Ranges: 42 | - bytes 43 | Cache-Control: 44 | - max-age=0 45 | Access-Control-Allow-Origin: 46 | - "*" 47 | Access-Control-Allow-Headers: 48 | - Accept,Accept-Language,Authorization,Cache-Control,Content-Length,Content-Range,Content-Type,DNT,Destination,Expires,If-Match,If-Modified-Since,If-None-Match,Keep-Alive,Last-Modified,Origin,Pragma,Range,User-Agent,X-Http-Method-Override,X-Mx-ReqToken,X-Requested-With,X-Contentful-Version,X-Contentful-Content-Type,X-Contentful-Organization 49 | Access-Control-Allow-Methods: 50 | - DELETE,GET,HEAD,POST,PUT,OPTIONS 51 | "^access-Control-Expose-Headers": 52 | - Etag 53 | Access-Control-Max-Age: 54 | - '1728000' 55 | body: 56 | encoding: UTF-8 57 | string: | 58 | { 59 | "sys":{ 60 | "type":"WebhookDefinition", 61 | "id":"0rK8ZNEOWLgYnO5gaah2pp", 62 | "version":1, 63 | "space":{ 64 | "sys":{ 65 | "type":"Link", 66 | "linkType":"Space", 67 | "id":"bfsvtul0c41g" 68 | } 69 | }, 70 | "createdBy":{ 71 | "sys":{ 72 | "type":"Link", 73 | "linkType":"User", 74 | "id":"1E7acJL8I5XUXAMHQt9Grs" 75 | } 76 | }, 77 | "createdAt":"2014-08-20T12:40:14Z", 78 | "updatedBy":{ 79 | "sys":{ 80 | "type":"Link", 81 | "linkType":"User", 82 | "id":"1E7acJL8I5XUXAMHQt9Grs" 83 | } 84 | }, 85 | "updatedAt":"2014-08-21T10:01:33Z" 86 | }, 87 | "url":"https://www.example.com", 88 | "httpBasicUsername":"some_username"} 89 | http_version: 90 | recorded_at: Thu, 21 Aug 2014 12:10:45 GMT 91 | recorded_with: VCR 2.9.2 92 | -------------------------------------------------------------------------------- /lib/contentful/management/resource/field_aware.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Contentful 4 | module Management 5 | module Resource 6 | # Module for creating Fields based off of ContentTypes 7 | module FieldAware 8 | # Creates fields for entry based on it's ContentType 9 | # 10 | # @param [Entry] entry the expected entry to modify 11 | def self.create_fields_for_content_type(entry, method = :instance) 12 | entry.content_type.fields.each do |field| 13 | accessor_name = Support.snakify(field.id) 14 | 15 | FieldAware.create_getter(entry, accessor_name, field, method) 16 | FieldAware.create_setter(entry, accessor_name, field, method) 17 | end 18 | end 19 | 20 | # Creates getters for field 21 | # @private 22 | def self.create_getter(entry, accessor_name, field, method) 23 | entry.send("#{method}_eval") do 24 | send(FieldAware.define(method), accessor_name) do 25 | fields[field.id.to_sym] 26 | end 27 | 28 | send(FieldAware.define(method), "#{accessor_name}_with_locales") do 29 | fields_for_query(false)[field.id.to_sym] 30 | end 31 | end 32 | end 33 | 34 | # Creates setters for field 35 | # @private 36 | def self.create_setter(entry, accessor_name, field, method) 37 | entry.send("#{method}_eval") do 38 | send(FieldAware.define(method), "#{accessor_name}=") do |value| 39 | FieldAware.create_setter_field(self, field, value, locale, default_locale) 40 | end 41 | 42 | send(FieldAware.define(method), "#{accessor_name}_with_locales=") do |values| 43 | values.each do |locale, value| 44 | FieldAware.create_setter_field(self, field, value, locale, default_locale) 45 | end 46 | end 47 | end 48 | end 49 | 50 | # Sets fields with value for locale 51 | # @private 52 | def self.create_setter_field(entry, field, value, locale, default_locale) 53 | fields = entry.instance_variable_get(:@fields) 54 | 55 | return unless localized_or_default_locale(field, default_locale, locale) 56 | 57 | fields[locale] ||= {} 58 | fields[locale][field.id.to_sym] = value 59 | end 60 | 61 | # Verifies if field is localized or default locale matches current locale 62 | # 63 | # @param [Field] field an entry field 64 | # @param [String] default_locale 65 | # @param [String] locale 66 | # 67 | # @return [Boolean] 68 | def self.localized_or_default_locale(field, default_locale, locale) 69 | field.localized || default_locale == locale 70 | end 71 | 72 | # @private 73 | def self.define(class_or_instance) 74 | "define_#{class_or_instance == :instance ? 'singleton_' : ''}method" 75 | end 76 | end 77 | end 78 | end 79 | end 80 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/upload/create_file.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: post 5 | uri: https://upload.contentful.com/spaces/facgnwwgj5fe/uploads 6 | body: 7 | encoding: ASCII-8BIT 8 | string: !binary |- 9 | /9j/4AAQSkZJRgABAQEASABIAAD/2wBDAP////////////////////////// 10 | //////////////////////////////////////////////////////////// 11 | 2wBDAf////////////////////////////////////////////////////// 12 | ////////////////////////////////wAARCAABAAEDASIAAhEBAxEB/8QA 13 | FQABAQAAAAAAAAAAAAAAAAAAAAP/xAAUEAEAAAAAAAAAAAAAAAAAAAAA/8QA 14 | FAEBAAAAAAAAAAAAAAAAAAAAAP/EABQRAQAAAAAAAAAAAAAAAAAAAAD/2gAM 15 | AwEAAhEDEQA/AJgA/9k= 16 | headers: 17 | User-Agent: 18 | - RubyContentfulManagementGem/1.6.0 19 | Authorization: 20 | - Bearer 21 | Content-Type: 22 | - application/octet-stream 23 | Connection: 24 | - close 25 | Host: 26 | - upload.contentful.com 27 | response: 28 | status: 29 | code: 201 30 | message: Created 31 | headers: 32 | Access-Control-Allow-Headers: 33 | - Accept,Accept-Language,Authorization,Cache-Control,Content-Length,Content-Range,Content-Type,DNT,Destination,Expires,If-Match,If-Modified-Since,If-None-Match,Keep-Alive,Last-Modified,Origin,Pragma,Range,User-Agent,X-Http-Method-Override,X-Mx-ReqToken,X-Requested-With,X-Contentful-Version,X-Contentful-Content-Type,X-Contentful-Organization,X-Contentful-Skip-Transformation,X-Contentful-User-Agent 34 | Access-Control-Allow-Origin: 35 | - "*" 36 | Access-Control-Expose-Headers: 37 | - Etag 38 | Cache-Control: 39 | - no-cache 40 | Content-Type: 41 | - application/vnd.contentful.management.v1+json 42 | Date: 43 | - Tue, 25 Apr 2017 14:01:08 GMT 44 | Server: 45 | - Contentful 46 | Strict-Transport-Security: 47 | - max-age=15768000 48 | Vary: 49 | - accept-encoding 50 | X-Content-Type-Options: 51 | - nosniff 52 | X-Contentful-Request-Id: 53 | - 55f47fb1a4e472e127ce1c5a766f18fa 54 | Content-Length: 55 | - '432' 56 | Connection: 57 | - Close 58 | body: 59 | encoding: ASCII-8BIT 60 | string: |- 61 | { 62 | "sys": { 63 | "id": "6ltsWxSmH0uelLeX6GL7nV", 64 | "type": "Upload", 65 | "createdAt": "2017-04-25T14:01:09.000Z", 66 | "expiresAt": "2017-04-27T00:00:00.000Z", 67 | "space": { 68 | "sys": { 69 | "type": "Link", 70 | "linkType": "Space", 71 | "id": "facgnwwgj5fe" 72 | } 73 | }, 74 | "createdBy": { 75 | "sys": { 76 | "type": "Link", 77 | "linkType": "User", 78 | "id": "4SejVrWT96dvL9IV4Nb7sQ" 79 | } 80 | } 81 | } 82 | } 83 | http_version: 84 | recorded_at: Tue, 25 Apr 2017 14:01:09 GMT 85 | recorded_with: VCR 3.0.3 86 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/upload/create_path.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: post 5 | uri: https://upload.contentful.com/spaces/facgnwwgj5fe/uploads 6 | body: 7 | encoding: ASCII-8BIT 8 | string: !binary |- 9 | /9j/4AAQSkZJRgABAQEASABIAAD/2wBDAP////////////////////////// 10 | //////////////////////////////////////////////////////////// 11 | 2wBDAf////////////////////////////////////////////////////// 12 | ////////////////////////////////wAARCAABAAEDASIAAhEBAxEB/8QA 13 | FQABAQAAAAAAAAAAAAAAAAAAAAP/xAAUEAEAAAAAAAAAAAAAAAAAAAAA/8QA 14 | FAEBAAAAAAAAAAAAAAAAAAAAAP/EABQRAQAAAAAAAAAAAAAAAAAAAAD/2gAM 15 | AwEAAhEDEQA/AJgA/9k= 16 | headers: 17 | User-Agent: 18 | - RubyContentfulManagementGem/1.6.0 19 | Authorization: 20 | - Bearer 21 | Content-Type: 22 | - application/octet-stream 23 | Connection: 24 | - close 25 | Host: 26 | - upload.contentful.com 27 | response: 28 | status: 29 | code: 201 30 | message: Created 31 | headers: 32 | Access-Control-Allow-Headers: 33 | - Accept,Accept-Language,Authorization,Cache-Control,Content-Length,Content-Range,Content-Type,DNT,Destination,Expires,If-Match,If-Modified-Since,If-None-Match,Keep-Alive,Last-Modified,Origin,Pragma,Range,User-Agent,X-Http-Method-Override,X-Mx-ReqToken,X-Requested-With,X-Contentful-Version,X-Contentful-Content-Type,X-Contentful-Organization,X-Contentful-Skip-Transformation,X-Contentful-User-Agent 34 | Access-Control-Allow-Origin: 35 | - "*" 36 | Access-Control-Expose-Headers: 37 | - Etag 38 | Cache-Control: 39 | - no-cache 40 | Content-Type: 41 | - application/vnd.contentful.management.v1+json 42 | Date: 43 | - Tue, 25 Apr 2017 14:01:09 GMT 44 | Server: 45 | - Contentful 46 | Strict-Transport-Security: 47 | - max-age=15768000 48 | Vary: 49 | - accept-encoding 50 | X-Content-Type-Options: 51 | - nosniff 52 | X-Contentful-Request-Id: 53 | - 47d19da405d23feab565da42bf4f1b99 54 | Content-Length: 55 | - '432' 56 | Connection: 57 | - Close 58 | body: 59 | encoding: ASCII-8BIT 60 | string: |- 61 | { 62 | "sys": { 63 | "id": "5U7s6EZ3CE9D7ZS25Rkayk", 64 | "type": "Upload", 65 | "createdAt": "2017-04-25T14:01:10.000Z", 66 | "expiresAt": "2017-04-27T00:00:00.000Z", 67 | "space": { 68 | "sys": { 69 | "type": "Link", 70 | "linkType": "Space", 71 | "id": "facgnwwgj5fe" 72 | } 73 | }, 74 | "createdBy": { 75 | "sys": { 76 | "type": "Link", 77 | "linkType": "User", 78 | "id": "4SejVrWT96dvL9IV4Nb7sQ" 79 | } 80 | } 81 | } 82 | } 83 | http_version: 84 | recorded_at: Tue, 25 Apr 2017 14:01:10 GMT 85 | recorded_with: VCR 3.0.3 86 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/locale/find.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: get 5 | uri: https://api.contentful.com/spaces/n6spjc167pc2/environments/master/locales/0X5xcjckv6RMrd9Trae81p 6 | body: 7 | encoding: US-ASCII 8 | string: '' 9 | headers: 10 | User-Agent: 11 | - RubyContenfulManagementGem/0.0.1 12 | Authorization: 13 | - Bearer 14 | Content-Type: 15 | - application/vnd.contentful.management.v1+json 16 | Content-Length: 17 | - '0' 18 | Host: 19 | - api.contentful.com 20 | response: 21 | status: 22 | code: 200 23 | message: OK 24 | headers: 25 | Server: 26 | - nginx 27 | Date: 28 | - Mon, 14 Jul 2014 07:44:57 GMT 29 | Content-Type: 30 | - application/vnd.contentful.management.v1+json 31 | Content-Length: 32 | - '703' 33 | Connection: 34 | - keep-alive 35 | Status: 36 | - 200 OK 37 | X-Contentful-Request-Id: 38 | - 85f-1209864303 39 | Etag: 40 | - '"84473d86f0e8887dd6b44d2ffe155176"' 41 | Accept-Ranges: 42 | - bytes 43 | Cache-Control: 44 | - max-age=0 45 | Access-Control-Allow-Origin: 46 | - "*" 47 | Access-Control-Allow-Headers: 48 | - Accept,Accept-Language,Authorization,Cache-Control,Content-Length,Content-Range,Content-Type,DNT,Destination,Expires,If-Match,If-Modified-Since,If-None-Match,Keep-Alive,Last-Modified,Origin,Pragma,Range,User-Agent,X-Http-Method-Override,X-Mx-ReqToken,X-Requested-With,X-Contentful-Version,X-Contentful-Content-Type,X-Contentful-Organization 49 | Access-Control-Allow-Methods: 50 | - DELETE,GET,HEAD,POST,PUT,OPTIONS 51 | "^access-Control-Expose-Headers": 52 | - Etag 53 | Access-Control-Max-Age: 54 | - '1728000' 55 | body: 56 | encoding: UTF-8 57 | string: | 58 | { 59 | "sys":{ 60 | "type":"Locale", 61 | "id":"0X5xcjckv6RMrd9Trae81p", 62 | "version":6, 63 | "space":{ 64 | "sys":{ 65 | "type":"Link", 66 | "linkType":"Space", 67 | "id":"n6spjc167pc2" 68 | } 69 | }, 70 | "createdBy":{ 71 | "sys":{ 72 | "type":"Link", 73 | "linkType":"User", 74 | "id":"1E7acJL8I5XUXAMHQt9Grs" 75 | } 76 | }, 77 | "createdAt":"2014-07-11T10:43:30Z", 78 | "updatedBy":{ 79 | "sys":{ 80 | "type":"Link", 81 | "linkType":"User", 82 | "id":"1E7acJL8I5XUXAMHQt9Grs" 83 | } 84 | }, 85 | "updatedAt":"2014-07-11T13:29:23Z" 86 | }, 87 | "name":"testNewLocaleName", 88 | "code":"pl", 89 | "default":false, 90 | "contentManagementApi":true, 91 | "publish":true, 92 | "contentDeliveryApi":true} 93 | http_version: 94 | recorded_at: Mon, 14 Jul 2014 07:44:57 GMT 95 | recorded_with: VCR 2.9.2 96 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/locale/find_default.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: get 5 | uri: https://api.contentful.com/spaces/n6spjc167pc2/environments/master/locales/0X5xcjckv6RMrd9Trae81p 6 | body: 7 | encoding: US-ASCII 8 | string: '' 9 | headers: 10 | User-Agent: 11 | - RubyContenfulManagementGem/0.0.1 12 | Authorization: 13 | - Bearer 14 | Content-Type: 15 | - application/vnd.contentful.management.v1+json 16 | Content-Length: 17 | - '0' 18 | Host: 19 | - api.contentful.com 20 | response: 21 | status: 22 | code: 200 23 | message: OK 24 | headers: 25 | Server: 26 | - nginx 27 | Date: 28 | - Mon, 14 Jul 2014 07:44:57 GMT 29 | Content-Type: 30 | - application/vnd.contentful.management.v1+json 31 | Content-Length: 32 | - '703' 33 | Connection: 34 | - keep-alive 35 | Status: 36 | - 200 OK 37 | X-Contentful-Request-Id: 38 | - 85f-1209864303 39 | Etag: 40 | - '"84473d86f0e8887dd6b44d2ffe155176"' 41 | Accept-Ranges: 42 | - bytes 43 | Cache-Control: 44 | - max-age=0 45 | Access-Control-Allow-Origin: 46 | - "*" 47 | Access-Control-Allow-Headers: 48 | - Accept,Accept-Language,Authorization,Cache-Control,Content-Length,Content-Range,Content-Type,DNT,Destination,Expires,If-Match,If-Modified-Since,If-None-Match,Keep-Alive,Last-Modified,Origin,Pragma,Range,User-Agent,X-Http-Method-Override,X-Mx-ReqToken,X-Requested-With,X-Contentful-Version,X-Contentful-Content-Type,X-Contentful-Organization 49 | Access-Control-Allow-Methods: 50 | - DELETE,GET,HEAD,POST,PUT,OPTIONS 51 | "^access-Control-Expose-Headers": 52 | - Etag 53 | Access-Control-Max-Age: 54 | - '1728000' 55 | body: 56 | encoding: UTF-8 57 | string: | 58 | { 59 | "sys":{ 60 | "type":"Locale", 61 | "id":"0X5xcjckv6RMrd9Trae81p", 62 | "version":6, 63 | "space":{ 64 | "sys":{ 65 | "type":"Link", 66 | "linkType":"Space", 67 | "id":"n6spjc167pc2" 68 | } 69 | }, 70 | "createdBy":{ 71 | "sys":{ 72 | "type":"Link", 73 | "linkType":"User", 74 | "id":"1E7acJL8I5XUXAMHQt9Grs" 75 | } 76 | }, 77 | "createdAt":"2014-07-11T10:43:30Z", 78 | "updatedBy":{ 79 | "sys":{ 80 | "type":"Link", 81 | "linkType":"User", 82 | "id":"1E7acJL8I5XUXAMHQt9Grs" 83 | } 84 | }, 85 | "updatedAt":"2014-07-11T13:29:23Z" 86 | }, 87 | "name":"testNewLocaleName", 88 | "code":"pl", 89 | "default":true, 90 | "contentManagementApi":true, 91 | "publish":true, 92 | "contentDeliveryApi":true} 93 | http_version: 94 | recorded_at: Mon, 14 Jul 2014 07:44:57 GMT 95 | recorded_with: VCR 2.9.2 96 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/locale/find_not_default.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: get 5 | uri: https://api.contentful.com/spaces/n6spjc167pc2/environments/master/locales/0X5xcjckv6RMrd9Trae81p 6 | body: 7 | encoding: US-ASCII 8 | string: '' 9 | headers: 10 | User-Agent: 11 | - RubyContenfulManagementGem/0.0.1 12 | Authorization: 13 | - Bearer 14 | Content-Type: 15 | - application/vnd.contentful.management.v1+json 16 | Content-Length: 17 | - '0' 18 | Host: 19 | - api.contentful.com 20 | response: 21 | status: 22 | code: 200 23 | message: OK 24 | headers: 25 | Server: 26 | - nginx 27 | Date: 28 | - Mon, 14 Jul 2014 07:44:57 GMT 29 | Content-Type: 30 | - application/vnd.contentful.management.v1+json 31 | Content-Length: 32 | - '703' 33 | Connection: 34 | - keep-alive 35 | Status: 36 | - 200 OK 37 | X-Contentful-Request-Id: 38 | - 85f-1209864303 39 | Etag: 40 | - '"84473d86f0e8887dd6b44d2ffe155176"' 41 | Accept-Ranges: 42 | - bytes 43 | Cache-Control: 44 | - max-age=0 45 | Access-Control-Allow-Origin: 46 | - "*" 47 | Access-Control-Allow-Headers: 48 | - Accept,Accept-Language,Authorization,Cache-Control,Content-Length,Content-Range,Content-Type,DNT,Destination,Expires,If-Match,If-Modified-Since,If-None-Match,Keep-Alive,Last-Modified,Origin,Pragma,Range,User-Agent,X-Http-Method-Override,X-Mx-ReqToken,X-Requested-With,X-Contentful-Version,X-Contentful-Content-Type,X-Contentful-Organization 49 | Access-Control-Allow-Methods: 50 | - DELETE,GET,HEAD,POST,PUT,OPTIONS 51 | "^access-Control-Expose-Headers": 52 | - Etag 53 | Access-Control-Max-Age: 54 | - '1728000' 55 | body: 56 | encoding: UTF-8 57 | string: | 58 | { 59 | "sys":{ 60 | "type":"Locale", 61 | "id":"0X5xcjckv6RMrd9Trae81p", 62 | "version":6, 63 | "space":{ 64 | "sys":{ 65 | "type":"Link", 66 | "linkType":"Space", 67 | "id":"n6spjc167pc2" 68 | } 69 | }, 70 | "createdBy":{ 71 | "sys":{ 72 | "type":"Link", 73 | "linkType":"User", 74 | "id":"1E7acJL8I5XUXAMHQt9Grs" 75 | } 76 | }, 77 | "createdAt":"2014-07-11T10:43:30Z", 78 | "updatedBy":{ 79 | "sys":{ 80 | "type":"Link", 81 | "linkType":"User", 82 | "id":"1E7acJL8I5XUXAMHQt9Grs" 83 | } 84 | }, 85 | "updatedAt":"2014-07-11T13:29:23Z" 86 | }, 87 | "name":"testNewLocaleName", 88 | "code":"pl", 89 | "default":false, 90 | "contentManagementApi":true, 91 | "publish":true, 92 | "contentDeliveryApi":true} 93 | http_version: 94 | recorded_at: Mon, 14 Jul 2014 07:44:57 GMT 95 | recorded_with: VCR 2.9.2 96 | -------------------------------------------------------------------------------- /spec/fixtures/vcr_cassettes/taxonomy_concept/total.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: get 5 | uri: https://api.contentful.com/organizations/4kQeJmhUWIKtNNmMkketza/taxonomy/concepts/total 6 | body: 7 | encoding: UTF-8 8 | string: '' 9 | headers: 10 | X-Contentful-User-Agent: 11 | - sdk contentful-management.rb/3.11.0; platform ruby/3.4.3; os macOS/24; 12 | Authorization: 13 | - Bearer 14 | Content-Type: 15 | - application/vnd.contentful.management.v1+json 16 | Connection: 17 | - close 18 | Host: 19 | - api.contentful.com 20 | User-Agent: 21 | - http.rb/5.0.1 22 | response: 23 | status: 24 | code: 200 25 | message: OK 26 | headers: 27 | Connection: 28 | - close 29 | Content-Length: 30 | - '11' 31 | Content-Type: 32 | - application/json; charset=utf-8 33 | X-Contentful-Ratelimit-Reset: 34 | - '0' 35 | X-Contentful-Ratelimit-Hour-Remaining: 36 | - '35999' 37 | X-Contentful-Ratelimit-Second-Remaining: 38 | - '9' 39 | X-Contentful-Ratelimit-Hour-Limit: 40 | - '36000' 41 | X-Contentful-Ratelimit-Second-Limit: 42 | - '10' 43 | X-Contentful-Route: 44 | - "/organizations/:organizationId/taxonomy/concepts/total" 45 | Cache-Control: 46 | - no-cache 47 | Accept-Ranges: 48 | - bytes 49 | X-Content-Type-Options: 50 | - nosniff 51 | Server: 52 | - Contentful 53 | Contentful-Api: 54 | - cma 55 | Contentful-Upstream: 56 | - taxonomy-service 57 | Access-Control-Allow-Origin: 58 | - "*" 59 | Access-Control-Allow-Headers: 60 | - Accept,Accept-Language,Authorization,Cache-Control,CF-Context,Content-Length,Content-Range,Content-Type,DNT,Destination,Expires,If-Match,If-Modified-Since,If-None-Match,Keep-Alive,Last-Modified,Origin,Pragma,Range,User-Agent,X-Http-Method-Override,X-Mx-ReqToken,X-Requested-With,X-Contentful-Version,X-Contentful-Content-Type,X-Contentful-Organization,X-Contentful-Skip-Transformation,X-Contentful-Tag-Visibility,X-Contentful-User-Agent,X-Contentful-Enable-Alpha-Feature,X-Contentful-Source-Environment,X-Contentful-Team,X-Contentful-Parent-Id,x-contentful-validate-only,X-Contentful-Skip-UI-Draft-Validation,X-Contentful-Marketplace,X-Contentful-UI-Content-Auto-Save,cf-trace,X-Contentful-Comment-Body-Format,X-Contentful-Parent-Entity-Reference,X-Contentful-Include-Invocation-Metadata,X-Contentful-Async-Ai-Action,x-contentful-ai-actions-platform 61 | Access-Control-Expose-Headers: 62 | - Etag,x-contentful-request-id,x-contentful-ai-actions-ratelimit-reset 63 | Access-Control-Allow-Methods: 64 | - DELETE,GET,HEAD,POST,PUT,PATCH,OPTIONS 65 | Access-Control-Max-Age: 66 | - '1728000' 67 | Date: 68 | - Wed, 22 Oct 2025 13:02:36 GMT 69 | X-Contentful-Request-Id: 70 | - 5aaff337-b6e2-4c01-a4e3-b34700978211 71 | Strict-Transport-Security: 72 | - max-age=15768000 73 | body: 74 | encoding: UTF-8 75 | string: '{"total":9}' 76 | recorded_at: Wed, 22 Oct 2025 13:02:36 GMT 77 | recorded_with: VCR 6.2.0 78 | --------------------------------------------------------------------------------