├── log └── .keep ├── app ├── mailers │ └── .keep ├── models │ ├── .keep │ ├── concerns │ │ ├── .keep │ │ └── has_primitive_type.rb │ ├── member.rb │ ├── api_gateway_integration.rb │ ├── application_record.rb │ ├── api_error_instance.rb │ ├── metadatum_instance.rb │ ├── resource_instance.rb │ ├── scheme.rb │ ├── metadata_response.rb │ ├── validation_error.rb │ ├── query_parameter.rb │ ├── api_error.rb │ ├── header.rb │ ├── metadatum.rb │ ├── mock_profile.rb │ └── report.rb ├── controllers │ ├── concerns │ │ ├── .keep │ │ ├── authenticated.rb │ │ └── project_related.rb │ ├── api_error_instances_controller.rb │ ├── metadatum_instances_controller.rb │ ├── instances_controller.rb │ ├── resource_instances_controller.rb │ ├── headers_controller.rb │ ├── validations_controller.rb │ ├── audits_controller.rb │ ├── users │ │ └── omniauth_callbacks_controller.rb │ ├── schemes_controller.rb │ └── users_controller.rb ├── helpers │ ├── application_helper.rb │ ├── android_code_gen_helper.rb │ ├── attributes_helper.rb │ ├── sidebar_helper.rb │ ├── validations_helper.rb │ └── responses_helper.rb ├── views │ ├── audits │ │ ├── _missing_partial.html.haml │ │ ├── _missing_partial.mrkdwn.erb │ │ ├── route │ │ │ ├── _destroy.mrkdwn.erb │ │ │ ├── _destroy.html.erb │ │ │ ├── _create.mrkdwn.erb │ │ │ ├── _create.html.erb │ │ │ ├── _update.mrkdwn.erb │ │ │ └── _update.html.erb │ │ ├── resource │ │ │ ├── _destroy.mrkdwn.erb │ │ │ ├── _destroy.html.erb │ │ │ ├── _create.mrkdwn.erb │ │ │ ├── _create.html.erb │ │ │ ├── _update.mrkdwn.erb │ │ │ └── _update.html.erb │ │ ├── metadatum │ │ │ ├── _destroy.mrkdwn.erb │ │ │ ├── _destroy.html.erb │ │ │ ├── _create.mrkdwn.erb │ │ │ ├── _create.html.erb │ │ │ ├── _update.mrkdwn.erb │ │ │ └── _update.html.erb │ │ ├── resources_representation │ │ │ ├── _destroy.mrkdwn.erb │ │ │ ├── _destroy.html.erb │ │ │ ├── _create.mrkdwn.erb │ │ │ ├── _create.html.erb │ │ │ ├── _update.mrkdwn.erb │ │ │ └── _update.html.erb │ │ ├── _changes.mrkdwn.erb │ │ ├── response │ │ │ ├── _create.mrkdwn.erb │ │ │ ├── _destroy.mrkdwn.erb │ │ │ ├── _update.mrkdwn.erb │ │ │ ├── _destroy.html.erb │ │ │ ├── _create.html.erb │ │ │ └── _update.html.erb │ │ ├── _changes.html.haml │ │ ├── metadata_response │ │ │ ├── _create.mrkdwn.erb │ │ │ ├── _destroy.mrkdwn.erb │ │ │ ├── _destroy.html.erb │ │ │ ├── _update.mrkdwn.erb │ │ │ ├── _create.html.erb │ │ │ └── _update.html.erb │ │ ├── attribute │ │ │ ├── _destroy.mrkdwn.erb │ │ │ ├── _create.mrkdwn.erb │ │ │ ├── _destroy.html.erb │ │ │ ├── _create.html.erb │ │ │ ├── _update.mrkdwn.erb │ │ │ └── _update.html.erb │ │ └── attributes_resource_representation │ │ │ ├── _create.mrkdwn.erb │ │ │ ├── _destroy.mrkdwn.erb │ │ │ ├── _create.html.erb │ │ │ ├── _destroy.html.erb │ │ │ ├── _update.mrkdwn.erb │ │ │ └── _update.html.erb │ ├── projects │ │ ├── edit.html.haml │ │ ├── new.html.haml │ │ ├── _proxy_configuration_fields.html.haml │ │ ├── _api_gateway_integration_fields.html.haml │ │ └── index.html.haml │ ├── api_errors │ │ ├── new.html.haml │ │ ├── edit.html.haml │ │ ├── _form.html.haml │ │ ├── _new_form.html.haml │ │ └── index.html.haml │ ├── metadata │ │ ├── new.html.haml │ │ ├── edit.html.haml │ │ ├── show.html.haml │ │ ├── index.html.haml │ │ ├── _form.html.haml │ │ └── _metadatum.html.haml │ ├── resources │ │ ├── new.html.haml │ │ ├── edit_resource.html.haml │ │ ├── _edit_resource_form.html.haml │ │ ├── _resource_instances.html.haml │ │ ├── edit_attributes.html.haml │ │ ├── index.html.haml │ │ └── _create_form.html.haml │ ├── resource_instances │ │ ├── edit.html.haml │ │ ├── _resource_instance.html.haml │ │ ├── new.html.haml │ │ └── _form.html.haml │ ├── api_error_instances │ │ ├── _api_error_instance.html.haml │ │ ├── edit.html.haml │ │ ├── new.html.haml │ │ └── _form.html.haml │ ├── metadatum_instances │ │ ├── edit.html.haml │ │ ├── new.html.haml │ │ ├── _form.html.haml │ │ └── _metadatum_instance.html.haml │ ├── routes │ │ ├── new.html.haml │ │ ├── edit.html.haml │ │ ├── _request_header_fields.html.haml │ │ ├── _form.html.haml │ │ └── _request_query_parameter_fields.html.haml │ ├── schemes │ │ ├── new.html.haml │ │ ├── edit.html.haml │ │ ├── _form.html.haml │ │ └── index.html.haml │ ├── mock_profiles │ │ ├── edit.html.haml │ │ └── new.html.haml │ ├── security_schemes │ │ ├── new.html.haml │ │ ├── edit.html.haml │ │ ├── index.html.haml │ │ └── _security_scheme.html.haml │ ├── shared │ │ ├── _alert.html.haml │ │ ├── _last_edit.html.haml │ │ ├── _schema_errors.html.haml │ │ ├── _errors.html.haml │ │ └── _head.html.haml │ ├── layouts │ │ ├── no_navbar_layout.html.haml │ │ └── application.html.haml │ ├── responses │ │ ├── new.html.haml │ │ ├── edit.html.haml │ │ ├── _header_fields.html.haml │ │ └── _metadata_responses_fields.html.haml │ ├── devise │ │ └── mailer │ │ │ └── confirmation_instructions.html.haml │ ├── code │ │ ├── graphql.ruby.erb │ │ ├── rest.kotlin.erb │ │ ├── serializer.ruby.erb │ │ └── rest.swift.erb │ ├── resource_representations │ │ ├── new.html.haml │ │ └── edit.html.haml │ ├── headers │ │ └── _header.html.haml │ ├── users │ │ ├── show.html.haml │ │ └── index.html.haml │ ├── instances │ │ └── _instance.html.haml │ ├── query_parameters │ │ └── _query_parameter.html.haml │ └── validations │ │ └── new.html.haml ├── assets │ ├── images │ │ ├── sad.gif │ │ ├── arrow_back.svg │ │ ├── copy.svg │ │ ├── edit.svg │ │ ├── sort.svg │ │ └── reset.svg │ ├── stylesheets │ │ ├── styles │ │ │ ├── mock_instances.scss │ │ │ ├── responses.scss │ │ │ ├── projects.scss │ │ │ └── audits.scss │ │ ├── variables.scss │ │ └── main.scss │ └── javascripts │ │ ├── setup.js │ │ ├── validations │ │ └── new.js │ │ ├── security_schemes │ │ └── form.js │ │ ├── generate_instance.js │ │ └── resources │ │ └── new_representation.js ├── policies │ ├── api_error_instance_policy.rb │ ├── metadatum_instance_policy.rb │ ├── resource_instance_policy.rb │ ├── api_error_policy.rb │ ├── user_context.rb │ ├── resource_policy.rb │ ├── metadatum_policy.rb │ ├── scheme_policy.rb │ ├── security_scheme_policy.rb │ ├── response_policy.rb │ ├── user_policy.rb │ ├── project_related_policy.rb │ └── mock_profile_policy.rb ├── serializers │ ├── id_serializer.rb │ ├── header_serializer.rb │ ├── user_serializer.rb │ ├── validation_serializer.rb │ ├── resource_representation_serializer.rb │ ├── route_serializer.rb │ ├── resource_serializer.rb │ ├── resource_index_serializer.rb │ ├── extended_resource_representation_serializer.rb │ ├── attributes_resource_representation_serializer.rb │ └── attribute_serializer.rb ├── decorators │ ├── security_scheme_decorator.rb │ ├── api_error_instance_decorator.rb │ ├── metadatum_instance_decorator.rb │ ├── user_decorator.rb │ ├── attributes_resource_representation_decorator.rb │ ├── response_decorator.rb │ ├── proxy │ │ └── route_decorator.rb │ ├── json_schema │ │ ├── metadata_response_decorator.rb │ │ ├── attribute_decorator.rb │ │ ├── metadatum_decorator.rb │ │ └── response_decorator.rb │ ├── resource_decorator.rb │ ├── news │ │ ├── header_audit_decorator.rb │ │ ├── route_audit_decorator.rb │ │ ├── metadatum_audit_decorator.rb │ │ ├── resource_audit_decorator.rb │ │ ├── response_audit_decorator.rb │ │ └── attribute_audit_decorator.rb │ ├── code │ │ ├── resource_decorator.rb │ │ ├── resource_representation_decorator.rb │ │ ├── attribute_decorator.rb │ │ ├── attributes_resource_representation_decorator.rb │ │ └── data_class.rb │ ├── attribute_decorator.rb │ ├── authorization.rb │ ├── resource_instance_decorator.rb │ ├── http │ │ └── response_decorator.rb │ └── report_decorator.rb ├── view_models │ ├── news │ │ └── change.rb │ └── body_error │ │ ├── body_error_view_model.rb │ │ ├── additional_error_view_model.rb │ │ ├── enum_error_view_model.rb │ │ ├── required_error_view_model.rb │ │ └── type_error_view_model.rb ├── validators │ ├── hash_validator.rb │ ├── json_validator.rb │ ├── regexp_validator.rb │ ├── json_object_validator.rb │ └── json_schema_validator.rb ├── jobs │ └── report_validator_job.rb ├── repositories │ └── audits_repository.rb ├── javascript │ └── packs │ │ ├── common │ │ └── markdown.js │ │ ├── resources │ │ ├── ps-unused-resources.vue │ │ └── index.js │ │ └── application.js └── services │ ├── json_schema_builder.rb │ ├── generate_json_instance_service.rb │ ├── abstract_zip_builder.rb │ ├── mocks_zip_builder.rb │ ├── post_slack_news.rb │ └── set_slack_webhook.rb ├── lib ├── assets │ └── .keep ├── tasks │ ├── .keep │ ├── audits.rake │ └── proxy.rake ├── node │ └── generate_mock.js └── bootstrap_form │ └── regex.rb ├── public ├── favicon.ico ├── robots.txt ├── 403.html └── 404.html ├── test ├── helpers │ ├── .keep │ └── validations_helper_test.rb ├── mailers │ └── .keep ├── factories │ ├── members.rb │ ├── responses.rb │ ├── validations.rb │ ├── metadata_responses.rb │ ├── api_error_instances.rb │ ├── metadatum_instances.rb │ ├── mock_pickers.rb │ ├── proxy_configurations.rb │ ├── validation_error.rb │ ├── api_gateway_integrations.rb │ ├── schemes.rb │ ├── headers.rb │ ├── mock_profiles.rb │ ├── api_errors.rb │ ├── resource_instances.rb │ ├── metadata.rb │ ├── query_parameters.rb │ ├── attributes_resource_representations.rb │ ├── security_schemes.rb │ ├── attributes.rb │ ├── reports.rb │ └── users.rb ├── authentication │ └── controller_with_authentication_test.rb ├── models │ ├── audit_test.rb │ ├── factories_test.rb │ ├── validation_error_test.rb │ ├── header_test.rb │ ├── api_error_test.rb │ ├── metadata_response_test.rb │ ├── scheme_test.rb │ ├── query_parameter_test.rb │ └── metadatum_test.rb ├── lib │ └── tasks │ │ └── proxy_test.rb ├── decorators │ └── json_schema │ │ └── resource_representation_decorator_test.rb └── transactions │ └── create_rest_routes_transaction_test.rb ├── .nvmrc ├── .browserslistrc ├── banner.jpg ├── config ├── initializers │ ├── haml.rb │ ├── bootstrap_form.rb │ ├── session_store.rb │ ├── neat_json.rb │ ├── active_model_serializer.rb │ ├── application_controller_renderer.rb │ ├── filter_parameter_logging.rb │ ├── cookies_serializer.rb │ ├── backtrace_silencers.rb │ ├── audited.rb │ ├── wrap_parameters.rb │ ├── mime_types.rb │ └── inflections.rb ├── locales │ ├── metadata │ │ ├── en.yml │ │ └── fr.yml │ ├── audits │ │ ├── en.yml │ │ └── fr.yml │ ├── responses │ │ ├── en.yml │ │ └── fr.yml │ ├── security_schemes │ │ ├── en.yml │ │ └── fr.yml │ ├── users │ │ ├── en.yml │ │ └── fr.yml │ ├── reports │ │ ├── en.yml │ │ └── fr.yml │ ├── attributes │ │ ├── en.yml │ │ └── fr.yml │ ├── api_errors │ │ ├── en.yml │ │ └── fr.yml │ ├── resource_representations │ │ ├── en.yml │ │ └── fr.yml │ ├── fr.yml │ └── validations │ │ └── fr.yml ├── webpack │ ├── test.js │ ├── production.js │ ├── development.js │ ├── loaders │ │ ├── pug.js │ │ ├── vue.js │ │ └── vue-svg-loader.js │ └── environment.js ├── spring.rb ├── boot.rb ├── environment.rb ├── cable.yml └── database.yml ├── proxy ├── config │ ├── config.exs │ ├── dev.exs │ ├── prod.exs │ └── test.exs ├── elixir_buildpack.config ├── test │ └── test_helper.exs ├── .formatter.exs ├── lib │ ├── pericles_proxy │ │ ├── repositories │ │ │ ├── repo.ex │ │ │ └── proxy_configuration_repo.ex │ │ └── models │ │ │ ├── project.ex │ │ │ ├── delayed_job.ex │ │ │ └── proxy_configuration.ex │ └── pericles_proxy.ex ├── app.json └── .gitignore ├── bin ├── rake ├── bundle ├── rails ├── delayed_job ├── webpack ├── webpack-dev-server └── spring ├── docker-entrypoint.sh ├── Procfile ├── config.ru ├── db ├── migrate │ ├── 20170405185230_destroy_json_schemas.rb │ ├── 20171208095001_add_value_to_headers.rb │ ├── 20170524122014_add_enum_to_attributes.rb │ ├── 20170901134536_add_avatar_url_to_users.rb │ ├── 20171213105131_remove_name_from_routes.rb │ ├── 20170530095333_add_pattern_to_attributes.rb │ ├── 20170721161004_add_server_url_to_project.rb │ ├── 20170407182241_remove_body_schema_from_routes.rb │ ├── 20170410163242_add_route_id_to_responses.rb │ ├── 20170927092704_rename_faker_to_attribute_faker.rb │ ├── 20170407163730_add_request_body_schema_to_routes.rb │ ├── 20171030102800_rename_server_url_to_proxy_url.rb │ ├── 20171207110941_remove_description_from_headers.rb │ ├── 20180810134422_add_validated_to_reports.rb │ ├── 20171206161957_remove_description_from_responses.rb │ ├── 20171009090238_add_request_description_to_routes.rb │ ├── 20190626123920_add_slack_updated_at_to_projects.rb │ ├── 20170410163241_remove_response_schema_from_routes.rb │ ├── 20170901114536_add_name_to_users.rb │ ├── 20171114144052_remove_example_from_resource_attributes.rb │ ├── 20180109151423_add_is_public_to_projects.rb │ ├── 20190226135641_add_nullable_to_metadata.rb │ ├── 20170720153921_add_nullable_to_attribute.rb │ ├── 20170830082826_add_is_collection_to_routes.rb │ ├── 20171114100627_add_active_mock_profile_to_projects.rb │ ├── 20171206155832_remove_request_description_from_routes.rb │ ├── 20180727095817_add_instances_number_to_mock_pickers.rb │ ├── 20190529154416_add_priority_to_mock_pickers.rb │ ├── 20190121145846_add_key_to_metadata_responses.rb │ ├── 20170529094105_add_is_required_to_attributes.rb │ ├── 20170922083249_rename_body_schema_to_body_schema_backup.rb │ ├── 20191128145342_add_required_to_metadata_responses.rb │ ├── 20180529073528_add_unique_constraint_to_attribute_name.rb │ ├── 20171212072623_add_ancestry_to_mock_profiles.rb │ ├── 20170614152319_add_resource_representation_id_to_responses.rb │ ├── 20170918155835_add_faker_to_attributes_resource_representation.rb │ ├── 20180219094508_add_ignore_ssl_to_proxy_configuration.rb │ ├── 20190613080952_add_slack_to_projects.rb │ ├── 20191006172737_route_deprecated.rb │ ├── 20191101142812_add_operation_id.rb │ ├── 20171031084915_add_min_max_items_to_attributes.rb │ ├── 20180403141405_remove_schemas_backup.rb │ ├── 20161213093837_create_projects.rb │ ├── 20180116160324_add_recoverable_to_users.rb │ ├── 20170623124732_add_is_collection_to_resource_representations.rb │ ├── 20171013123912_rename_request_body_schema_to_request_body_schema_backup.rb │ ├── 20170322151410_create_validations.rb │ ├── 20170828152358_add_custom_nullable_to_attributes_resource_representations.rb │ ├── 20171130154438_add_is_null_to_attributes_resource_representation.rb │ ├── 20170407165817_create_responses.rb │ ├── 20171227103848_create_members.rb │ ├── 20171228165935_rename_key_name_to_custom_key_name.rb │ ├── 20170310105503_create_resources.rb │ ├── 20170329124037_create_json_errors.rb │ ├── 20170407172714_create_headers.rb │ ├── 20161214162402_create_json_schemas.rb │ ├── 20171229144723_change_validation_errors_description_to_text.rb │ ├── 20180117161236_create_metadata.rb │ ├── 20170602145951_create_resource_representations.rb │ ├── 20170720143737_add_missing_constraints_in_attribute.rb │ ├── 20170720101800_add_request_ressource_representation_to_route.rb │ ├── 20180208103459_create_metadata_responses.rb │ ├── 20171108092720_create_mock_instances.rb │ ├── 20180208151538_create_metadatum_instances.rb │ ├── 20171013130330_add_root_key_and_is_collection_to_route.rb │ ├── 20170313102138_create_routes.rb │ ├── 20170407175225_create_query_parameters.rb │ ├── 20171030155238_merge_attribute_min_max.rb │ ├── 20171115105126_add_patterns_to_mock_pickers.rb │ ├── 20190928112108_add_api_gateway_integration.rb │ ├── 20190926081509_change_parameters_to_jsonb_in_security_schemes.rb │ ├── 20190304112548_add_project_id_to_audits.rb │ ├── 20190715164030_add_internal_to_users.rb │ ├── 20170919124934_add_root_key_to_responses.rb │ ├── 20171030094823_remove_custom_fields_from_resource_representation.rb │ ├── 20180223163412_drop_attribute_fakers.rb │ ├── 20171115165949_rename_mock_instance_to_resource_instance.rb │ ├── 20171226152120_add_key_name_to_attributes_resource_representation.rb │ ├── 20170919080631_create_fakers.rb │ ├── 20170310132514_create_attributes.rb │ ├── 20190912182400_create_security_schemes.rb │ ├── 20170602161118_create_attributes_resource_representations.rb │ ├── 20200417091346_add_confirmable_to_devise.rb │ ├── 20170830101250_devise_create_users.rb │ ├── 20171229133209_remove_json_errors.rb │ ├── 20171116161642_create_api_errors_and_errors_instances.rb │ ├── 20170921083345_create_schemes.rb │ └── 20171004090741_create_report.rb └── seeds.rb ├── .github └── dependabot.yml ├── Rakefile ├── postcss.config.js └── app.json /log/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/mailers/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/models/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /lib/assets/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /lib/tasks/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/helpers/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/mailers/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.nvmrc: -------------------------------------------------------------------------------- 1 | v10.13.0 2 | -------------------------------------------------------------------------------- /.browserslistrc: -------------------------------------------------------------------------------- 1 | defaults 2 | -------------------------------------------------------------------------------- /app/models/concerns/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/controllers/concerns/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/helpers/application_helper.rb: -------------------------------------------------------------------------------- 1 | module ApplicationHelper 2 | end 3 | -------------------------------------------------------------------------------- /banner.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/faberNovel/pericles/HEAD/banner.jpg -------------------------------------------------------------------------------- /config/initializers/haml.rb: -------------------------------------------------------------------------------- 1 | Haml::Template.options[:remove_whitespace] = true -------------------------------------------------------------------------------- /app/views/audits/_missing_partial.html.haml: -------------------------------------------------------------------------------- 1 | %div= "#{audit.id} has no partial" 2 | -------------------------------------------------------------------------------- /app/views/audits/_missing_partial.mrkdwn.erb: -------------------------------------------------------------------------------- 1 | <%= audit.id %> has no partial 2 | -------------------------------------------------------------------------------- /proxy/config/config.exs: -------------------------------------------------------------------------------- 1 | use Mix.Config 2 | 3 | import_config "#{Mix.env}.exs" 4 | -------------------------------------------------------------------------------- /app/views/audits/route/_destroy.mrkdwn.erb: -------------------------------------------------------------------------------- 1 | Route *<%= audit.name %>* has been deleted -------------------------------------------------------------------------------- /app/views/audits/resource/_destroy.mrkdwn.erb: -------------------------------------------------------------------------------- 1 | Resource *<%= audit.name %>* has been deleted -------------------------------------------------------------------------------- /app/views/audits/metadatum/_destroy.mrkdwn.erb: -------------------------------------------------------------------------------- 1 | Metadatum *<%= audit.name %>* has been deleted 2 | -------------------------------------------------------------------------------- /proxy/elixir_buildpack.config: -------------------------------------------------------------------------------- 1 | # Elixir version 2 | erlang_version=21.0 3 | elixir_version=1.7.2 4 | -------------------------------------------------------------------------------- /app/assets/images/sad.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/faberNovel/pericles/HEAD/app/assets/images/sad.gif -------------------------------------------------------------------------------- /app/policies/api_error_instance_policy.rb: -------------------------------------------------------------------------------- 1 | class ApiErrorInstancePolicy < ProjectRelatedPolicy 2 | end 3 | -------------------------------------------------------------------------------- /app/policies/metadatum_instance_policy.rb: -------------------------------------------------------------------------------- 1 | class MetadatumInstancePolicy < ProjectRelatedPolicy 2 | end 3 | -------------------------------------------------------------------------------- /app/policies/resource_instance_policy.rb: -------------------------------------------------------------------------------- 1 | class ResourceInstancePolicy < ProjectRelatedPolicy 2 | end 3 | -------------------------------------------------------------------------------- /app/serializers/id_serializer.rb: -------------------------------------------------------------------------------- 1 | class IdSerializer < ActiveModel::Serializer 2 | attributes :id 3 | end 4 | -------------------------------------------------------------------------------- /app/views/audits/route/_destroy.html.erb: -------------------------------------------------------------------------------- 1 |
2 | Route <%= audit.name %> has been deleted 3 |
-------------------------------------------------------------------------------- /app/views/projects/edit.html.haml: -------------------------------------------------------------------------------- 1 | = content_for :title, "Edit Project #{project.title}" 2 | 3 | = render 'form' -------------------------------------------------------------------------------- /app/models/member.rb: -------------------------------------------------------------------------------- 1 | class Member < ApplicationRecord 2 | belongs_to :project 3 | belongs_to :user 4 | end 5 | -------------------------------------------------------------------------------- /app/views/audits/resource/_destroy.html.erb: -------------------------------------------------------------------------------- 1 |
2 | Resource <%= audit.name %> has been deleted 3 |
-------------------------------------------------------------------------------- /bin/rake: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require_relative '../config/boot' 3 | require 'rake' 4 | Rake.application.run 5 | -------------------------------------------------------------------------------- /proxy/test/test_helper.exs: -------------------------------------------------------------------------------- 1 | ExUnit.start() 2 | 3 | Ecto.Adapters.SQL.Sandbox.mode(PericlesProxy.Repo, :manual) 4 | -------------------------------------------------------------------------------- /app/models/api_gateway_integration.rb: -------------------------------------------------------------------------------- 1 | class ApiGatewayIntegration < ApplicationRecord 2 | belongs_to :project 3 | end 4 | -------------------------------------------------------------------------------- /app/serializers/header_serializer.rb: -------------------------------------------------------------------------------- 1 | class HeaderSerializer < ActiveModel::Serializer 2 | attributes :name 3 | end 4 | -------------------------------------------------------------------------------- /app/views/api_errors/new.html.haml: -------------------------------------------------------------------------------- 1 | = content_for :title, "New API Error" 2 | 3 | %h1 New Error 4 | 5 | = render 'new_form' -------------------------------------------------------------------------------- /app/views/audits/metadatum/_destroy.html.erb: -------------------------------------------------------------------------------- 1 |
2 | Metadatum <%= audit.name %> has been deleted 3 |
4 | -------------------------------------------------------------------------------- /app/views/audits/resources_representation/_destroy.mrkdwn.erb: -------------------------------------------------------------------------------- 1 | ResourceRepresentation *<%= audit.name %>* has been deleted -------------------------------------------------------------------------------- /app/views/metadata/new.html.haml: -------------------------------------------------------------------------------- 1 | = content_for :title, "New Metadatum" 2 | 3 | %h1 New Metadatum 4 | 5 | = render 'form' -------------------------------------------------------------------------------- /test/factories/members.rb: -------------------------------------------------------------------------------- 1 | FactoryBot.define do 2 | factory :member do 3 | project 4 | user 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /app/decorators/security_scheme_decorator.rb: -------------------------------------------------------------------------------- 1 | class SecuritySchemeDecorator < Draper::Decorator 2 | delegate_all 3 | end 4 | -------------------------------------------------------------------------------- /app/serializers/user_serializer.rb: -------------------------------------------------------------------------------- 1 | class UserSerializer < ActiveModel::Serializer 2 | attributes :id, :internal 3 | end 4 | -------------------------------------------------------------------------------- /app/views/resources/new.html.haml: -------------------------------------------------------------------------------- 1 | = content_for :title, "New Resource" 2 | 3 | %h3 New resource 4 | 5 | = render 'create_form' -------------------------------------------------------------------------------- /config/locales/metadata/en.yml: -------------------------------------------------------------------------------- 1 | en: 2 | metadata: 3 | index: 4 | no_metadata: "There are no metadata, create one !" -------------------------------------------------------------------------------- /config/webpack/test.js: -------------------------------------------------------------------------------- 1 | const environment = require('./environment') 2 | 3 | module.exports = environment.toWebpackConfig() 4 | -------------------------------------------------------------------------------- /docker-entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | bundle exec rake db:migrate 3 | bundle exec rails assets:precompile 4 | 5 | exec "$@" 6 | -------------------------------------------------------------------------------- /app/decorators/api_error_instance_decorator.rb: -------------------------------------------------------------------------------- 1 | class ApiErrorInstanceDecorator < Draper::Decorator 2 | delegate_all 3 | end 4 | -------------------------------------------------------------------------------- /app/decorators/metadatum_instance_decorator.rb: -------------------------------------------------------------------------------- 1 | class MetadatumInstanceDecorator < Draper::Decorator 2 | delegate_all 3 | end 4 | -------------------------------------------------------------------------------- /app/decorators/user_decorator.rb: -------------------------------------------------------------------------------- 1 | class UserDecorator < Draper::Decorator 2 | include Authorization 3 | delegate_all 4 | end 5 | -------------------------------------------------------------------------------- /app/views/resource_instances/edit.html.haml: -------------------------------------------------------------------------------- 1 | = content_for :title, "Edit Resource Mock #{model_instance.name}" 2 | 3 | = render 'form' -------------------------------------------------------------------------------- /config/locales/metadata/fr.yml: -------------------------------------------------------------------------------- 1 | fr: 2 | metadata: 3 | index: 4 | no_metadata: "Il n'y a pas de métadonnées, créez en une !" -------------------------------------------------------------------------------- /config/webpack/production.js: -------------------------------------------------------------------------------- 1 | const environment = require('./environment') 2 | 3 | module.exports = environment.toWebpackConfig() 4 | -------------------------------------------------------------------------------- /proxy/.formatter.exs: -------------------------------------------------------------------------------- 1 | # Used by "mix format" 2 | [ 3 | inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"] 4 | ] 5 | -------------------------------------------------------------------------------- /config/webpack/development.js: -------------------------------------------------------------------------------- 1 | const environment = require('./environment') 2 | 3 | module.exports = environment.toWebpackConfig() 4 | -------------------------------------------------------------------------------- /config/webpack/loaders/pug.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | test: /\.pug$/, 3 | use: [{ 4 | loader: 'pug-plain-loader' 5 | }] 6 | } 7 | -------------------------------------------------------------------------------- /test/factories/responses.rb: -------------------------------------------------------------------------------- 1 | FactoryBot.define do 2 | 3 | factory :response do 4 | status_code 200 5 | route 6 | end 7 | end -------------------------------------------------------------------------------- /Procfile: -------------------------------------------------------------------------------- 1 | web: bundle exec passenger start -p $PORT --max-pool-size 3 2 | worker: bundle exec rails jobs:work 3 | release: rake db:migrate 4 | -------------------------------------------------------------------------------- /app/views/api_error_instances/_api_error_instance.html.haml: -------------------------------------------------------------------------------- 1 | = render partial: 'instances/instance', locals: {instance: api_error_instance} 2 | -------------------------------------------------------------------------------- /app/views/api_error_instances/edit.html.haml: -------------------------------------------------------------------------------- 1 | = content_for :title, "Edit API Error Instance #{model_instance.name}" 2 | 3 | = render 'form' -------------------------------------------------------------------------------- /app/views/api_errors/edit.html.haml: -------------------------------------------------------------------------------- 1 | = content_for :title, "Edit API Error #{api_error.name}" 2 | 3 | %h1 Edit Error 4 | 5 | = render 'form' -------------------------------------------------------------------------------- /app/views/metadatum_instances/edit.html.haml: -------------------------------------------------------------------------------- 1 | = content_for :title, "Edit Metadatum instance #{model_instance.name}" 2 | 3 | = render 'form' -------------------------------------------------------------------------------- /app/views/resource_instances/_resource_instance.html.haml: -------------------------------------------------------------------------------- 1 | = render partial: 'instances/instance', locals: {instance: resource_instance} 2 | -------------------------------------------------------------------------------- /app/views/routes/new.html.haml: -------------------------------------------------------------------------------- 1 | = content_for :title, "New Route" 2 | 3 | .page-header 4 | %h1 5 | New route 6 | 7 | = render 'form' 8 | -------------------------------------------------------------------------------- /app/views/schemes/new.html.haml: -------------------------------------------------------------------------------- 1 | = content_for :title, "New Scheme" 2 | 3 | .page-header 4 | %h1 5 | Scheme 6 | 7 | = render 'form' 8 | -------------------------------------------------------------------------------- /config/webpack/loaders/vue.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | test: /\.vue(\.erb)?$/, 3 | use: [{ 4 | loader: 'vue-loader' 5 | }] 6 | } 7 | -------------------------------------------------------------------------------- /proxy/lib/pericles_proxy/repositories/repo.ex: -------------------------------------------------------------------------------- 1 | defmodule PericlesProxy.Repo do 2 | use Ecto.Repo, otp_app: :pericles_proxy 3 | end 4 | 5 | -------------------------------------------------------------------------------- /app/views/projects/new.html.haml: -------------------------------------------------------------------------------- 1 | = content_for :title, "New Project" 2 | 3 | %h1 New Project 4 | 5 | .row 6 | .col-xs-12 7 | = render 'form' -------------------------------------------------------------------------------- /config/webpack/loaders/vue-svg-loader.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | test: /\.svg$/, 3 | use: [{ 4 | loader: 'vue-svg-loader' 5 | }] 6 | } 7 | -------------------------------------------------------------------------------- /app/view_models/news/change.rb: -------------------------------------------------------------------------------- 1 | module News 2 | class Change < ActiveModelSerializers::Model 3 | attributes :key, :old, :new 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /app/views/audits/resources_representation/_destroy.html.erb: -------------------------------------------------------------------------------- 1 |
2 | ResourceRepresentation 3 | <%= audit.name %> has been deleted 4 |
-------------------------------------------------------------------------------- /app/views/mock_profiles/edit.html.haml: -------------------------------------------------------------------------------- 1 | = content_for :title, "Edit Mock Profile #{mock_profile.name}" 2 | 3 | %h1 Mock Profile 4 | 5 | = render 'form' -------------------------------------------------------------------------------- /bin/bundle: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) 3 | load Gem.bin_path('bundler', 'bundle') 4 | -------------------------------------------------------------------------------- /config/locales/audits/en.yml: -------------------------------------------------------------------------------- 1 | en: 2 | audits: 3 | slack_post: 4 | news_posted_on: "%{news_posted_count} news posted on %{slack_channel}" 5 | -------------------------------------------------------------------------------- /config/locales/audits/fr.yml: -------------------------------------------------------------------------------- 1 | fr: 2 | audits: 3 | slack_post: 4 | news_posted_on: "%{news_posted_count} news postées sur %{slack_channel}" 5 | -------------------------------------------------------------------------------- /config/spring.rb: -------------------------------------------------------------------------------- 1 | %w( 2 | .ruby-version 3 | .rbenv-vars 4 | tmp/restart.txt 5 | tmp/caching-dev.txt 6 | ).each { |path| Spring.watch(path) } 7 | -------------------------------------------------------------------------------- /test/factories/validations.rb: -------------------------------------------------------------------------------- 1 | FactoryBot.define do 2 | 3 | factory :validation do 4 | json_schema "{}" 5 | json_instance '""' 6 | end 7 | end -------------------------------------------------------------------------------- /app/assets/stylesheets/styles/mock_instances.scss: -------------------------------------------------------------------------------- 1 | #mock_instance_body { 2 | height: 400px; 3 | } 4 | 5 | .mock_instance_text_area { 6 | width: 100%; 7 | } -------------------------------------------------------------------------------- /config/boot.rb: -------------------------------------------------------------------------------- 1 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__) 2 | 3 | require 'bundler/setup' # Set up gems listed in the Gemfile. 4 | -------------------------------------------------------------------------------- /test/factories/metadata_responses.rb: -------------------------------------------------------------------------------- 1 | FactoryBot.define do 2 | 3 | factory :metadata_response do 4 | metadatum 5 | response 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /app/policies/api_error_policy.rb: -------------------------------------------------------------------------------- 1 | class ApiErrorPolicy < ProjectRelatedPolicy 2 | def permitted_attributes 3 | [:name, :json_schema] 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /app/views/resource_instances/new.html.haml: -------------------------------------------------------------------------------- 1 | = content_for :title, "New Resource Mock" 2 | 3 | %h1 New Mock 4 | 5 | .row 6 | .col-xs-12 7 | = render 'form' -------------------------------------------------------------------------------- /config/initializers/bootstrap_form.rb: -------------------------------------------------------------------------------- 1 | require 'bootstrap_form/regex' 2 | 3 | BootstrapForm::FormBuilder.send(:include, BootstrapForm::RegexFormBuilder) 4 | 5 | -------------------------------------------------------------------------------- /config/locales/responses/en.yml: -------------------------------------------------------------------------------- 1 | en: 2 | responses: 3 | header_fields: 4 | name_placeholder: Content-Type 5 | value_placeholder: application/json -------------------------------------------------------------------------------- /config/locales/responses/fr.yml: -------------------------------------------------------------------------------- 1 | fr: 2 | responses: 3 | header_fields: 4 | name_placeholder: Content-Type 5 | value_placeholder: application/json -------------------------------------------------------------------------------- /config/locales/security_schemes/en.yml: -------------------------------------------------------------------------------- 1 | en: 2 | security_schemes: 3 | index: 4 | no_security_scheme: "There are no security schemes, create one !" 5 | -------------------------------------------------------------------------------- /config/locales/users/en.yml: -------------------------------------------------------------------------------- 1 | en: 2 | users: 3 | sign_in: 4 | check_domain: Unauthorized domain. Please check the domain of the selected email address. -------------------------------------------------------------------------------- /app/views/api_error_instances/new.html.haml: -------------------------------------------------------------------------------- 1 | = content_for :title, "New API Error Instance" 2 | 3 | %h1 New Mock 4 | 5 | .row 6 | .col-xs-12 7 | = render 'form' -------------------------------------------------------------------------------- /app/views/schemes/edit.html.haml: -------------------------------------------------------------------------------- 1 | = content_for :title, "Edit Scheme #{scheme.name}" 2 | 3 | .page-header 4 | %h1 5 | Edit Scheme 6 | 7 | = render 'form' 8 | -------------------------------------------------------------------------------- /bin/rails: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | APP_PATH = File.expand_path('../config/application', __dir__) 3 | require_relative '../config/boot' 4 | require 'rails/commands' 5 | -------------------------------------------------------------------------------- /config/locales/security_schemes/fr.yml: -------------------------------------------------------------------------------- 1 | fr: 2 | security_scheme: 3 | index: 4 | no_security_scheme: "Il n'y a aucune security schemes, créez-en une !" 5 | -------------------------------------------------------------------------------- /config/locales/users/fr.yml: -------------------------------------------------------------------------------- 1 | fr: 2 | users: 3 | sign_in: 4 | check_domain: Domaine non autorisé. Veuillez vérifier le domaine de l'adresse email sélectionnée. -------------------------------------------------------------------------------- /app/views/audits/_changes.mrkdwn.erb: -------------------------------------------------------------------------------- 1 | <% audited_changes.each do |change| %> 2 | • <%= change.key %> went from ~<%= change.old %>~ to *<%= change.new %>* 3 | <% end %> 4 | -------------------------------------------------------------------------------- /app/views/audits/route/_create.mrkdwn.erb: -------------------------------------------------------------------------------- 1 | A new Route <% if audit.url %><<%= audit.url%>|<%= audit.link_name%>><% else %> which no longer exists<% end %> has been created -------------------------------------------------------------------------------- /app/views/metadatum_instances/new.html.haml: -------------------------------------------------------------------------------- 1 | = content_for :title, "New Metadatum Instance" 2 | 3 | %h1 New Metadatum 4 | 5 | .row 6 | .col-xs-12 7 | = render 'form' -------------------------------------------------------------------------------- /app/views/security_schemes/new.html.haml: -------------------------------------------------------------------------------- 1 | = content_for :title, "New Security Scheme" 2 | 3 | .page-header 4 | %h1 5 | New Security Scheme 6 | 7 | = render 'form' 8 | -------------------------------------------------------------------------------- /config/environment.rb: -------------------------------------------------------------------------------- 1 | # Load the Rails application. 2 | require_relative 'application' 3 | 4 | # Initialize the Rails application. 5 | Rails.application.initialize! 6 | -------------------------------------------------------------------------------- /app/controllers/api_error_instances_controller.rb: -------------------------------------------------------------------------------- 1 | class ApiErrorInstancesController < AbstractInstancesController 2 | def model_name 3 | 'api_error' 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /app/controllers/metadatum_instances_controller.rb: -------------------------------------------------------------------------------- 1 | class MetadatumInstancesController < AbstractInstancesController 2 | def model_name 3 | 'metadatum' 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /app/serializers/validation_serializer.rb: -------------------------------------------------------------------------------- 1 | class ValidationSerializer < ActiveModel::Serializer 2 | attributes :json_schema, :json_instance, :status, :json_errors 3 | end 4 | -------------------------------------------------------------------------------- /app/views/audits/resource/_create.mrkdwn.erb: -------------------------------------------------------------------------------- 1 | A new Resource <% if audit.url %><<%= audit.url%>|<%= audit.link_name%>><% else %> which no longer exists<% end %> has been created -------------------------------------------------------------------------------- /app/views/security_schemes/edit.html.haml: -------------------------------------------------------------------------------- 1 | = content_for :title, "edit Security Scheme" 2 | 3 | .page-header 4 | %h1 5 | Edit Security Scheme 6 | 7 | = render 'form' 8 | -------------------------------------------------------------------------------- /config.ru: -------------------------------------------------------------------------------- 1 | # This file is used by Rack-based servers to start the application. 2 | 3 | require ::File.expand_path('../config/environment', __FILE__) 4 | run Rails.application 5 | -------------------------------------------------------------------------------- /config/cable.yml: -------------------------------------------------------------------------------- 1 | development: 2 | adapter: async 3 | 4 | test: 5 | adapter: async 6 | 7 | production: 8 | adapter: redis 9 | url: redis://localhost:6379/1 10 | -------------------------------------------------------------------------------- /db/migrate/20170405185230_destroy_json_schemas.rb: -------------------------------------------------------------------------------- 1 | class DestroyJsonSchemas < ActiveRecord::Migration[5.0] 2 | def change 3 | drop_table :json_schemas 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /test/factories/api_error_instances.rb: -------------------------------------------------------------------------------- 1 | FactoryBot.define do 2 | factory :api_error_instance do 3 | name 'Nice name' 4 | body '{}' 5 | api_error 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /test/factories/metadatum_instances.rb: -------------------------------------------------------------------------------- 1 | FactoryBot.define do 2 | factory :metadatum_instance do 3 | name 'Nice name' 4 | body '1' 5 | metadatum 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /app/views/audits/metadatum/_create.mrkdwn.erb: -------------------------------------------------------------------------------- 1 | A new Metadatum <% if audit.url %><<%= audit.url%>|<%= audit.link_name%>><% else %> which no longer exists<% end %> has been created 2 | -------------------------------------------------------------------------------- /app/views/shared/_alert.html.haml: -------------------------------------------------------------------------------- 1 | .row 2 | .col-xs-12 3 | - if notice 4 | %p.alert.alert-success= notice 5 | - if alert 6 | %p.alert.alert-warning= alert 7 | -------------------------------------------------------------------------------- /app/helpers/android_code_gen_helper.rb: -------------------------------------------------------------------------------- 1 | module AndroidCodeGenHelper 2 | def android_company_domain_name 3 | ENV['ANDROID_COMPANY_DOMAIN_NAME'] || 'com.example' 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /app/serializers/resource_representation_serializer.rb: -------------------------------------------------------------------------------- 1 | class ResourceRepresentationSerializer < ActiveModel::Serializer 2 | attributes :id, :name, :description, :resource_id 3 | end 4 | -------------------------------------------------------------------------------- /db/migrate/20171208095001_add_value_to_headers.rb: -------------------------------------------------------------------------------- 1 | class AddValueToHeaders < ActiveRecord::Migration[5.0] 2 | def change 3 | add_column :headers, :value, :string 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: "bundler" 4 | directory: "/" 5 | schedule: 6 | interval: "daily" 7 | target-branch: "develop" 8 | -------------------------------------------------------------------------------- /app/policies/user_context.rb: -------------------------------------------------------------------------------- 1 | class UserContext 2 | attr_reader :user, :project 3 | 4 | def initialize(user, project) 5 | @user = user 6 | @project = project 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /app/serializers/route_serializer.rb: -------------------------------------------------------------------------------- 1 | class RouteSerializer < ActiveModel::Serializer 2 | attributes( 3 | :id, 4 | :url, 5 | :http_method, 6 | :resource_id 7 | ) 8 | end 9 | -------------------------------------------------------------------------------- /config/initializers/session_store.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | Rails.application.config.session_store :cookie_store, key: '_Pericles_GW_gw_session' 4 | -------------------------------------------------------------------------------- /db/migrate/20170524122014_add_enum_to_attributes.rb: -------------------------------------------------------------------------------- 1 | class AddEnumToAttributes < ActiveRecord::Migration[5.0] 2 | def change 3 | add_column :attributes, :enum, :string 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20170901134536_add_avatar_url_to_users.rb: -------------------------------------------------------------------------------- 1 | class AddAvatarUrlToUsers < ActiveRecord::Migration[5.0] 2 | def change 3 | add_column :users, :avatar_url, :string 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20171213105131_remove_name_from_routes.rb: -------------------------------------------------------------------------------- 1 | class RemoveNameFromRoutes < ActiveRecord::Migration[5.0] 2 | def change 3 | remove_column :routes, :name, :string 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /proxy/lib/pericles_proxy/models/project.ex: -------------------------------------------------------------------------------- 1 | defmodule PericlesProxy.Project do 2 | use Ecto.Schema 3 | 4 | schema "projects" do 5 | timestamps(inserted_at: :created_at) 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /app/assets/stylesheets/variables.scss: -------------------------------------------------------------------------------- 1 | $brand-primary: #008afd; 2 | 3 | $input-border-focus: $brand-primary; 4 | $btn-default-color: white; 5 | $btn-default-bg: $brand-primary; 6 | 7 | $grey: #999999; -------------------------------------------------------------------------------- /app/policies/resource_policy.rb: -------------------------------------------------------------------------------- 1 | class ResourcePolicy < ProjectRelatedPolicy 2 | def edit_attributes? 3 | edit? 4 | end 5 | 6 | def edit_resource? 7 | edit? 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /db/migrate/20170530095333_add_pattern_to_attributes.rb: -------------------------------------------------------------------------------- 1 | class AddPatternToAttributes < ActiveRecord::Migration[5.0] 2 | def change 3 | add_column :attributes, :pattern, :string 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20170721161004_add_server_url_to_project.rb: -------------------------------------------------------------------------------- 1 | class AddServerUrlToProject < ActiveRecord::Migration[5.0] 2 | def change 3 | add_column :projects, :server_url, :string 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /test/factories/mock_pickers.rb: -------------------------------------------------------------------------------- 1 | FactoryBot.define do 2 | 3 | factory :mock_picker do 4 | mock_profile 5 | response 6 | url_pattern "" 7 | body_pattern "" 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /test/factories/proxy_configurations.rb: -------------------------------------------------------------------------------- 1 | FactoryBot.define do 2 | 3 | factory :proxy_configuration do 4 | project 5 | target_base_url 'https://api-develop.herokuapp.com' 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /app/controllers/instances_controller.rb: -------------------------------------------------------------------------------- 1 | class InstancesController < ApplicationController 2 | def create 3 | render json: GenerateJsonInstanceService.new(params[:schema]).execute 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /app/views/audits/resources_representation/_create.mrkdwn.erb: -------------------------------------------------------------------------------- 1 | A new ResourceRepresentation <% if audit.url %><<%= audit.url%>|<%= audit.link_name%>><% else %> which no longer exists<% end %> has been created -------------------------------------------------------------------------------- /app/decorators/attributes_resource_representation_decorator.rb: -------------------------------------------------------------------------------- 1 | class AttributesResourceRepresentationDecorator < Draper::Decorator 2 | decorates_association :resource_attribute 3 | delegate_all 4 | end 5 | -------------------------------------------------------------------------------- /app/views/audits/response/_create.mrkdwn.erb: -------------------------------------------------------------------------------- 1 | A new <%= audit.type %> <%= audit.name %> has been created: <% if audit.url %><<%= audit.url %>|<%= audit.link_name %>><% else %>Audit which no longer exists<% end %> -------------------------------------------------------------------------------- /app/views/audits/response/_destroy.mrkdwn.erb: -------------------------------------------------------------------------------- 1 | <%= audit.type %> <%= audit.name %> has been created: <% if audit.url %><<%= audit.url %>|<%= audit.link_name %>><% else %>Audit which no longer exists<% end %> 2 | -------------------------------------------------------------------------------- /bin/delayed_job: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | require File.expand_path(File.join(File.dirname(__FILE__), '..', 'config', 'environment')) 4 | require 'delayed/command' 5 | Delayed::Command.new(ARGV).daemonize 6 | -------------------------------------------------------------------------------- /db/migrate/20170407182241_remove_body_schema_from_routes.rb: -------------------------------------------------------------------------------- 1 | class RemoveBodySchemaFromRoutes < ActiveRecord::Migration[5.0] 2 | def change 3 | remove_column :routes, :body_schema, :json 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20170410163242_add_route_id_to_responses.rb: -------------------------------------------------------------------------------- 1 | class AddRouteIdToResponses < ActiveRecord::Migration[5.0] 2 | def change 3 | add_reference :responses, :route, foreign_key: true 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20170927092704_rename_faker_to_attribute_faker.rb: -------------------------------------------------------------------------------- 1 | class RenameFakerToAttributeFaker < ActiveRecord::Migration[5.0] 2 | def change 3 | rename_table :fakers, :attribute_fakers 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /app/views/audits/_changes.html.haml: -------------------------------------------------------------------------------- 1 | %ul 2 | - audited_changes.each do |change| 3 | %li 4 | = "#{change.key} went from" 5 | %span.stroke= change.old 6 | to 7 | %span.bold= change.new 8 | -------------------------------------------------------------------------------- /app/views/audits/metadata_response/_create.mrkdwn.erb: -------------------------------------------------------------------------------- 1 | Metadatum *<%= audit.name %>* has been added to <% if audit.url %><<%= audit.url %>|<%= audit.link_name %>><% else %>a response which no longer exists<% end %> 2 | -------------------------------------------------------------------------------- /app/views/routes/edit.html.haml: -------------------------------------------------------------------------------- 1 | = content_for :title, "Edit Route #{route.url}" 2 | 3 | .page-header 4 | %h1 5 | !="#{route.resource.name} Edit Route: #{route.url} " 6 | 7 | = render 'form' 8 | -------------------------------------------------------------------------------- /config/initializers/neat_json.rb: -------------------------------------------------------------------------------- 1 | module JSON 2 | def self.stable_pretty_generate(json) 3 | JSON.neat_generate(json, 4 | sort: true, 5 | wrap: true, 6 | after_colon: 1 7 | ) 8 | end 9 | end -------------------------------------------------------------------------------- /db/migrate/20170407163730_add_request_body_schema_to_routes.rb: -------------------------------------------------------------------------------- 1 | class AddRequestBodySchemaToRoutes < ActiveRecord::Migration[5.0] 2 | def change 3 | add_column :routes, :request_body_schema, :json 4 | end 5 | end -------------------------------------------------------------------------------- /db/migrate/20171030102800_rename_server_url_to_proxy_url.rb: -------------------------------------------------------------------------------- 1 | class RenameServerUrlToProxyUrl < ActiveRecord::Migration[5.0] 2 | def change 3 | rename_column :projects, :server_url, :proxy_url 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20171207110941_remove_description_from_headers.rb: -------------------------------------------------------------------------------- 1 | class RemoveDescriptionFromHeaders < ActiveRecord::Migration[5.0] 2 | def change 3 | remove_column :headers, :description, :text 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20180810134422_add_validated_to_reports.rb: -------------------------------------------------------------------------------- 1 | class AddValidatedToReports < ActiveRecord::Migration[5.1] 2 | def change 3 | add_column :reports, :validated, :boolean, default: true 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /app/views/audits/metadata_response/_destroy.mrkdwn.erb: -------------------------------------------------------------------------------- 1 | Metadatum *<%= audit.name %>* has been removed from <% if audit.url %><<%= audit.url %>|<%= audit.link_name %>><% else %>a response which no longer exists<% end %> 2 | -------------------------------------------------------------------------------- /db/migrate/20171206161957_remove_description_from_responses.rb: -------------------------------------------------------------------------------- 1 | class RemoveDescriptionFromResponses < ActiveRecord::Migration[5.0] 2 | def change 3 | remove_column :responses, :description, :text 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /app/decorators/response_decorator.rb: -------------------------------------------------------------------------------- 1 | class ResponseDecorator < Draper::Decorator 2 | delegate_all 3 | 4 | def schema_summary 5 | h.schema_summary(root_key, resource_representation, is_collection) 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /app/models/application_record.rb: -------------------------------------------------------------------------------- 1 | class ApplicationRecord < ActiveRecord::Base 2 | self.abstract_class = true 3 | 4 | def last_audit 5 | (audits.to_a + associated_audits.to_a).max_by(&:created_at) 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /app/policies/metadatum_policy.rb: -------------------------------------------------------------------------------- 1 | class MetadatumPolicy < ProjectRelatedPolicy 2 | def permitted_attributes 3 | [ 4 | :name, 5 | :primitive_type, 6 | :nullable 7 | ] 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /app/views/audits/attribute/_destroy.mrkdwn.erb: -------------------------------------------------------------------------------- 1 | Attribute *<%= audit.name %>* has been deleted from <% if audit.url %><<%= audit.url %>|<%= audit.link_name %>><% else %>an associated resource which no longer exists<% end %> 2 | -------------------------------------------------------------------------------- /app/views/audits/attributes_resource_representation/_create.mrkdwn.erb: -------------------------------------------------------------------------------- 1 | <% if audit.url %><<%= audit.url %>|<%= audit.link_name %>><% else %>A representation which no longer exists<% end %> is now using *<%= audit.name %>* 2 | -------------------------------------------------------------------------------- /app/views/shared/_last_edit.html.haml: -------------------------------------------------------------------------------- 1 | - if last_audit&.user&.name && last_audit&.created_at 2 | .last-edit 3 | Last edit by 4 | %span=last_audit.user.name 5 | ="(#{time_ago_in_words(last_audit.created_at)} ago)" -------------------------------------------------------------------------------- /app/views/shared/_schema_errors.html.haml: -------------------------------------------------------------------------------- 1 | - body_errors.group_by(&:readable_path).each do |path, errors| 2 | %h6= path 3 | %ul 4 | - errors.sort_by { |e| [e.type, e.path] }.each do |e| 5 | %li.error= e.description -------------------------------------------------------------------------------- /config/initializers/active_model_serializer.rb: -------------------------------------------------------------------------------- 1 | # When upgrading to ams ~> 0.9 this is required to have root and meta keys in the json responses - see ams documentation on meta 2 | ActiveModel::Serializer.config.adapter = :json -------------------------------------------------------------------------------- /config/locales/reports/en.yml: -------------------------------------------------------------------------------- 1 | en: 2 | reports: 3 | index: 4 | in_validation: 'Validation pending' 5 | unknown: 'UNKNOWN' 6 | no_reports: 'There are no reports, please use the proxy to generate some' 7 | -------------------------------------------------------------------------------- /config/locales/reports/fr.yml: -------------------------------------------------------------------------------- 1 | fr: 2 | reports: 3 | index: 4 | in_validation: 'Validation en cours' 5 | unknown: 'INCONNUES' 6 | no_reports: Il n'y a pas de rapports, utilisez le proxy pour en générer 7 | -------------------------------------------------------------------------------- /db/migrate/20171009090238_add_request_description_to_routes.rb: -------------------------------------------------------------------------------- 1 | class AddRequestDescriptionToRoutes < ActiveRecord::Migration[5.0] 2 | def change 3 | add_column :routes, :request_description, :text 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20190626123920_add_slack_updated_at_to_projects.rb: -------------------------------------------------------------------------------- 1 | class AddSlackUpdatedAtToProjects < ActiveRecord::Migration[5.1] 2 | def change 3 | add_column :projects, :slack_updated_at, :datetime 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /test/factories/validation_error.rb: -------------------------------------------------------------------------------- 1 | FactoryBot.define do 2 | 3 | factory :validation_error do 4 | category :header 5 | description 'Content-Type is missing from the response headers' 6 | report 7 | end 8 | end -------------------------------------------------------------------------------- /app/views/audits/attribute/_create.mrkdwn.erb: -------------------------------------------------------------------------------- 1 | <% if audit.url %><<%= audit.url %>|<%= audit.link_name %>><% else %>Associated resource which no longer exists<% end %> has a new attribute *<%= audit.name %>* (<%= audit.type %>) 2 | -------------------------------------------------------------------------------- /db/migrate/20170410163241_remove_response_schema_from_routes.rb: -------------------------------------------------------------------------------- 1 | class RemoveResponseSchemaFromRoutes < ActiveRecord::Migration[5.0] 2 | def change 3 | remove_column :routes, :response_schema, :json 4 | end 5 | end 6 | 7 | -------------------------------------------------------------------------------- /db/migrate/20170901114536_add_name_to_users.rb: -------------------------------------------------------------------------------- 1 | class AddNameToUsers < ActiveRecord::Migration[5.0] 2 | def change 3 | add_column :users, :first_name, :string 4 | add_column :users, :last_name, :string 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20171114144052_remove_example_from_resource_attributes.rb: -------------------------------------------------------------------------------- 1 | class RemoveExampleFromResourceAttributes < ActiveRecord::Migration[5.0] 2 | def change 3 | remove_column :attributes, :example, :string 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20180109151423_add_is_public_to_projects.rb: -------------------------------------------------------------------------------- 1 | class AddIsPublicToProjects < ActiveRecord::Migration[5.0] 2 | def change 3 | add_column :projects, :is_public, :boolean, default: false, null: false 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20190226135641_add_nullable_to_metadata.rb: -------------------------------------------------------------------------------- 1 | class AddNullableToMetadata < ActiveRecord::Migration[5.1] 2 | def change 3 | add_column :metadata, :nullable, :boolean, null: false, default: true 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /test/factories/api_gateway_integrations.rb: -------------------------------------------------------------------------------- 1 | FactoryBot.define do 2 | factory :api_gateway_integration do 3 | title 'api title' 4 | uri_prefix 'prefix' 5 | timeout_in_millis 29000 6 | project 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /app/views/api_errors/_form.html.haml: -------------------------------------------------------------------------------- 1 | = bootstrap_form_for([project, api_error]) do |f| 2 | .flexcontainer-justify-end= f.submit class: 'btn btn-primary' 3 | 4 | = f.text_field :name 5 | 6 | = f.text_area :json_schema, class: 'json' -------------------------------------------------------------------------------- /app/views/audits/attributes_resource_representation/_destroy.mrkdwn.erb: -------------------------------------------------------------------------------- 1 | *<%= audit.name %>* has been removed from <% if audit.url %><<%= audit.url %>|<%= audit.link_name %>><% else %>a representation which no longer exists<% end %> 2 | -------------------------------------------------------------------------------- /app/views/audits/route/_create.html.erb: -------------------------------------------------------------------------------- 1 |
2 | A new Route 3 | <% if audit.url %> 4 | <%= link_to audit.link_name, audit.url %> 5 | <% else %> 6 | which no longer exists 7 | <% end %> 8 | has been created 9 |
-------------------------------------------------------------------------------- /db/migrate/20170720153921_add_nullable_to_attribute.rb: -------------------------------------------------------------------------------- 1 | class AddNullableToAttribute < ActiveRecord::Migration[5.0] 2 | def change 3 | add_column :attributes, :nullable, :boolean, null: false, default: false 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20170830082826_add_is_collection_to_routes.rb: -------------------------------------------------------------------------------- 1 | class AddIsCollectionToRoutes < ActiveRecord::Migration[5.0] 2 | def change 3 | add_column :routes, :is_collection, :boolean, default: false, null: false 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20171114100627_add_active_mock_profile_to_projects.rb: -------------------------------------------------------------------------------- 1 | class AddActiveMockProfileToProjects < ActiveRecord::Migration[5.0] 2 | def change 3 | add_reference :projects, :mock_profile, foreign_key: true 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20171206155832_remove_request_description_from_routes.rb: -------------------------------------------------------------------------------- 1 | class RemoveRequestDescriptionFromRoutes < ActiveRecord::Migration[5.0] 2 | def change 3 | remove_column :routes, :request_description, :text 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20180727095817_add_instances_number_to_mock_pickers.rb: -------------------------------------------------------------------------------- 1 | class AddInstancesNumberToMockPickers < ActiveRecord::Migration[5.1] 2 | def change 3 | add_column :mock_pickers, :instances_number, :integer 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20190529154416_add_priority_to_mock_pickers.rb: -------------------------------------------------------------------------------- 1 | class AddPriorityToMockPickers < ActiveRecord::Migration[5.1] 2 | def change 3 | add_column :mock_pickers, :priority, :integer, default: 0, null: false 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /app/views/audits/resource/_create.html.erb: -------------------------------------------------------------------------------- 1 |
2 | A new Resource 3 | <% if audit.url %> 4 | <%= link_to audit.link_name, audit.url %> 5 | <% else %> 6 | which no longer exists 7 | <% end %> 8 | has been created 9 |
-------------------------------------------------------------------------------- /app/views/audits/route/_update.mrkdwn.erb: -------------------------------------------------------------------------------- 1 | <% if audit.url %><<%= audit.url %>|<%= audit.link_name %>><% else %>A Route which no longer exists<% end %> has been updated: 2 | <%= render 'audits/changes', audited_changes: audit.map_changes %> 3 | -------------------------------------------------------------------------------- /config/initializers/application_controller_renderer.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # ApplicationController.renderer.defaults.merge!( 4 | # http_host: 'example.org', 5 | # https: false 6 | # ) 7 | -------------------------------------------------------------------------------- /db/migrate/20190121145846_add_key_to_metadata_responses.rb: -------------------------------------------------------------------------------- 1 | class AddKeyToMetadataResponses < ActiveRecord::Migration[5.1] 2 | def change 3 | add_column :metadata_responses, :key, :string, null: false, default: '' 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | # See http://www.robotstxt.org/robotstxt.html for documentation on how to use the robots.txt file 2 | # 3 | # To ban all spiders from the entire site uncomment the next two lines: 4 | # User-agent: * 5 | # Disallow: / 6 | -------------------------------------------------------------------------------- /test/factories/schemes.rb: -------------------------------------------------------------------------------- 1 | FactoryBot.define do 2 | 3 | sequence :name do |n| 4 | "Scheme #{n}" 5 | end 6 | 7 | factory :scheme do 8 | name { generate(:name) } 9 | regexp '(azertyuiop)+' 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /app/decorators/proxy/route_decorator.rb: -------------------------------------------------------------------------------- 1 | module Proxy 2 | class RouteDecorator < Draper::Decorator 3 | decorates Route 4 | 5 | delegate_all 6 | decorates_association :responses, with: Proxy::ResponseDecorator 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /app/models/api_error_instance.rb: -------------------------------------------------------------------------------- 1 | class ApiErrorInstance < ApplicationRecord 2 | include Instance 3 | 4 | belongs_to :api_error 5 | delegate :project, to: :api_error 6 | 7 | def parent 8 | api_error 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /app/models/metadatum_instance.rb: -------------------------------------------------------------------------------- 1 | class MetadatumInstance < ApplicationRecord 2 | include Instance 3 | 4 | belongs_to :metadatum 5 | delegate :project, to: :metadatum 6 | 7 | def parent 8 | metadatum 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /app/models/resource_instance.rb: -------------------------------------------------------------------------------- 1 | class ResourceInstance < ApplicationRecord 2 | include Instance 3 | 4 | belongs_to :resource 5 | 6 | delegate :project, to: :resource 7 | 8 | def parent 9 | resource 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /db/migrate/20170529094105_add_is_required_to_attributes.rb: -------------------------------------------------------------------------------- 1 | class AddIsRequiredToAttributes < ActiveRecord::Migration[5.0] 2 | def change 3 | add_column :attributes, :is_required, :boolean, null: false, default: false 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20170922083249_rename_body_schema_to_body_schema_backup.rb: -------------------------------------------------------------------------------- 1 | class RenameBodySchemaToBodySchemaBackup < ActiveRecord::Migration[5.0] 2 | def change 3 | rename_column :responses, :body_schema, :body_schema_backup 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20191128145342_add_required_to_metadata_responses.rb: -------------------------------------------------------------------------------- 1 | class AddRequiredToMetadataResponses < ActiveRecord::Migration[5.1] 2 | def change 3 | add_column :metadata_responses, :required, :boolean, default: false 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /app/views/audits/resource/_update.mrkdwn.erb: -------------------------------------------------------------------------------- 1 | <% if audit.url %><<%= audit.url %>|<%= audit.link_name %>><% else %>A Resource which no longer exists<% end %> has been updated: 2 | <%= render 'audits/changes', audited_changes: audit.map_changes %> 3 | -------------------------------------------------------------------------------- /app/views/layouts/no_navbar_layout.html.haml: -------------------------------------------------------------------------------- 1 | !!! 2 | %html 3 | %head 4 | = render partial: 'shared/head' 5 | %body 6 | .container#main-container 7 | = render 'shared/alert' 8 | = yield 9 | = yield :page_scripts 10 | -------------------------------------------------------------------------------- /app/views/routes/_request_header_fields.html.haml: -------------------------------------------------------------------------------- 1 | %tr.fields.nested-fields 2 | %td 3 | = f.text_field :name, hide_label: true 4 | %td 5 | = f.text_field :value, hide_label: true 6 | %td 7 | = link_to_remove_association "Remove", f 8 | -------------------------------------------------------------------------------- /app/views/schemes/_form.html.haml: -------------------------------------------------------------------------------- 1 | = bootstrap_form_for scheme do |f| 2 | .flexcontainer-justify-end= f.submit class: 'btn btn-primary' 3 | = render 'shared/errors', object: scheme 4 | 5 | = f.text_field :name 6 | 7 | = f.regex_field :regexp -------------------------------------------------------------------------------- /db/migrate/20180529073528_add_unique_constraint_to_attribute_name.rb: -------------------------------------------------------------------------------- 1 | class AddUniqueConstraintToAttributeName < ActiveRecord::Migration[5.1] 2 | def change 3 | add_index :attributes, [:parent_resource_id, :name], unique: true 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /test/authentication/controller_with_authentication_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class ControllerWithAuthenticationTest < ActionDispatch::IntegrationTest 4 | setup do 5 | @user = create(:user) 6 | sign_in @user 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /app/decorators/json_schema/metadata_response_decorator.rb: -------------------------------------------------------------------------------- 1 | module JSONSchema 2 | class MetadataResponseDecorator < Draper::Decorator 3 | delegate_all 4 | decorates_association :metadatum, with: JSONSchema::MetadatumDecorator 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /app/models/concerns/has_primitive_type.rb: -------------------------------------------------------------------------------- 1 | module HasPrimitiveType 2 | extend ActiveSupport::Concern 3 | 4 | included do 5 | enum primitive_type: [:integer, :string, :boolean, :null, :number, :date, :datetime, :object, :any] 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /app/views/audits/attributes_resource_representation/_create.html.erb: -------------------------------------------------------------------------------- 1 | <% if audit.url %> 2 | <%= link_to audit.link_name, audit.url %> 3 | <% else %> 4 | A representation which no longer exists 5 | <% end %> 6 | is now using <%= audit.name %> 7 | -------------------------------------------------------------------------------- /app/views/audits/metadatum/_create.html.erb: -------------------------------------------------------------------------------- 1 |
2 | A new Metadatum 3 | <% if audit.url %> 4 | <%= link_to audit.link_name, audit.url %> 5 | <% else %> 6 | which no longer exists 7 | <% end %> 8 | has been created 9 |
10 | -------------------------------------------------------------------------------- /config/initializers/filter_parameter_logging.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Configure sensitive parameters which will be filtered from the log file. 4 | Rails.application.config.filter_parameters += [:password] 5 | -------------------------------------------------------------------------------- /db/migrate/20171212072623_add_ancestry_to_mock_profiles.rb: -------------------------------------------------------------------------------- 1 | class AddAncestryToMockProfiles < ActiveRecord::Migration[5.0] 2 | def change 3 | add_column :mock_profiles, :ancestry, :string 4 | add_index :mock_profiles, :ancestry 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /app/validators/hash_validator.rb: -------------------------------------------------------------------------------- 1 | class HashValidator < ActiveModel::EachValidator 2 | def validate_each(record, attribute, value) 3 | return unless value 4 | record.errors.add(attribute, :value_must_be_hash) unless value.is_a? Hash 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /app/views/audits/metadatum/_update.mrkdwn.erb: -------------------------------------------------------------------------------- 1 | <% if audit.url %>Metadatum <<%= audit.url %>|<%= audit.link_name %>><% else %>A Metadatum which no longer exists<% end %> has been updated: 2 | <%= render 'audits/changes', audited_changes: audit.map_changes %> 3 | -------------------------------------------------------------------------------- /proxy/config/dev.exs: -------------------------------------------------------------------------------- 1 | use Mix.Config 2 | 3 | config :pericles_proxy, PericlesProxy.Repo, 4 | adapter: Ecto.Adapters.Postgres, 5 | database: "Pericles_GW_dev", 6 | hostname: "localhost" 7 | 8 | config :rollbax, enabled: :log, enable_crash_reports: true 9 | -------------------------------------------------------------------------------- /app/assets/images/arrow_back.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /app/views/audits/attributes_resource_representation/_destroy.html.erb: -------------------------------------------------------------------------------- 1 | <%= audit.name %> has been removed from 2 | <% if audit.url %> 3 | <%= link_to audit.link_name, audit.url %> 4 | <% else %> 5 | a representation which no longer exists 6 | <% end %> 7 | -------------------------------------------------------------------------------- /app/views/audits/response/_update.mrkdwn.erb: -------------------------------------------------------------------------------- 1 | <%= audit.auditable_type %> <% if audit.url %><<%= audit.url %>|<%= audit.link_name %>><% else %>Audit which no longer exists<% end %> has been updated: 2 | <%= render 'audits/changes', audited_changes: audit.map_changes %> -------------------------------------------------------------------------------- /db/migrate/20170614152319_add_resource_representation_id_to_responses.rb: -------------------------------------------------------------------------------- 1 | class AddResourceRepresentationIdToResponses < ActiveRecord::Migration[5.0] 2 | def change 3 | add_reference :responses, :resource_representation, foreign_key: true 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20170918155835_add_faker_to_attributes_resource_representation.rb: -------------------------------------------------------------------------------- 1 | class AddFakerToAttributesResourceRepresentation < ActiveRecord::Migration[5.0] 2 | def change 3 | add_column :attributes_resource_representations, :faker, :string 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20180219094508_add_ignore_ssl_to_proxy_configuration.rb: -------------------------------------------------------------------------------- 1 | class AddIgnoreSslToProxyConfiguration < ActiveRecord::Migration[5.1] 2 | def change 3 | add_column :proxy_configurations, :ignore_ssl, :boolean, default: false, null: false 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20190613080952_add_slack_to_projects.rb: -------------------------------------------------------------------------------- 1 | class AddSlackToProjects < ActiveRecord::Migration[5.1] 2 | def change 3 | add_column :projects, :slack_incoming_webhook_url, :string 4 | add_column :projects, :slack_channel, :string 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20191006172737_route_deprecated.rb: -------------------------------------------------------------------------------- 1 | class RouteDeprecated < ActiveRecord::Migration[5.0] 2 | def up 3 | add_column :routes, :deprecated, :string 4 | end 5 | 6 | def down 7 | remove_column :routes, :deprecated 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /db/migrate/20191101142812_add_operation_id.rb: -------------------------------------------------------------------------------- 1 | class AddOperationId < ActiveRecord::Migration[5.0] 2 | def up 3 | add_column :routes, :operation_id, :string 4 | end 5 | 6 | def down 7 | remove_column :routes, :operation_id 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /test/factories/headers.rb: -------------------------------------------------------------------------------- 1 | FactoryBot.define do 2 | 3 | sequence :header_name do |n| 4 | "Header #{n}" 5 | end 6 | 7 | factory :header do 8 | name { generate(:header_name) } 9 | association :http_message, factory: :route 10 | end 11 | end -------------------------------------------------------------------------------- /test/factories/mock_profiles.rb: -------------------------------------------------------------------------------- 1 | FactoryBot.define do 2 | 3 | sequence :mock_profile_name do |n| 4 | "MockProfile #{n}" 5 | end 6 | 7 | factory :mock_profile do 8 | name { generate(:mock_profile_name) } 9 | project 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /app/jobs/report_validator_job.rb: -------------------------------------------------------------------------------- 1 | class ReportValidatorJob < Struct.new(:report_id) 2 | def perform 3 | report = Report.find_by(id: report_id) 4 | return if report.nil? || report.validated 5 | 6 | ReportValidator.new(report).validate 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /app/views/audits/resources_representation/_create.html.erb: -------------------------------------------------------------------------------- 1 |
2 | A new ResourceRepresentation 3 | <% if audit.url %> 4 | <%= link_to audit.link_name, audit.url %> 5 | <% else %> 6 | which no longer exists 7 | <% end %> 8 | has been created 9 |
-------------------------------------------------------------------------------- /app/views/audits/response/_destroy.html.erb: -------------------------------------------------------------------------------- 1 |
2 | <%= audit.type %> <%= audit.name %> has been deleted: 3 | <% if audit.url %> 4 | <%= link_to audit.link_name, audit.url %> 5 | <% else %> 6 | Audit which no longer exists 7 | <% end %> 8 |
9 | -------------------------------------------------------------------------------- /app/views/responses/new.html.haml: -------------------------------------------------------------------------------- 1 | = content_for :title, "New Response #{route.url}" 2 | 3 | .page-header 4 | %h1 5 | !="#{route.url} New Response " 6 | 7 | = render 'form' 8 | 9 | = link_to 'Back', project_route_path(project, route) 10 | -------------------------------------------------------------------------------- /db/migrate/20171031084915_add_min_max_items_to_attributes.rb: -------------------------------------------------------------------------------- 1 | class AddMinMaxItemsToAttributes < ActiveRecord::Migration[5.0] 2 | def change 3 | add_column :attributes, :min_items, :integer 4 | add_column :attributes, :max_items, :integer 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20180403141405_remove_schemas_backup.rb: -------------------------------------------------------------------------------- 1 | class RemoveSchemasBackup < ActiveRecord::Migration[5.1] 2 | def change 3 | remove_column :routes, :request_body_schema_backup, :json 4 | remove_column :responses, :body_schema_backup, :json 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /test/factories/api_errors.rb: -------------------------------------------------------------------------------- 1 | FactoryBot.define do 2 | sequence :api_error_name do |n| 3 | "API Error #{n}" 4 | end 5 | 6 | factory :api_error do 7 | name { generate(:api_error_name) } 8 | json_schema '{}' 9 | project 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | # Add your own tasks in files placed in lib/tasks ending in .rake, 2 | # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. 3 | 4 | require File.expand_path('config/application', __dir__) 5 | 6 | Rails.application.load_tasks 7 | -------------------------------------------------------------------------------- /app/serializers/resource_serializer.rb: -------------------------------------------------------------------------------- 1 | class ResourceSerializer < ActiveModel::Serializer 2 | attributes :id, :name, :description 3 | has_many :resource_attributes 4 | has_many :resource_representations, serializer: ExtendedResourceRepresentationSerializer 5 | end 6 | -------------------------------------------------------------------------------- /app/views/audits/response/_create.html.erb: -------------------------------------------------------------------------------- 1 |
2 | A new <%= audit.type %> <%= audit.name %> has been created: 3 | <% if audit.url %> 4 | <%= link_to audit.link_name, audit.url %> 5 | <% else %> 6 | Audit which no longer exists 7 | <% end %> 8 |
9 | -------------------------------------------------------------------------------- /app/views/devise/mailer/confirmation_instructions.html.haml: -------------------------------------------------------------------------------- 1 | %p=t('mailer.confirmation_grettings', email: @email) 2 | 3 | %p=t('mailer.confirmation_instructions') 4 | 5 | %p=link_to(t('mailer.confirmation_action'), confirmation_url(@resource, confirmation_token: @token)) 6 | -------------------------------------------------------------------------------- /app/views/responses/edit.html.haml: -------------------------------------------------------------------------------- 1 | = content_for :title, "Edit Response #{route.url}" 2 | 3 | .page-header 4 | %h1 5 | !="#{route.url} Edit Response " 6 | 7 | = render 'form' 8 | 9 | = link_to 'Back', project_route_path(project, route) 10 | -------------------------------------------------------------------------------- /test/factories/resource_instances.rb: -------------------------------------------------------------------------------- 1 | FactoryBot.define do 2 | 3 | sequence :mock_name do |n| 4 | "Mock #{n}" 5 | end 6 | 7 | factory :resource_instance do 8 | name { generate(:mock_name) } 9 | body '{}' 10 | resource 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /app/views/audits/resources_representation/_update.mrkdwn.erb: -------------------------------------------------------------------------------- 1 | <% if audit.url %><<%= audit.url %>|<%= audit.link_name %>><% else %>A ResourceRepresentation which no longer exists<% end %> has been updated: 2 | <%= render 'audits/changes', audited_changes: audit.map_changes %> 3 | -------------------------------------------------------------------------------- /db/migrate/20161213093837_create_projects.rb: -------------------------------------------------------------------------------- 1 | class CreateProjects < ActiveRecord::Migration[5.0] 2 | def change 3 | create_table :projects do |t| 4 | t.string :title 5 | t.text :description 6 | 7 | t.timestamps 8 | end 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /app/views/audits/metadata_response/_destroy.html.erb: -------------------------------------------------------------------------------- 1 |
2 | Metadatum <%= audit.name %> has been removed from 3 | <% if audit.url %> 4 | <%= link_to audit.link_name, audit.url %> 5 | <% else %> 6 | a response which no longer exists 7 | <% end %> 8 |
9 | -------------------------------------------------------------------------------- /db/migrate/20180116160324_add_recoverable_to_users.rb: -------------------------------------------------------------------------------- 1 | class AddRecoverableToUsers < ActiveRecord::Migration[5.0] 2 | def change 3 | change_table :users do |t| 4 | t.string :reset_password_token 5 | t.datetime :reset_password_sent_at 6 | end 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /test/factories/metadata.rb: -------------------------------------------------------------------------------- 1 | FactoryBot.define do 2 | 3 | sequence :metadatum_name do |n| 4 | "Metadatum #{n}" 5 | end 6 | 7 | factory :metadatum do 8 | project 9 | name { generate(:metadatum_name) } 10 | primitive_type :integer 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /app/views/audits/attribute/_destroy.html.erb: -------------------------------------------------------------------------------- 1 |
2 | Attribute <%= audit.name %> has been deleted from 3 | <% if audit.url %> 4 | <%= link_to audit.link_name, audit.url %> 5 | <% else %> 6 | an associated resource which no longer exists 7 | <% end %> 8 |
9 | -------------------------------------------------------------------------------- /app/views/audits/metadata_response/_update.mrkdwn.erb: -------------------------------------------------------------------------------- 1 | Metadatum *<%= audit.name %>* on <% if audit.url %><<%= audit.url %>|<%= audit.link_name %>><% else %>a response which no longer exists<% end %> has been updated: 2 | <%= render 'audits/changes', audited_changes: audit.map_changes %> 3 | -------------------------------------------------------------------------------- /app/views/code/graphql.ruby.erb: -------------------------------------------------------------------------------- 1 | class <%= resource.graphql_name %> < Types::BaseObject 2 | <% resource.resource_attributes.each do |attribute| %> 3 | field :<%= attribute.snake_variable_name %>, <%= attribute.graphql_type%>, null: <%= attribute.graphql_nullable %> 4 | <% end %> 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20170623124732_add_is_collection_to_resource_representations.rb: -------------------------------------------------------------------------------- 1 | class AddIsCollectionToResourceRepresentations < ActiveRecord::Migration[5.0] 2 | def change 3 | add_column :resource_representations, :is_collection, :boolean, null: false, default: false 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20171013123912_rename_request_body_schema_to_request_body_schema_backup.rb: -------------------------------------------------------------------------------- 1 | class RenameRequestBodySchemaToRequestBodySchemaBackup < ActiveRecord::Migration[5.0] 2 | def change 3 | rename_column :routes, :request_body_schema, :request_body_schema_backup 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /app/views/audits/attribute/_create.html.erb: -------------------------------------------------------------------------------- 1 |
2 | <% if audit.url %> 3 | <%= link_to audit.link_name, audit.url %> 4 | <% else %> 5 | Associated resource which no longer exists 6 | <% end %> 7 | has a new attribute <%= audit.name %> (<%= audit.type %>) 8 |
9 | -------------------------------------------------------------------------------- /app/views/audits/metadata_response/_create.html.erb: -------------------------------------------------------------------------------- 1 |
2 | Metadatum <%= audit.name %> has been added to 3 | <% if audit.url %> 4 | <%= link_to audit.link_name, audit.url %> 5 | <% else %> 6 | a response which no longer exists 7 | <% end %> 8 |
9 | 10 | -------------------------------------------------------------------------------- /app/views/resource_representations/new.html.haml: -------------------------------------------------------------------------------- 1 | = content_for :title, "New Representation" 2 | 3 | .page-header 4 | %h1 5 | !="#{resource.name} New Representation " 6 | 7 | = render 'form' 8 | 9 | = link_to 'Back', project_resource_path(project, resource) 10 | -------------------------------------------------------------------------------- /db/migrate/20170322151410_create_validations.rb: -------------------------------------------------------------------------------- 1 | class CreateValidations < ActiveRecord::Migration[5.0] 2 | def change 3 | create_table :validations do |t| 4 | t.text :json_schema 5 | t.text :json_instance 6 | 7 | t.timestamps 8 | end 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /proxy/lib/pericles_proxy/models/delayed_job.ex: -------------------------------------------------------------------------------- 1 | defmodule PericlesProxy.DelayedJob do 2 | use Ecto.Schema 3 | 4 | schema "delayed_jobs" do 5 | field(:handler, :string) 6 | field(:run_at, :naive_datetime) 7 | timestamps(inserted_at: :created_at) 8 | end 9 | end 10 | 11 | -------------------------------------------------------------------------------- /app/serializers/resource_index_serializer.rb: -------------------------------------------------------------------------------- 1 | class ResourceIndexSerializer < ActiveModel::Serializer 2 | attributes :id, :name, :description, :has_invalid_mocks? 3 | attributes :request_route_ids 4 | attributes :response_ids 5 | has_many :used_resources, serializer: IdSerializer 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20170828152358_add_custom_nullable_to_attributes_resource_representations.rb: -------------------------------------------------------------------------------- 1 | class AddCustomNullableToAttributesResourceRepresentations < ActiveRecord::Migration[5.0] 2 | def change 3 | add_column :attributes_resource_representations, :custom_nullable, :boolean 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20171130154438_add_is_null_to_attributes_resource_representation.rb: -------------------------------------------------------------------------------- 1 | class AddIsNullToAttributesResourceRepresentation < ActiveRecord::Migration[5.0] 2 | def change 3 | add_column :attributes_resource_representations, :is_null, :boolean, default: false, null: false 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: [ 3 | require('postcss-import'), 4 | require('postcss-flexbugs-fixes'), 5 | require('postcss-preset-env')({ 6 | autoprefixer: { 7 | flexbox: 'no-2009' 8 | }, 9 | stage: 3 10 | }) 11 | ] 12 | } 13 | -------------------------------------------------------------------------------- /app/views/audits/attributes_resource_representation/_update.mrkdwn.erb: -------------------------------------------------------------------------------- 1 | <% if audit.url %><<%= audit.url %>|<%= audit.link_name %>><% else %>A representation which no longer exists<% end %> *<%= audit.name %>* has been updated: 2 | <%= render 'audits/changes', audited_changes: audit.map_changes %> 3 | 4 | -------------------------------------------------------------------------------- /config/initializers/cookies_serializer.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Specify a serializer for the signed and encrypted cookie jars. 4 | # Valid options are :json, :marshal, and :hybrid. 5 | Rails.application.config.action_dispatch.cookies_serializer = :json 6 | -------------------------------------------------------------------------------- /test/factories/query_parameters.rb: -------------------------------------------------------------------------------- 1 | FactoryBot.define do 2 | 3 | sequence :query_parameter_name do |n| 4 | "QueryParameter #{n}" 5 | end 6 | 7 | factory :query_parameter do 8 | name { generate(:query_parameter_name) } 9 | primitive_type :integer 10 | route 11 | end 12 | end -------------------------------------------------------------------------------- /app/models/scheme.rb: -------------------------------------------------------------------------------- 1 | class Scheme < ApplicationRecord 2 | validates :name, presence: true 3 | 4 | has_many :resource_attributes, class_name: 'Attribute', dependent: :nullify 5 | 6 | def format? 7 | regexp.blank? 8 | end 9 | 10 | def pattern? 11 | !format? 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /app/views/layouts/application.html.haml: -------------------------------------------------------------------------------- 1 | !!! 2 | %html 3 | %head 4 | = render partial: 'shared/head' 5 | %body 6 | #wrapper 7 | = render 'shared/sidebar' 8 | #page-content-wrapper 9 | = render 'shared/alert' 10 | = yield 11 | 12 | = yield :page_scripts 13 | -------------------------------------------------------------------------------- /app/views/mock_profiles/new.html.haml: -------------------------------------------------------------------------------- 1 | = content_for :title, "New Mock Profile" 2 | 3 | %h1 New Mock Profile 4 | 5 | #mock_profile_form 6 | = bootstrap_form_for([project, mock_profile]) do |f| 7 | .flexcontainer-justify-end= f.submit class: 'btn btn-primary' 8 | = f.text_field :name 9 | 10 | -------------------------------------------------------------------------------- /config/locales/attributes/en.yml: -------------------------------------------------------------------------------- 1 | en: 2 | activerecord: 3 | errors: 4 | models: 5 | attribute: 6 | attributes: 7 | base: 8 | type_cannot_be_primitive_type_and_resource: "The chosen type for the attribute cannot be both a primitive type and a resource" 9 | -------------------------------------------------------------------------------- /app/decorators/resource_decorator.rb: -------------------------------------------------------------------------------- 1 | class ResourceDecorator < Draper::Decorator 2 | delegate_all 3 | 4 | def used_in_resources_links 5 | object.used_in_resources.map do |r| 6 | h.link_to(r.name, h.project_resource_path(r.project, r)) 7 | end.to_sentence.html_safe 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /app/models/metadata_response.rb: -------------------------------------------------------------------------------- 1 | class MetadataResponse < ApplicationRecord 2 | belongs_to :metadatum, required: true 3 | belongs_to :response, required: true 4 | 5 | validates_uniqueness_of :metadatum_id, scope: :response_id 6 | 7 | audited 8 | 9 | delegate :project, to: :response 10 | end 11 | -------------------------------------------------------------------------------- /app/views/audits/route/_update.html.erb: -------------------------------------------------------------------------------- 1 |
2 | <% if audit.url %> 3 | <%= link_to audit.link_name, audit.url %> 4 | <% else %> 5 | A Route which no longer exists 6 | <% end %> 7 | has been updated: 8 | <%= render 'audits/changes', audited_changes: audit.map_changes %> 9 |
10 | -------------------------------------------------------------------------------- /app/controllers/resource_instances_controller.rb: -------------------------------------------------------------------------------- 1 | class ResourceInstancesController < AbstractInstancesController 2 | def model_name 3 | 'resource' 4 | end 5 | 6 | def redirect_to_model 7 | redirect_to project_resource_path(project, model, anchor: 'pills-resource-instances') 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /app/views/audits/attribute/_update.mrkdwn.erb: -------------------------------------------------------------------------------- 1 | <%= audit.auditable_type %> <%= audit.auditable&.name %> of <% if audit.url %><<%= audit.url %>|<%= audit.link_name %>><% else %>an associated resource which no longer exists<% end %> has been updated: 2 | <%= render 'audits/changes', audited_changes: audit.map_changes %> 3 | -------------------------------------------------------------------------------- /app/views/audits/resource/_update.html.erb: -------------------------------------------------------------------------------- 1 |
2 | <% if audit.url %> 3 | <%= link_to audit.link_name, audit.url %> 4 | <% else %> 5 | A Resource which no longer exists 6 | <% end %> 7 | has been updated: 8 | <%= render 'audits/changes', audited_changes: audit.map_changes %> 9 |
10 | -------------------------------------------------------------------------------- /app/views/responses/_header_fields.html.haml: -------------------------------------------------------------------------------- 1 | %tr.fields.nested-fields 2 | %td 3 | = f.text_field :name, hide_label: true, placeholder: t('.name_placeholder') 4 | %td 5 | = f.text_field :value, hide_label: true, placeholder: t('.value_placeholder') 6 | %td 7 | = link_to_remove_association "Remove", f 8 | -------------------------------------------------------------------------------- /config/locales/attributes/fr.yml: -------------------------------------------------------------------------------- 1 | fr: 2 | activerecord: 3 | errors: 4 | models: 5 | attribute: 6 | attributes: 7 | base: 8 | type_cannot_be_primitive_type_and_resource: "Le type choisi pour l'attribut ne peut pas être à la fois un type primitif et une ressource" 9 | -------------------------------------------------------------------------------- /db/migrate/20170407165817_create_responses.rb: -------------------------------------------------------------------------------- 1 | class CreateResponses < ActiveRecord::Migration[5.0] 2 | def change 3 | create_table :responses do |t| 4 | t.integer :status_code 5 | t.text :description 6 | t.json :body_schema 7 | 8 | t.timestamps 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /db/migrate/20171227103848_create_members.rb: -------------------------------------------------------------------------------- 1 | class CreateMembers < ActiveRecord::Migration[5.0] 2 | def change 3 | create_table :members do |t| 4 | t.references :project, foreign_key: true 5 | t.references :user, foreign_key: true 6 | 7 | t.timestamps 8 | end 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /app/repositories/audits_repository.rb: -------------------------------------------------------------------------------- 1 | class AuditsRepository 2 | def news_of_project(project) 3 | Audited::Audit 4 | .of_project(project) 5 | .where.not(auditable_type: ['Header', 'QueryParameter']) 6 | .preload(:auditable, :associated) 7 | .order(created_at: :desc) 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /app/assets/images/copy.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /app/views/audits/metadatum/_update.html.erb: -------------------------------------------------------------------------------- 1 |
2 | <% if audit.url %> 3 | Metadatum <%= link_to audit.link_name, audit.url %> 4 | <% else %> 5 | A Metadatum which no longer exists 6 | <% end %> 7 | has been updated: 8 | <%= render 'audits/changes', audited_changes: audit.map_changes %> 9 |
10 | -------------------------------------------------------------------------------- /config/locales/api_errors/en.yml: -------------------------------------------------------------------------------- 1 | en: 2 | api_errors: 3 | new_form: 4 | json_instance_explanation: 5 | If you give us an example of your error, we can try to generate a JSON Schema from it 6 | index: 7 | no_errors: There are no errors defined, please define here what kind of errors your API can throw -------------------------------------------------------------------------------- /db/migrate/20171228165935_rename_key_name_to_custom_key_name.rb: -------------------------------------------------------------------------------- 1 | class RenameKeyNameToCustomKeyName < ActiveRecord::Migration[5.0] 2 | def change 3 | remove_column :attributes_resource_representations, :key_name, :string 4 | add_column :attributes_resource_representations, :custom_key_name, :string 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /app/helpers/attributes_helper.rb: -------------------------------------------------------------------------------- 1 | module AttributesHelper 2 | def format_type(primitive_type, resource_id, is_array, is_null = false) 3 | return 'NULL' if is_null 4 | 5 | base_type = primitive_type.nil? ? Resource.find(resource_id).name : primitive_type 6 | is_array ? "array<#{base_type}>" : base_type 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /app/models/validation_error.rb: -------------------------------------------------------------------------------- 1 | class ValidationError < ApplicationRecord 2 | belongs_to :report 3 | 4 | enum category: [:header, :body, :status_code] 5 | 6 | validates :description, presence: true 7 | 8 | def header_name 9 | return unless header? 10 | 11 | description.split.first 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /app/policies/scheme_policy.rb: -------------------------------------------------------------------------------- 1 | class SchemePolicy < ApplicationPolicy 2 | def create? 3 | user&.internal? 4 | end 5 | 6 | def update? 7 | user&.internal? 8 | end 9 | 10 | def destroy? 11 | user&.internal? 12 | end 13 | 14 | def permitted_attributes 15 | [:name, :regexp] 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /app/views/api_error_instances/_form.html.haml: -------------------------------------------------------------------------------- 1 | = bootstrap_form_for(model_instance.persisted? ? model_instance : [model, model_instance]) do |f| 2 | 3 | .flexcontainer-justify-end= f.submit class: 'btn btn-primary' 4 | 5 | = f.text_field :name 6 | 7 | = f.text_area :body, value: format_json(model_instance.body), class: 'json' -------------------------------------------------------------------------------- /app/views/audits/attributes_resource_representation/_update.html.erb: -------------------------------------------------------------------------------- 1 | <% if audit.url %> 2 | <%= link_to audit.link_name, audit.url %> 3 | <% else %> 4 | A representation which no longer exists 5 | <% end %> 6 | <%= audit.name %> has been updated: 7 | <%= render 'audits/changes', audited_changes: audit.map_changes %> 8 | 9 | -------------------------------------------------------------------------------- /db/migrate/20170310105503_create_resources.rb: -------------------------------------------------------------------------------- 1 | class CreateResources < ActiveRecord::Migration[5.0] 2 | def change 3 | create_table :resources do |t| 4 | t.string :name 5 | t.text :description 6 | t.references :project, foreign_key: true 7 | 8 | t.timestamps 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /test/models/audit_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class AuditTest < ActiveSupport::TestCase 4 | test "project scope" do 5 | project = create(:project) 6 | assert_difference -> { Audited::Audit.of_project(project).count }, 2 do 7 | create(:resource, project: project) 8 | end 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /app/controllers/concerns/authenticated.rb: -------------------------------------------------------------------------------- 1 | module Authenticated 2 | extend ActiveSupport::Concern 3 | 4 | included do 5 | before_action :authenticate_user! 6 | 7 | rescue_from Pundit::NotAuthorizedError do 8 | render file: 'public/403.html', status: :forbidden, layout: false 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /app/views/audits/response/_update.html.erb: -------------------------------------------------------------------------------- 1 |
2 | <%= audit.type %> 3 | <% if audit.url %> 4 | <%= link_to audit.link_name, audit.url %> 5 | <% else %> 6 | Audit which no longer exists 7 | <% end %> 8 | has been updated: 9 | <%= render 'audits/changes', audited_changes: audit.map_changes %> 10 |
11 | -------------------------------------------------------------------------------- /db/migrate/20170329124037_create_json_errors.rb: -------------------------------------------------------------------------------- 1 | class CreateJsonErrors < ActiveRecord::Migration[5.0] 2 | def change 3 | create_table :json_errors do |t| 4 | t.text :description 5 | t.string :type 6 | t.references :validation, foreign_key: true 7 | 8 | t.timestamps 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /app/decorators/news/header_audit_decorator.rb: -------------------------------------------------------------------------------- 1 | module News 2 | class HeaderAuditDecorator < AuditDecorator 3 | def name 4 | audit.audited_changes['name'] 5 | end 6 | 7 | def url 8 | # TODO: Clement Villain 2019-03-04 9 | # Handle polymorphic association http_message 10 | end 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /db/migrate/20170407172714_create_headers.rb: -------------------------------------------------------------------------------- 1 | class CreateHeaders < ActiveRecord::Migration[5.0] 2 | def change 3 | create_table :headers do |t| 4 | t.string :name 5 | t.text :description 6 | t.references :http_message, polymorphic: true, index: true 7 | 8 | t.timestamps 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /app/assets/images/edit.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /app/validators/json_validator.rb: -------------------------------------------------------------------------------- 1 | class JsonValidator < ActiveModel::EachValidator 2 | def validate_each(record, attribute, value) 3 | return if value.empty? 4 | JSON.parse(value) if value.is_a? String 5 | rescue JSON::ParserError 6 | record.errors.add(attribute, :value_must_be_valid_json) if value.is_a? String 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /app/views/audits/resources_representation/_update.html.erb: -------------------------------------------------------------------------------- 1 |
2 | <% if audit.url %> 3 | <%= link_to audit.link_name, audit.url %> 4 | <% else %> 5 | A ResourceRepresentation which no longer exists 6 | <% end %> 7 | has been updated: 8 | <%= render 'audits/changes', audited_changes: audit.map_changes %> 9 |
10 | -------------------------------------------------------------------------------- /config/locales/api_errors/fr.yml: -------------------------------------------------------------------------------- 1 | fr: 2 | api_errors: 3 | new_form: 4 | json_instance_explanation: 5 | Si vous nous donnez un exemple de votre erreur, nous pouvons essayer de générer un JSON Schema pour vous 6 | index: 7 | no_errors: Aucune erreur n'est spécifiée, il faut définir ici la forme des erreurs que l'API renvoie -------------------------------------------------------------------------------- /db/migrate/20161214162402_create_json_schemas.rb: -------------------------------------------------------------------------------- 1 | class CreateJsonSchemas < ActiveRecord::Migration[5.0] 2 | def change 3 | create_table :json_schemas do |t| 4 | t.string :name 5 | t.json :schema 6 | t.references :project, index: true, foreign_key: true 7 | 8 | t.timestamps 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /db/migrate/20171229144723_change_validation_errors_description_to_text.rb: -------------------------------------------------------------------------------- 1 | class ChangeValidationErrorsDescriptionToText < ActiveRecord::Migration[5.0] 2 | def up 3 | change_column :validation_errors, :description, :text 4 | end 5 | 6 | def down 7 | change_column :validation_errors, :description, :string 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /db/migrate/20180117161236_create_metadata.rb: -------------------------------------------------------------------------------- 1 | class CreateMetadata < ActiveRecord::Migration[5.0] 2 | def change 3 | create_table :metadata do |t| 4 | t.string :name 5 | t.integer :primitive_type, default: 0 6 | t.references :project, foreign_key: true 7 | 8 | t.timestamps 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /lib/tasks/audits.rake: -------------------------------------------------------------------------------- 1 | namespace :audits do 2 | task slack_post: :environment do 3 | Project.where.not(slack_channel: [nil, '']).map do |project| 4 | news_posted_count = PostSlackNews.new(project).execute 5 | puts "#{news_posted_count} news posted on #{project.slack_channel} for project #{project.id}" 6 | end 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /app/validators/regexp_validator.rb: -------------------------------------------------------------------------------- 1 | class RegexpValidator < ActiveModel::EachValidator 2 | def validate_each(record, attribute, value) 3 | return if value.blank? 4 | 5 | begin 6 | Regexp.new(value.to_s) 7 | rescue RegexpError 8 | record.errors.add(attribute, 'must_be_valid_regexp') 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /app/controllers/headers_controller.rb: -------------------------------------------------------------------------------- 1 | class HeadersController < ApplicationController 2 | include Authenticated 3 | 4 | def index 5 | term = params[:term] ? params[:term] : '' 6 | @found_headers = Header.ransack(name_cont: term).result(distinct: true).select(:name) 7 | render json: @found_headers, status: :ok 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /app/views/resource_representations/edit.html.haml: -------------------------------------------------------------------------------- 1 | = content_for :title, "Edit Representation #{resource_representation.name}" 2 | 3 | .page-header 4 | %h1 5 | !="#{resource.name} Edit Representation: #{resource_representation.name} " 6 | 7 | = render 'form' 8 | 9 | = link_to 'Back', project_resource_path(project, resource) 10 | -------------------------------------------------------------------------------- /app/views/shared/_errors.html.haml: -------------------------------------------------------------------------------- 1 | - if object.errors.any? 2 | #error_explanation 3 | %h2 4 | = pluralize(object.errors.count, "error") 5 | = " prohibited this #{object.respond_to?(:class_name) ? object.class_name : object.class.name} from being saved:" 6 | %ul 7 | - object.errors.full_messages.each do |msg| 8 | %li= msg 9 | -------------------------------------------------------------------------------- /app/decorators/code/resource_decorator.rb: -------------------------------------------------------------------------------- 1 | class Code::ResourceDecorator < Draper::Decorator 2 | include Code::DataClass 3 | delegate_all 4 | 5 | def resource_attributes 6 | @resource_attributes ||= object.resource_attributes.map do |a| 7 | Code::AttributeDecorator.new(a) 8 | end.sort_by(&:camel_variable_name) 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /app/views/metadatum_instances/_form.html.haml: -------------------------------------------------------------------------------- 1 | = bootstrap_form_for(model_instance.persisted? ? model_instance : [model, model_instance]) do |f| 2 | .flexcontainer-justify-end= f.submit class: 'btn btn-primary' 3 | 4 | = f.text_field :name 5 | 6 | = f.text_field :body, value: model_instance.body, class: 'json', placeholder: '"string", 123, 0.5, true...' 7 | -------------------------------------------------------------------------------- /lib/node/generate_mock.js: -------------------------------------------------------------------------------- 1 | var jsf = require('json-schema-faker'); 2 | // jsf.option({ optionalsProbability: 1.0 }); TODO Uncomment when https://github.com/json-schema-faker/json-schema-faker/issues/477#issuecomment-510525609 fixed 3 | 4 | var schema = JSON.parse(process.argv[2]); 5 | var json = jsf.generate(schema); 6 | 7 | console.log(JSON.stringify(json)); 8 | -------------------------------------------------------------------------------- /test/models/factories_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class FactoriesTest < ActiveSupport::TestCase 4 | FactoryBot.factories.map(&:name).each do |factory_name| 5 | test "#{factory_name} factory" do 6 | object = build(factory_name) 7 | assert object.valid?, object.errors.full_messages.join('|') 8 | end 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /config/locales/resource_representations/en.yml: -------------------------------------------------------------------------------- 1 | en: 2 | activerecord: 3 | errors: 4 | models: 5 | resource_representation: 6 | attributes: 7 | base: 8 | destroy_failed_foreign_key: "Could not destroy resource representation because it is still referenced in responses 9 | or in resource representations." -------------------------------------------------------------------------------- /proxy/lib/pericles_proxy/repositories/proxy_configuration_repo.ex: -------------------------------------------------------------------------------- 1 | defmodule PericlesProxy.ProxyConfigurationRepo do 2 | alias PericlesProxy.{Repo, ProxyConfiguration} 3 | 4 | @spec for_project(Integer.t) :: ProxyConfiguration.t 5 | def for_project(project_id) do 6 | Repo.get_by(ProxyConfiguration, project_id: project_id) 7 | end 8 | end 9 | 10 | 11 | -------------------------------------------------------------------------------- /app/views/audits/metadata_response/_update.html.erb: -------------------------------------------------------------------------------- 1 |
2 | Metadatum <%= audit.name %> on 3 | <% if audit.url %> 4 | <%= link_to audit.link_name, audit.url %> 5 | <% else %> 6 | a response which no longer exists 7 | <% end %> 8 | has been updated: 9 | <%= render 'audits/changes', audited_changes: audit.map_changes %> 10 |
11 | 12 | -------------------------------------------------------------------------------- /app/views/headers/_header.html.haml: -------------------------------------------------------------------------------- 1 | .panel.panel-default 2 | .panel-body 3 | .row 4 | .col-xs-6 5 | %dl 6 | %dt Name 7 | %dd 8 | %strong= header.name 9 | - unless header.value.blank? 10 | .col-xs-6 11 | %dl 12 | %dt Value 13 | %dd 14 | %strong= header.value -------------------------------------------------------------------------------- /app/views/metadata/edit.html.haml: -------------------------------------------------------------------------------- 1 | = content_for :title, "Edit Metadatum #{metadatum.name}" 2 | 3 | %ol.breadcrumb 4 | %li 5 | = link_to 'Projects', projects_path 6 | %li 7 | = link_to "#{project.title}", project_path(project) 8 | %li 9 | = link_to 'Metadata', project_metadata_path(project) 10 | %li 11 | = metadatum.name 12 | 13 | = render 'form' -------------------------------------------------------------------------------- /db/migrate/20170602145951_create_resource_representations.rb: -------------------------------------------------------------------------------- 1 | class CreateResourceRepresentations < ActiveRecord::Migration[5.0] 2 | def change 3 | create_table :resource_representations do |t| 4 | t.string :name 5 | t.text :description 6 | t.references :resource, foreign_key: true 7 | 8 | t.timestamps 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /app/decorators/attribute_decorator.rb: -------------------------------------------------------------------------------- 1 | class AttributeDecorator < Draper::Decorator 2 | delegate_all 3 | 4 | def key_name_placeholder 5 | name.underscore.parameterize(separator: '_') 6 | end 7 | 8 | def readable_type 9 | base_type = resource&.name || primitive_type.to_s.capitalize 10 | is_array ? "Array<#{base_type}>" : base_type 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /db/migrate/20170720143737_add_missing_constraints_in_attribute.rb: -------------------------------------------------------------------------------- 1 | class AddMissingConstraintsInAttribute < ActiveRecord::Migration[5.0] 2 | def change 3 | add_column :attributes, :min_length, :integer 4 | add_column :attributes, :max_length, :integer 5 | add_column :attributes, :minimum, :integer 6 | add_column :attributes, :maximum, :integer 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /app/models/query_parameter.rb: -------------------------------------------------------------------------------- 1 | class QueryParameter < ApplicationRecord 2 | enum primitive_type: [:integer, :string, :boolean] 3 | 4 | belongs_to :route 5 | 6 | validates :name, presence: true 7 | validates :primitive_type, presence: true 8 | validates :route, presence: true 9 | 10 | delegate :project, to: :route 11 | 12 | audited associated_with: :route 13 | end 14 | -------------------------------------------------------------------------------- /app/views/routes/_form.html.haml: -------------------------------------------------------------------------------- 1 | - if params[:section] == "base" || route.new_record? 2 | = render 'base_form' 3 | 4 | - if params[:section] == "query_parameters" 5 | = render 'query_parameters_form' 6 | 7 | - if params[:section] == "request_headers" 8 | = render 'request_headers_form' 9 | 10 | - if params[:section] == "request_body" 11 | = render 'request_body_form' 12 | -------------------------------------------------------------------------------- /db/migrate/20170720101800_add_request_ressource_representation_to_route.rb: -------------------------------------------------------------------------------- 1 | class AddRequestRessourceRepresentationToRoute < ActiveRecord::Migration[5.0] 2 | def change 3 | add_reference :routes, :request_resource_representation, references: :resource_representations 4 | add_foreign_key :routes, :resource_representations, column: :request_resource_representation_id 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20180208103459_create_metadata_responses.rb: -------------------------------------------------------------------------------- 1 | class CreateMetadataResponses < ActiveRecord::Migration[5.0] 2 | def change 3 | create_table(:metadata_responses) do |t| 4 | t.references :metadatum, foreign_key: true, index: true 5 | t.references :response, foreign_key: true, index: true 6 | 7 | t.timestamps null: false 8 | end 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /app/assets/stylesheets/styles/responses.scss: -------------------------------------------------------------------------------- 1 | .valid-response { 2 | background-color: #5cb85c !important; 3 | color: white !important; 4 | } 5 | 6 | .invalid-response { 7 | background-color: #d9534f !important; 8 | color: white !important; 9 | } 10 | 11 | li > a.valid-response, a.invalid-response { 12 | opacity: 0.5; 13 | } 14 | 15 | li.active > a { 16 | opacity: 1; 17 | } 18 | -------------------------------------------------------------------------------- /app/views/audits/attribute/_update.html.erb: -------------------------------------------------------------------------------- 1 |
2 | <%= audit.auditable_type %> <%= audit.auditable&.name %> of 3 | <% if audit.url %> 4 | <%= link_to audit.link_name, audit.url %> 5 | <% else %> 6 | an associated resource which no longer exists 7 | <% end %> 8 | has been updated: 9 | <%= render 'audits/changes', audited_changes: audit.map_changes %> 10 |
11 | -------------------------------------------------------------------------------- /config/locales/resource_representations/fr.yml: -------------------------------------------------------------------------------- 1 | fr: 2 | activerecord: 3 | errors: 4 | models: 5 | resource_representation: 6 | attributes: 7 | base: 8 | destroy_failed_foreign_key: "Impossible de supprimer cette représentation de ressource car elle toujours référencée 9 | dans des réponses ou dans des représentations de ressource." -------------------------------------------------------------------------------- /app/views/resources/edit_resource.html.haml: -------------------------------------------------------------------------------- 1 | = content_for :title, "Edit Resource #{resource.name}" 2 | 3 | %ol.breadcrumb 4 | %li 5 | = link_to 'Projects', projects_path 6 | %li 7 | = link_to "#{project.title}", project_path(project) 8 | %li 9 | = link_to 'Resources', project_resources_path(project) 10 | %li 11 | = resource.name 12 | 13 | = render 'edit_resource_form' -------------------------------------------------------------------------------- /app/assets/javascripts/setup.js: -------------------------------------------------------------------------------- 1 | $(document).ready(function () { 2 | $("select").chosen({allow_single_deselect: true, search_contains: true}); 3 | $(document).on('cocoon:after-insert', function () { 4 | $("select").chosen({allow_single_deselect: true, search_contains: true}); 5 | }); 6 | 7 | $('[data-toggle="tooltip"]').tooltip(); 8 | hljs.initHighlightingOnLoad(); 9 | }); 10 | 11 | -------------------------------------------------------------------------------- /app/views/metadata/show.html.haml: -------------------------------------------------------------------------------- 1 | %h3 Metadatum 2 | 3 | = render metadatum, show: false 4 | 5 | %h3 Mocks 6 | .flexcontainer-justify-end 7 | = link_to 'New mock', new_metadatum_metadatum_instance_path(metadatum), class: "btn btn-primary" if user.can_create? MetadatumInstance, project: project 8 | .margin-top-element 9 | - metadatum.metadatum_instances.each do |instance| 10 | = render instance -------------------------------------------------------------------------------- /app/views/resources/_edit_resource_form.html.haml: -------------------------------------------------------------------------------- 1 | - content_for :page_scripts do 2 | = javascript_include_tag("resources/form.js") 3 | 4 | = bootstrap_form_for([project, resource]) do |f| 5 | = render 'shared/errors', object: resource 6 | 7 | .flexcontainer-justify-end= f.submit class: 'btn btn-primary' 8 | 9 | = f.text_field :name, placeholder: 'MyResource' 10 | = f.text_area :description -------------------------------------------------------------------------------- /proxy/config/prod.exs: -------------------------------------------------------------------------------- 1 | use Mix.Config 2 | 3 | config :pericles_proxy, PericlesProxy.Repo, 4 | adapter: Ecto.Adapters.Postgres, 5 | url: System.get_env("DATABASE_URL"), 6 | pool_size: String.to_integer(System.get_env("POOL_SIZE") || "5"), 7 | ssl: true 8 | 9 | config :rollbax, 10 | access_token: System.get_env("ROLLBAR_ACCESS_TOKEN"), 11 | environment: System.get_env("ROLLBAR_ENV") 12 | -------------------------------------------------------------------------------- /db/migrate/20171108092720_create_mock_instances.rb: -------------------------------------------------------------------------------- 1 | class CreateMockInstances < ActiveRecord::Migration[5.0] 2 | def change 3 | create_table :mock_instances do |t| 4 | t.string :name 5 | t.json :body 6 | t.references :resource, foreign_key: true 7 | 8 | t.timestamps 9 | end 10 | 11 | add_reference :responses, :mock_instance, foreign_key: true 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /app/assets/javascripts/validations/new.js: -------------------------------------------------------------------------------- 1 | $(document).ready(function() { 2 | $("#validate_json_instance").off('click').on("click", function() { 3 | var json_schema = $("#json_schema").val(); 4 | var json_instance = $("#json_instance").val(); 5 | var display_result_element = $("#json-validation-result"); 6 | validate_json_instance(json_schema, json_instance, display_result_element); 7 | }); 8 | }); -------------------------------------------------------------------------------- /app/models/api_error.rb: -------------------------------------------------------------------------------- 1 | class ApiError < ApplicationRecord 2 | belongs_to :project 3 | 4 | has_many :api_error_instances, dependent: :destroy 5 | 6 | validates :name, presence: true, uniqueness: { scope: [:project], case_sensitive: false } 7 | validates :json_schema, json_schema: true 8 | 9 | def has_invalid_mocks? 10 | api_error_instances.any? { |mock| !mock.valid? } 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /app/views/responses/_metadata_responses_fields.html.haml: -------------------------------------------------------------------------------- 1 | .flex-v-center 2 | = f.hidden_field :metadatum_id 3 | = f.check_box :_destroy, { label: '', checked: !f.object.new_record? }, '0', '1' 4 | = f.text_field :key 5 | %dl.h-margin 6 | %dt Name 7 | %dd= f.object.metadatum.name 8 | %dl.h-margin 9 | %dt Type 10 | %dd= f.object.metadatum.primitive_type 11 | = f.check_box :required 12 | -------------------------------------------------------------------------------- /proxy/config/test.exs: -------------------------------------------------------------------------------- 1 | use Mix.Config 2 | 3 | config :pericles_proxy, PericlesProxy.Repo, 4 | adapter: Ecto.Adapters.Postgres, 5 | database: "Pericles_GW_test", 6 | hostname: "localhost", 7 | pool: Ecto.Adapters.SQL.Sandbox 8 | 9 | config :rollbax, enabled: false 10 | 11 | config :logger, level: :info 12 | 13 | config :exvcr, [ 14 | vcr_cassette_library_dir: "test/fixture/vcr_cassettes" 15 | ] 16 | -------------------------------------------------------------------------------- /app/javascript/packs/common/markdown.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue/dist/vue.esm' 2 | import VueMarkdown from 'vue-markdown' 3 | 4 | document.addEventListener('DOMContentLoaded', () => { 5 | Array.from(document.querySelectorAll('.markdown')).forEach(markdown => { 6 | new Vue({ 7 | el: markdown, 8 | components: { 9 | 'vue-markdown': VueMarkdown 10 | } 11 | }); 12 | }) 13 | }); 14 | -------------------------------------------------------------------------------- /app/serializers/extended_resource_representation_serializer.rb: -------------------------------------------------------------------------------- 1 | class ExtendedResourceRepresentationSerializer < ActiveModel::Serializer 2 | attributes :id, :name, :description, :resource_id, :used_in_resource_representations 3 | 4 | has_many :attributes_resource_representations 5 | 6 | def used_in_resource_representations 7 | object.used_in_resource_representations.pluck(:name) 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /db/migrate/20180208151538_create_metadatum_instances.rb: -------------------------------------------------------------------------------- 1 | class CreateMetadatumInstances < ActiveRecord::Migration[5.0] 2 | def change 3 | create_table :metadatum_instances do |t| 4 | t.string :name 5 | t.json :body 6 | t.references :metadatum, foreign_key: true 7 | 8 | t.timestamps 9 | end 10 | 11 | create_join_table :metadatum_instances, :mock_pickers 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /app/decorators/code/resource_representation_decorator.rb: -------------------------------------------------------------------------------- 1 | class Code::ResourceRepresentationDecorator < Draper::Decorator 2 | include Code::DataClass 3 | delegate_all 4 | 5 | def resource_attributes 6 | @resource_attributes ||= object.attributes_resource_representations.map do |a| 7 | Code::AttributesResourceRepresentationDecorator.new(a) 8 | end.sort_by(&:camel_variable_name) 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /app/policies/security_scheme_policy.rb: -------------------------------------------------------------------------------- 1 | class SecuritySchemePolicy < ProjectRelatedPolicy 2 | def permitted_attributes 3 | [ 4 | :key, 5 | :description, 6 | :security_scheme_type, 7 | :name, 8 | :security_scheme_in, 9 | :scheme, 10 | :bearer_format, 11 | :flows, 12 | :open_id_connect_url, 13 | :specification_extensions 14 | ] 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /app/assets/javascripts/security_schemes/form.js: -------------------------------------------------------------------------------- 1 | function updateOnTypeChange () { 2 | const selectedType = $('#security_scheme_security_scheme_type').val() 3 | $(`.security-scheme-detail`).hide() 4 | $(`#security-scheme-detail-${selectedType}`).show() 5 | } 6 | 7 | $(document).ready(function () { 8 | $('#security_scheme_security_scheme_type').on('change', updateOnTypeChange); 9 | updateOnTypeChange(); 10 | }); 11 | -------------------------------------------------------------------------------- /db/migrate/20171013130330_add_root_key_and_is_collection_to_route.rb: -------------------------------------------------------------------------------- 1 | class AddRootKeyAndIsCollectionToRoute < ActiveRecord::Migration[5.0] 2 | def change 3 | rename_column :routes, :is_collection, :request_is_collection 4 | change_column_null :routes, :request_is_collection, false 5 | change_column_default :routes, :request_is_collection, false 6 | add_column :routes, :request_root_key, :string 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /lib/tasks/proxy.rake: -------------------------------------------------------------------------------- 1 | namespace :proxy do 2 | desc 'Clean reports older than 1 month' 3 | task clean_reports: :environment do 4 | Report.unscoped.where('created_at < ?', 1.month.ago).find_each(batch_size: 200, &:destroy) 5 | end 6 | 7 | task validate_reports: :environment do 8 | Report.where(validated: false).find_each do |report| 9 | ReportValidator.new(report).validate 10 | end 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /app/policies/response_policy.rb: -------------------------------------------------------------------------------- 1 | class ResponsePolicy < ProjectRelatedPolicy 2 | def permitted_attributes 3 | [ 4 | :status_code, 5 | :resource_representation_id, 6 | :api_error_id, 7 | :is_collection, 8 | :root_key, 9 | headers_attributes: [:id, :name, :value, :_destroy], 10 | metadata_responses_attributes: [:id, :metadatum_id, :key, :required, :_destroy] 11 | ] 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /app/serializers/attributes_resource_representation_serializer.rb: -------------------------------------------------------------------------------- 1 | class AttributesResourceRepresentationSerializer < ActiveModel::Serializer 2 | attributes :id, :is_required, :parent_resource_representation_id, 3 | :attribute_id, :resource_representation_id, :custom_key_name, :is_null, 4 | :resource_representation_name 5 | 6 | def resource_representation_name 7 | object.resource_representation&.name 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /db/migrate/20170313102138_create_routes.rb: -------------------------------------------------------------------------------- 1 | class CreateRoutes < ActiveRecord::Migration[5.0] 2 | def change 3 | create_table :routes do |t| 4 | t.string :name 5 | t.text :description 6 | t.integer :http_method 7 | t.string :url 8 | t.json :body_schema 9 | t.json :response_schema 10 | t.references :resource, foreign_key: true 11 | 12 | t.timestamps 13 | end 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /db/migrate/20170407175225_create_query_parameters.rb: -------------------------------------------------------------------------------- 1 | class CreateQueryParameters < ActiveRecord::Migration[5.0] 2 | def change 3 | create_table :query_parameters do |t| 4 | t.string :name 5 | t.text :description 6 | t.integer :primitive_type 7 | t.boolean :is_optional, null: false, default: true 8 | t.references :route, foreign_key: true 9 | 10 | t.timestamps 11 | end 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /db/migrate/20171030155238_merge_attribute_min_max.rb: -------------------------------------------------------------------------------- 1 | class MergeAttributeMinMax < ActiveRecord::Migration[5.0] 2 | def change 3 | Attribute.find_each do |a| 4 | a.minimum = a.min_length unless a.min_length.blank? 5 | a.maximum = a.max_length unless a.max_length.blank? 6 | end 7 | 8 | remove_column :attributes, :min_length, :integer 9 | remove_column :attributes, :max_length, :integer 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /test/models/validation_error_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class ValidationErrorTest < ActiveSupport::TestCase 4 | test 'header name is the first word of description' do 5 | validation_error = build(:validation_error, 6 | category: :header, 7 | description: 'Content-Type is missing from the response headers' 8 | ) 9 | 10 | assert_equal 'Content-Type', validation_error.header_name 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /app/policies/user_policy.rb: -------------------------------------------------------------------------------- 1 | class UserPolicy < ApplicationPolicy 2 | class Scope < Scope 3 | def resolve 4 | scope.all 5 | end 6 | end 7 | 8 | def index? 9 | user&.internal? 10 | end 11 | 12 | def update? 13 | index? 14 | end 15 | 16 | def destroy? 17 | index? 18 | end 19 | 20 | def show? 21 | index? 22 | end 23 | 24 | def permitted_attributes 25 | [:internal] 26 | end 27 | end 28 | -------------------------------------------------------------------------------- /app/views/metadata/index.html.haml: -------------------------------------------------------------------------------- 1 | = content_for :title, "Metadata" 2 | 3 | - if user.can_create? Metadatum, project: project 4 | .flexcontainer.flexcontainer-justify-end 5 | = link_to 'New metadatum', new_project_metadatum_path(project), class: "btn btn-primary btn-lg" 6 | 7 | .margin-top-element 8 | - if @metadata.empty? 9 | %p= t('.no_metadata') 10 | 11 | - @metadata.each do |metadatum| 12 | = render metadatum 13 | 14 | -------------------------------------------------------------------------------- /app/views/projects/_proxy_configuration_fields.html.haml: -------------------------------------------------------------------------------- 1 | %h3 Proxy 2 | .fields.nested-fields 3 | = f.text_field :target_base_url, placeholder: 'https://api-develop.herokuapp.com' 4 | = f.text_field :proxy_hostname, placeholder: 'example.com' 5 | = f.number_field :proxy_port, placeholder: 8080 6 | = f.text_field :proxy_username, placeholder: 'username' 7 | = f.text_field :proxy_password, placeholder: 'password' 8 | = f.check_box :ignore_ssl -------------------------------------------------------------------------------- /test/factories/attributes_resource_representations.rb: -------------------------------------------------------------------------------- 1 | FactoryBot.define do 2 | 3 | factory :attributes_resource_representation do 4 | is_required false 5 | is_null false 6 | association :parent_resource_representation, factory: :resource_representation 7 | association :resource_attribute, factory: :attribute 8 | custom_key_name nil 9 | end 10 | 11 | trait :is_required do 12 | is_required true 13 | end 14 | end -------------------------------------------------------------------------------- /app/models/header.rb: -------------------------------------------------------------------------------- 1 | class Header < ApplicationRecord 2 | belongs_to :http_message, polymorphic: true 3 | belongs_to :response, foreign_key: 'http_message_id', optional: true 4 | belongs_to :route, foreign_key: 'http_message_id', optional: true 5 | 6 | validates :name, presence: true 7 | validates :http_message, presence: true 8 | 9 | audited associated_with: :http_message 10 | 11 | delegate :project, to: :http_message 12 | end 13 | -------------------------------------------------------------------------------- /db/migrate/20171115105126_add_patterns_to_mock_pickers.rb: -------------------------------------------------------------------------------- 1 | class AddPatternsToMockPickers < ActiveRecord::Migration[5.0] 2 | def change 3 | change_table :mock_pickers do |t| 4 | t.column :url_pattern, :string 5 | t.column :body_pattern, :string 6 | end 7 | 8 | remove_column :mock_pickers, :response_is_favorite, :boolean 9 | remove_index :mock_pickers, :column => [:mock_profile_id, :response_id] 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /app/assets/stylesheets/main.scss: -------------------------------------------------------------------------------- 1 | @import "variables.scss"; 2 | @import "base/globals.scss"; 3 | @import "base/sidebar.scss"; 4 | @import "base/animations.scss"; 5 | @import "styles/projects.scss"; 6 | @import "styles/resources.scss"; 7 | @import "styles/reports.scss"; 8 | @import "styles/routes.scss"; 9 | @import "styles/responses.scss"; 10 | @import "styles/mock_instances.scss"; 11 | @import "styles/mock_profiles.scss"; 12 | @import "styles/audits.scss"; 13 | -------------------------------------------------------------------------------- /db/migrate/20190928112108_add_api_gateway_integration.rb: -------------------------------------------------------------------------------- 1 | class AddApiGatewayIntegration < ActiveRecord::Migration[5.1] 2 | def up 3 | create_table :api_gateway_integrations do |t| 4 | t.string :title 5 | t.string :uri_prefix 6 | t.integer :timeout_in_millis 7 | t.references :project, foreign_key: true, index: true 8 | end 9 | end 10 | 11 | def down 12 | drop_table :api_gateway_integrations 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /config/initializers/backtrace_silencers.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces. 4 | # Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ } 5 | 6 | # You can also remove all the silencers if you're trying to debug a problem that might stem from framework code. 7 | # Rails.backtrace_cleaner.remove_silencers! 8 | -------------------------------------------------------------------------------- /db/migrate/20190926081509_change_parameters_to_jsonb_in_security_schemes.rb: -------------------------------------------------------------------------------- 1 | class ChangeParametersToJsonbInSecuritySchemes < ActiveRecord::Migration[5.1] 2 | def up 3 | remove_column :security_schemes, :parameters 4 | add_column :security_schemes, :parameters, :jsonb, default: {} 5 | end 6 | 7 | def down 8 | remove_column :security_schemes, :parameters, :jsonb 9 | add_column :security_schemes, :parameters, :string 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /proxy/lib/pericles_proxy/models/proxy_configuration.ex: -------------------------------------------------------------------------------- 1 | defmodule PericlesProxy.ProxyConfiguration do 2 | use Ecto.Schema 3 | 4 | schema "proxy_configurations" do 5 | field(:project_id, :integer) 6 | field(:target_base_url, :string) 7 | field(:proxy_hostname, :string) 8 | field(:proxy_port, :integer) 9 | field(:proxy_username, :string) 10 | field(:proxy_password, :string) 11 | field(:ignore_ssl, :boolean) 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /test/factories/security_schemes.rb: -------------------------------------------------------------------------------- 1 | FactoryBot.define do 2 | sequence :security_scheme_key do |n| 3 | "theUltimateSecurity#{n}" 4 | end 5 | 6 | factory :security_scheme do 7 | key { generate(:security_scheme_key) } 8 | security_scheme_type "apiKey" 9 | name "Authorization" 10 | security_scheme_in "header" 11 | specification_extensions "{\"x-amazon-apigateway-authtype\": \"cognito_user_pools\"}" 12 | project 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /app/views/metadata/_form.html.haml: -------------------------------------------------------------------------------- 1 | %div{style: 'min-height: 400px;'} 2 | = bootstrap_form_for(metadatum.persisted? ? metadatum : [project, metadatum]) do |f| 3 | .flexcontainer-justify-end= f.submit class: 'btn btn-primary' 4 | = render 'shared/errors', object: metadatum 5 | 6 | = f.text_field :name 7 | 8 | = f.select :primitive_type, available_types, required: true, selected: f.object.primitive_type || :string 9 | = f.check_box :nullable 10 | -------------------------------------------------------------------------------- /public/403.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | You are not authorized to perform this action (403) 5 | 6 | 12 | 13 | 14 | 15 | Unauthorized access 16 | 17 | 18 | -------------------------------------------------------------------------------- /app.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Pericles", 3 | "description": "Pericles is a tool that makes API specification easier.", 4 | "repository": "https://github.com/applidium/pericles", 5 | "keywords": ["API", "specification", "RESTful", "JSON", "JSON schema", "resource", "route"], 6 | "addons": ["heroku-postgresql", "sendgrid"], 7 | "buildpacks": [ 8 | { 9 | "url": "heroku/nodejs" 10 | }, 11 | { 12 | "url": "heroku/ruby" 13 | } 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /app/policies/project_related_policy.rb: -------------------------------------------------------------------------------- 1 | class ProjectRelatedPolicy < ApplicationPolicy 2 | [:create?, :update?, :destroy?].each do |action| 3 | define_method action do 4 | project && Pundit.policy(user, project).update? 5 | end 6 | end 7 | 8 | def show? 9 | project && Pundit.policy(user, project).show? 10 | end 11 | 12 | private 13 | 14 | def project 15 | super || (record.respond_to?(:project) ? record.project : nil) 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /app/view_models/body_error/body_error_view_model.rb: -------------------------------------------------------------------------------- 1 | module BodyError 2 | class BodyErrorViewModel 3 | attr_reader :path, :description 4 | 5 | def initialize(path, description = nil) 6 | @path = path 7 | @description = description 8 | end 9 | 10 | def readable_path 11 | path&.gsub(/\/\d+/, '') 12 | end 13 | 14 | def type 15 | :unknown 16 | end 17 | 18 | def valid? 19 | path.present? 20 | end 21 | end 22 | end -------------------------------------------------------------------------------- /app/views/code/rest.kotlin.erb: -------------------------------------------------------------------------------- 1 | package <%= android_company_domain_name =%>.<%= project.title.parameterize(separator: '.') =%>.android.data.net.retrofit.model 2 | 3 | @SuppressWarnings("ConstructorParameterNaming") 4 | data class <%= resource.rest_name =%>( 5 | <% resource.resource_attributes.each do |attribute| %> 6 | val <%= attribute.snake_variable_name =%>: <%= attribute.kotlin_type =%><%= (attribute == resource.resource_attributes.last) ? '' : ',' =%> 7 | 8 | <% end %> 9 | ) -------------------------------------------------------------------------------- /app/views/resources/_resource_instances.html.haml: -------------------------------------------------------------------------------- 1 | - if user.can_create? ResourceInstance, project: project 2 | .top 3 | %div 4 | .pull-right 5 | = link_to 'New Mock', new_resource_resource_instance_path(resource), class: "btn btn-primary" 6 | 7 | .margin-top-element 8 | - if resource.resource_instances.any? 9 | - resource.resource_instances.each do |instance| 10 | = render instance 11 | - else 12 | %p 13 | %i= t('.no_mocks_placeholder') -------------------------------------------------------------------------------- /app/views/resources/edit_attributes.html.haml: -------------------------------------------------------------------------------- 1 | = content_for :title, "Edit Resource #{resource.name}" 2 | 3 | %ol.breadcrumb 4 | %li 5 | = link_to 'Projects', projects_path 6 | %li 7 | = link_to "#{project.title}", project_path(project) 8 | %li 9 | = link_to 'Resources', project_resources_path(project) 10 | %li 11 | = link_to "#{resource.name}", project_resource_path(project, resource) 12 | %li 13 | Attributes 14 | 15 | = render 'attributes_form' -------------------------------------------------------------------------------- /db/migrate/20190304112548_add_project_id_to_audits.rb: -------------------------------------------------------------------------------- 1 | class AddProjectIdToAudits < ActiveRecord::Migration[5.1] 2 | def up 3 | add_reference :audits, :project, foreign_key: true, index: true, null: true 4 | 5 | Audited::Audit.reset_column_information 6 | Audited::Audit.find_each do |audit| 7 | audit.update(project_id: audit.auditable&.project&.id) 8 | end 9 | end 10 | 11 | def down 12 | remove_reference :audits, :project 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /app/assets/images/sort.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /app/view_models/body_error/additional_error_view_model.rb: -------------------------------------------------------------------------------- 1 | module BodyError 2 | class AdditionalErrorViewModel < BodyErrorViewModel 3 | attr_reader :additional_list 4 | 5 | def initialize(path, additional_list) 6 | super(path) 7 | @additional_list = additional_list 8 | end 9 | 10 | def description 11 | "#{path} - additional properties #{@additional_list}" 12 | end 13 | 14 | def type 15 | :additional 16 | end 17 | end 18 | end -------------------------------------------------------------------------------- /db/migrate/20190715164030_add_internal_to_users.rb: -------------------------------------------------------------------------------- 1 | class AddInternalToUsers < ActiveRecord::Migration[5.1] 2 | class User < ActiveRecord::Base 3 | end 4 | 5 | def up 6 | add_column :users, :internal, :boolean, default: false 7 | 8 | if ENV['INTERNAL_EMAIL_DOMAIN'] 9 | User.where('email LIKE ?', "%#{ENV['INTERNAL_EMAIL_DOMAIN']}").update_all(internal: true) 10 | end 11 | end 12 | 13 | def down 14 | remove_column :users, :internal 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /lib/bootstrap_form/regex.rb: -------------------------------------------------------------------------------- 1 | module BootstrapForm 2 | module RegexFormBuilder 3 | extend ActiveSupport::Concern 4 | 5 | included do 6 | bootstrap_method_alias :regex_field 7 | end 8 | 9 | def regex_field_with_bootstrap(name, options = {}) 10 | form_group_builder(name, options) do 11 | prepend_and_append_input(options) do 12 | regex_field_without_bootstrap(name, options) 13 | end 14 | end 15 | end 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /test/factories/attributes.rb: -------------------------------------------------------------------------------- 1 | FactoryBot.define do 2 | 3 | sequence :attribute_name do |n| 4 | "Attribute #{n}" 5 | end 6 | 7 | factory :attribute do 8 | name { generate(:attribute_name) } 9 | association :parent_resource, factory: :resource 10 | primitive_type :integer 11 | 12 | trait :with_resource do 13 | primitive_type nil 14 | resource 15 | end 16 | 17 | factory :attribute_with_resource, traits: [:with_resource] 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /app/views/projects/_api_gateway_integration_fields.html.haml: -------------------------------------------------------------------------------- 1 | %h3 API Gateway Integration 2 | 3 | %p If you do not use API Gateway Integration, keep following fields blank. 4 | 5 | .fields.nested-fields 6 | = f.text_field :title, placeholder: 'Title replacement or configurable title (eg: "${PROJECT_TITLE}")' 7 | = f.text_field :uri_prefix, placeholder: 'Prefix to add to each uri (ex: "http://example.com/context/" or "${PROJECT_URI}")' 8 | = f.number_field :timeout_in_millis, placeholder: 29000 -------------------------------------------------------------------------------- /app/assets/images/reset.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /app/services/json_schema_builder.rb: -------------------------------------------------------------------------------- 1 | class JSONSchemaBuilder 2 | def initialize(object, options = {}) 3 | @object = object 4 | @is_collection = options[:is_collection] 5 | @root_key = options[:root_key] 6 | @metadata_responses = options[:metadata_responses] || [] 7 | end 8 | 9 | def execute 10 | return if @object.nil? 11 | 12 | JSONSchemaWrapper.new( 13 | @object.json_schema, @root_key, @is_collection, @metadata_responses 14 | ).execute 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /bin/webpack: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | ENV["RAILS_ENV"] ||= ENV["RACK_ENV"] || "development" 4 | ENV["NODE_ENV"] ||= "development" 5 | 6 | require "pathname" 7 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 8 | Pathname.new(__FILE__).realpath) 9 | 10 | require "bundler/setup" 11 | 12 | require "webpacker" 13 | require "webpacker/webpack_runner" 14 | 15 | APP_ROOT = File.expand_path("..", __dir__) 16 | Dir.chdir(APP_ROOT) do 17 | Webpacker::WebpackRunner.run(ARGV) 18 | end 19 | -------------------------------------------------------------------------------- /app/views/users/show.html.haml: -------------------------------------------------------------------------------- 1 | = content_for :title, "User #{current_user.name}" 2 | 3 | -# br tag required otherwise navbar is over page content (cf media tag and margin-top) (Charles-Elie SIMON, 01/09/2017) 4 | %br 5 | .media 6 | .media-left 7 | %img.media-object.img-rounded{ src: "#{current_user.avatar_url}", height: "42", width: "42" } 8 | .media-body 9 | %h1.media-heading= current_user.name 10 | 11 | .row 12 | .col-xs-12 13 | %dl 14 | %dt Email 15 | %dd= current_user.email -------------------------------------------------------------------------------- /test/factories/reports.rb: -------------------------------------------------------------------------------- 1 | FactoryBot.define do 2 | 3 | sequence :url_sequence do |n| 4 | "/users/#{n}" 5 | end 6 | 7 | factory :report do 8 | url { generate(:url_sequence) } 9 | response_status_code 200 10 | response_body '{"user": {"id": 1}}' 11 | response_headers {{ 12 | 'Content-Length' => 19 13 | }} 14 | request_body '{}' 15 | request_headers {{ 16 | 'Accept-Encoding' => 'gzip' 17 | }} 18 | route 19 | project 20 | response 21 | end 22 | end -------------------------------------------------------------------------------- /bin/webpack-dev-server: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | ENV["RAILS_ENV"] ||= ENV["RACK_ENV"] || "development" 4 | ENV["NODE_ENV"] ||= "development" 5 | 6 | require "pathname" 7 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 8 | Pathname.new(__FILE__).realpath) 9 | 10 | require "bundler/setup" 11 | 12 | require "webpacker" 13 | require "webpacker/dev_server_runner" 14 | 15 | APP_ROOT = File.expand_path("..", __dir__) 16 | Dir.chdir(APP_ROOT) do 17 | Webpacker::DevServerRunner.run(ARGV) 18 | end 19 | -------------------------------------------------------------------------------- /db/migrate/20170919124934_add_root_key_to_responses.rb: -------------------------------------------------------------------------------- 1 | class Response < ApplicationRecord 2 | end 3 | 4 | class AddRootKeyToResponses < ActiveRecord::Migration[5.0] 5 | def change 6 | add_column :responses, :root_key, :string 7 | 8 | Response.find_each do |r| 9 | begin 10 | r.root_key = ActiveSupport::JSON.decode(r.body_schema).fetch('required', nil)&.first 11 | rescue JSON::ParserError 12 | r.root_key = '' 13 | end 14 | r.save 15 | end 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /public/404.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | The page you were looking for doesn't exist (404) 5 | 6 | 12 | 13 | 14 | 15 | 16 | John is confused 17 | 18 | 19 | -------------------------------------------------------------------------------- /app/views/resources/index.html.haml: -------------------------------------------------------------------------------- 1 | = content_for :title, "Resources" 2 | 3 | - content_for :page_scripts do 4 | = javascript_pack_tag("resources/index.js") 5 | 6 | %ol.breadcrumb 7 | %li 8 | = link_to 'Projects', projects_path 9 | %li 10 | = link_to "#{project.title}", project_path(project) 11 | %li 12 | Resources 13 | 14 | #resources 15 | %ps-resources{':resources': 'displayedResources', ':tree-mode': 'treeMode', ':query': 'query'} 16 | 17 | %ps-unused-resources{':resources': 'unusedResources'} -------------------------------------------------------------------------------- /app/decorators/authorization.rb: -------------------------------------------------------------------------------- 1 | module Authorization 2 | extend ActiveSupport::Concern 3 | 4 | def can_create?(record_class, options = {}) 5 | Pundit.policy(UserContext.new(object, options[:project]), record_class).create? 6 | end 7 | 8 | def can_edit?(record) 9 | Pundit.policy(object, record).edit? 10 | end 11 | 12 | def can_update?(record) 13 | Pundit.policy(object, record).update? 14 | end 15 | 16 | def can_delete?(record) 17 | Pundit.policy(object, record).destroy? 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /app/decorators/resource_instance_decorator.rb: -------------------------------------------------------------------------------- 1 | class ResourceInstanceDecorator < Draper::Decorator 2 | delegate_all 3 | 4 | def body_errors_by_representations 5 | object.errors[:instance].each_with_index.reduce({}) do |hash, (errors, i)| 6 | representation = object.parent.resource_representations[i] 7 | body_errors = errors.split("\n").map { |e| BodyError::BodyErrorViewModel.new(e) } 8 | 9 | hash.merge({ representation => BodyError::ViewModels.new(*body_errors) }) 10 | end 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /app/views/routes/_request_query_parameter_fields.html.haml: -------------------------------------------------------------------------------- 1 | %tr.fields.nested-fields 2 | %td 3 | = f.text_field :name, hide_label: true, placeholder: t('.name_placeholder') 4 | %td 5 | = f.select :primitive_type, QueryParameter.primitive_types.keys.to_a, include_blank: true, hide_label: true 6 | %td 7 | = f.check_box :is_optional, hide_label: true 8 | %td 9 | = f.text_area :description, hide_label: true, placeholder: t('.description_placeholder') 10 | %td 11 | = link_to_remove_association "Remove", f -------------------------------------------------------------------------------- /db/migrate/20171030094823_remove_custom_fields_from_resource_representation.rb: -------------------------------------------------------------------------------- 1 | class RemoveCustomFieldsFromResourceRepresentation < ActiveRecord::Migration[5.0] 2 | def change 3 | remove_column :attributes_resource_representations, :custom_enum, :string 4 | remove_column :attributes_resource_representations, :custom_pattern, :string 5 | remove_column :attributes_resource_representations, :custom_nullable, :boolean 6 | remove_column :attributes_resource_representations, :custom_faker_id, :boolean 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /db/migrate/20180223163412_drop_attribute_fakers.rb: -------------------------------------------------------------------------------- 1 | class DropAttributeFakers < ActiveRecord::Migration[5.1] 2 | def up 3 | remove_reference :attributes, :faker, foreign_key: {to_table: :attribute_fakers}, index: true 4 | 5 | drop_table :attribute_fakers 6 | end 7 | 8 | def down 9 | create_table :attribute_fakers do |t| 10 | t.string :name 11 | 12 | t.timestamps 13 | end 14 | 15 | add_reference :attributes, :faker, foreign_key: {to_table: :attribute_fakers}, index: true 16 | end 17 | end -------------------------------------------------------------------------------- /test/models/header_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class HeaderTest < ActiveSupport::TestCase 4 | test "shouldn't exist without a name" do 5 | assert_not build(:header, name: nil).valid? 6 | end 7 | 8 | test "shouldn't exist without a http_message" do 9 | assert_not build(:header, http_message: nil).valid? 10 | end 11 | 12 | test 'Header should be valid with all attributes set correctly' do 13 | assert build(:header, name: 'Content-Type', value: 'application/json').valid? 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /app/assets/javascripts/generate_instance.js: -------------------------------------------------------------------------------- 1 | function generateJsonInstance(jsonSchema, callback) { 2 | var schema = JSON.parse(jsonSchema); 3 | var data = { 4 | schema: schema 5 | }; 6 | $.ajax({ 7 | type: "POST", 8 | url: "/instances", 9 | data: JSON.stringify(data), 10 | contentType: "application/json", 11 | dataType: "json" 12 | }) 13 | .done(function(data) { 14 | callback(data); 15 | }) 16 | .fail(function(data) { 17 | console.log(data); 18 | }); 19 | } 20 | -------------------------------------------------------------------------------- /app/serializers/attribute_serializer.rb: -------------------------------------------------------------------------------- 1 | class AttributeSerializer < ActiveModel::Serializer 2 | attributes :id, :name, :description, :is_array, :primitive_type, 3 | :resource_id, :enum, :minimum, :maximum, :nullable, :scheme, 4 | :min_items, :max_items, :readable_type 5 | 6 | has_many :available_resource_representations 7 | 8 | def readable_type 9 | object.decorate.readable_type 10 | end 11 | 12 | def available_resource_representations 13 | object.resource&.resource_representations 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /db/migrate/20171115165949_rename_mock_instance_to_resource_instance.rb: -------------------------------------------------------------------------------- 1 | class RenameMockInstanceToResourceInstance < ActiveRecord::Migration[5.0] 2 | def change 3 | rename_table :mock_instances, :resource_instances 4 | rename_table :mock_instances_pickers, :mock_pickers_resource_instances 5 | rename_column :mock_pickers_resource_instances, :mock_instance_id, :resource_instance_id 6 | 7 | remove_column :responses, :mock_instance_id, :integer 8 | remove_column :mock_pickers, :mock_instance_id 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /test/helpers/validations_helper_test.rb: -------------------------------------------------------------------------------- 1 | class ValidationsHelperTest < ActionView::TestCase 2 | test 'format_json_text should return a pretty json if text is valid json' do 3 | json = '{}' 4 | parsed_json = JSON.parse(json) 5 | expected = JSON.stable_pretty_generate(parsed_json) 6 | assert_equal expected, format_json_text(json) 7 | end 8 | 9 | test 'format_json_text should return the input text if not valid json' do 10 | text = '{ abcdefg }' 11 | assert_equal text, format_json_text(text) 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /bin/spring: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | # This file loads spring without using Bundler, in order to be fast. 4 | # It gets overwritten when you run the `spring binstub` command. 5 | 6 | unless defined?(Spring) 7 | require "rubygems" 8 | require "bundler" 9 | 10 | match = Bundler.default_lockfile.read.match(/^GEM$.*?^ (?: )*spring \((.*?)\)$.*?^$/m) 11 | if match 12 | Gem.paths = { "GEM_PATH" => [Bundler.bundle_path.to_s, *Gem.path].uniq } 13 | gem "spring", match[1] 14 | require "spring/binstub" 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /app/view_models/body_error/enum_error_view_model.rb: -------------------------------------------------------------------------------- 1 | module BodyError 2 | class EnumErrorViewModel < BodyErrorViewModel 3 | attr_reader :current_value, :target_values 4 | 5 | def initialize(path, current_value, target_values) 6 | super(path) 7 | @current_value = current_value 8 | @target_values = target_values 9 | end 10 | 11 | def description 12 | "#{path} value is #{current_value} and should be #{target_values}" 13 | end 14 | 15 | def type 16 | :enum 17 | end 18 | end 19 | end 20 | 21 | -------------------------------------------------------------------------------- /config/webpack/environment.js: -------------------------------------------------------------------------------- 1 | const { environment } = require('@rails/webpacker') 2 | const { VueLoaderPlugin } = require('vue-loader') 3 | 4 | const vue = require('./loaders/vue') 5 | const vueSvgLoader = require('./loaders/vue-svg-loader') 6 | const pug = require('./loaders/pug') 7 | 8 | environment.plugins.append('VueLoaderPlugin', new VueLoaderPlugin()) 9 | environment.loaders.append('vue', vue) 10 | environment.loaders.append('vue-svg-loader', vueSvgLoader) 11 | environment.loaders.append('pug', pug) 12 | 13 | module.exports = environment 14 | -------------------------------------------------------------------------------- /app/views/shared/_head.html.haml: -------------------------------------------------------------------------------- 1 | %meta{:content => "text/html; charset=UTF-8", "http-equiv" => "Content-Type"}/ 2 | %title= "Pericles - " + yield(:title) 3 | = stylesheet_link_tag 'application', media: 'all' 4 | %link{href: "https://fonts.googleapis.com/css?family=Open+Sans:400,600", rel: "stylesheet"} 5 | %link{rel: "stylesheet", href: "//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/default.min.css"} 6 | %script{src: "//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/highlight.min.js"} 7 | = javascript_include_tag 'application' 8 | = csrf_meta_tags -------------------------------------------------------------------------------- /db/migrate/20171226152120_add_key_name_to_attributes_resource_representation.rb: -------------------------------------------------------------------------------- 1 | class AddKeyNameToAttributesResourceRepresentation < ActiveRecord::Migration[5.0] 2 | def change 3 | add_column :attributes_resource_representations, :key_name, :string 4 | 5 | AttributesResourceRepresentation.find_each do |attributes_resource_representation| 6 | attributes_resource_representation.key_name = attributes_resource_representation.resource_attribute.default_key_name 7 | attributes_resource_representation.save 8 | end 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /test/factories/users.rb: -------------------------------------------------------------------------------- 1 | FactoryBot.define do 2 | 3 | sequence :email do |n| 4 | "person#{n}#{User::INTERNAL_EMAIL_DOMAIN}" 5 | end 6 | 7 | sequence :external_email do |n| 8 | "person#{n}@external.com" 9 | end 10 | 11 | factory :user do 12 | email { generate(:email) } 13 | password Devise.friendly_token[0,20] 14 | first_name 'John' 15 | last_name 'Smith' 16 | 17 | trait :external do 18 | email { generate(:external_email) } 19 | end 20 | 21 | after(:create) { |user| user.confirm } 22 | end 23 | end 24 | -------------------------------------------------------------------------------- /app/controllers/validations_controller.rb: -------------------------------------------------------------------------------- 1 | class ValidationsController < ApplicationController 2 | def index 3 | @validations = Validation.order(created_at: 'desc').page(params[:page]).per(10) 4 | end 5 | 6 | def new 7 | @default_json_instance = '{}' 8 | end 9 | 10 | def create 11 | validation = Validation.create(validation_params) 12 | render json: validation, status: :created 13 | end 14 | 15 | private 16 | 17 | def validation_params 18 | params.require(:validation).permit(:json_schema, :json_instance) 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /db/migrate/20170919080631_create_fakers.rb: -------------------------------------------------------------------------------- 1 | class CreateFakers < ActiveRecord::Migration[5.0] 2 | def change 3 | create_table :fakers do |t| 4 | t.string :name 5 | 6 | t.timestamps 7 | end 8 | 9 | add_reference :attributes, :faker, foreign_key: true 10 | add_column :attributes_resource_representations, :custom_faker_id, :integer, index: true 11 | add_foreign_key :attributes_resource_representations, :fakers, column: :custom_faker_id 12 | remove_column :attributes_resource_representations, :faker, :string 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /app/controllers/audits_controller.rb: -------------------------------------------------------------------------------- 1 | class AuditsController < ApplicationController 2 | include Authenticated 3 | include ProjectRelated 4 | 5 | def index 6 | @audits = AuditsRepository.new 7 | .news_of_project(project) 8 | .page(params[:page]).per(200) 9 | end 10 | 11 | def slack_post 12 | news_posted_count = PostSlackNews.new(project).execute 13 | redirect_to project_audits_path(project), notice: t('.news_posted_on', news_posted_count: news_posted_count, slack_channel: project.slack_channel) 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /app/decorators/code/attribute_decorator.rb: -------------------------------------------------------------------------------- 1 | class Code::AttributeDecorator < Draper::Decorator 2 | include Code::Field 3 | delegate_all 4 | decorates_association :resource, with: Code::ResourceDecorator 5 | 6 | def code_nullable 7 | @code_nullable ||= object.nullable || parent_resource.resource_representations.any? { |rep| rep.attributes_resource_representations.none? { |a| a.attribute_id == id } } 8 | end 9 | 10 | def graphql_nullable 11 | object.nullable 12 | end 13 | 14 | def key_name 15 | object.default_key_name 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /app/models/metadatum.rb: -------------------------------------------------------------------------------- 1 | class Metadatum < ApplicationRecord 2 | include HasPrimitiveType 3 | 4 | belongs_to :project, required: true 5 | 6 | has_many :metadata_responses, dependent: :destroy 7 | has_many :responses, through: :metadata_responses 8 | has_many :metadatum_instances 9 | 10 | validates :name, presence: true, uniqueness: { scope: :project, case_sensitive: true } 11 | validates :primitive_type, presence: true 12 | 13 | audited 14 | 15 | def json_schema 16 | JSONSchema::MetadatumDecorator.new(self).json_schema 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /config/initializers/audited.rb: -------------------------------------------------------------------------------- 1 | module Audited 2 | class Audit < ::ActiveRecord::Base 3 | belongs_to :project, optional: true 4 | 5 | scope :of_project, ->(project) { where(project: project) } 6 | 7 | before_create :set_project_id 8 | 9 | def decorator_class 10 | "News::#{auditable_type}AuditDecorator".constantize 11 | rescue NameError 12 | News::AuditDecorator 13 | end 14 | 15 | private 16 | 17 | def set_project_id 18 | self.project_id ||= auditable&.project&.id 19 | true 20 | end 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /db/migrate/20170310132514_create_attributes.rb: -------------------------------------------------------------------------------- 1 | class CreateAttributes < ActiveRecord::Migration[5.0] 2 | def change 3 | create_table :attributes do |t| 4 | t.string :name 5 | t.text :description 6 | t.json :example 7 | t.integer :parent_resource_id 8 | t.boolean :is_array, null: false, default: false 9 | t.integer :primitive_type 10 | t.references :resource, foreign_key: true 11 | 12 | t.timestamps 13 | end 14 | 15 | add_foreign_key :attributes, :resources, column: :parent_resource_id 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /app/javascript/packs/resources/ps-unused-resources.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 21 | 22 | 24 | -------------------------------------------------------------------------------- /app/decorators/http/response_decorator.rb: -------------------------------------------------------------------------------- 1 | class HTTP::ResponseDecorator < Draper::Decorator 2 | delegate_all 3 | 4 | def body 5 | content = object.body.to_s 6 | return content if content.empty? 7 | 8 | case object.headers[:content_encoding] 9 | # NOTE: Clément Villain 28/12/17 10 | # 'deflate' seems to be a nightmare because of different implementations 11 | # and seems to not be used by webserver 12 | when 'gzip' 13 | Zlib::GzipReader.new(StringIO.new(content)).read 14 | else 15 | object.body 16 | end 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /app/views/code/serializer.ruby.erb: -------------------------------------------------------------------------------- 1 | class <%= resource.pascal_name %>Serializer < ActiveModel::Serializer 2 | attributes( 3 | <% resource.resource_attributes.select(&:primitive_type).each do |attribute| %> 4 | :<%= attribute.snake_variable_name %>, 5 | <% end %> 6 | ) 7 | 8 | <% resource.resource_attributes.reject(&:primitive_type).sort_by { |a| a.is_array ? 0 : 1 }.each do |attribute| %> 9 | <%= attribute.is_array ? 'has_many' : 'belongs_to' %> :<%= attribute.snake_variable_name %>, serializer: <%= attribute.resource.pascal_name %>Serializer 10 | <% end %> 11 | end 12 | -------------------------------------------------------------------------------- /app/views/metadatum_instances/_metadatum_instance.html.haml: -------------------------------------------------------------------------------- 1 | .flexspace-and-center 2 | .flex 3 | = metadatum_instance.name 4 | .flex{class: ('invalid-instance' unless metadatum_instance.valid?)} 5 | = metadatum_instance.body 6 | %flexcontainer 7 | = link_to 'Delete', polymorphic_path(metadatum_instance), method: :delete, data: { confirm: 'Are you sure?' }, class: "btn btn-default h-margin" if user.can_delete? metadatum_instance 8 | = link_to 'Edit', edit_polymorphic_path(metadatum_instance), class: "btn btn-primary" if user.can_edit? metadatum_instance 9 | 10 | -------------------------------------------------------------------------------- /config/initializers/wrap_parameters.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # This file contains settings for ActionController::ParamsWrapper which 4 | # is enabled by default. 5 | 6 | # Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array. 7 | ActiveSupport.on_load(:action_controller) do 8 | wrap_parameters format: [:json] 9 | end 10 | 11 | # To enable root element in JSON for ActiveRecord objects. 12 | # ActiveSupport.on_load(:active_record) do 13 | # self.include_root_in_json = true 14 | # end 15 | -------------------------------------------------------------------------------- /app/javascript/packs/application.js: -------------------------------------------------------------------------------- 1 | /* eslint no-console:0 */ 2 | // This file is automatically compiled by Webpack, along with any other files 3 | // present in this directory. You're encouraged to place your actual application logic in 4 | // a relevant structure within app/javascript and only use these pack files to reference 5 | // that code so it'll be compiled. 6 | // 7 | // To reference this file, add <%= javascript_pack_tag 'application' %> to the appropriate 8 | // layout file, like app/views/layouts/application.html.erb 9 | 10 | console.log('Hello World from Webpacker') 11 | -------------------------------------------------------------------------------- /db/seeds.rb: -------------------------------------------------------------------------------- 1 | # This file should contain all the record creation needed to seed the database with its default values. 2 | # The data can then be loaded with the rake db:seed (or created alongside the db with db:setup). 3 | # 4 | # Examples: 5 | # 6 | # cities = City.create([{ name: 'Chicago' }, { name: 'Copenhagen' }]) 7 | # Mayor.create(name: 'Emanuel', city: cities.first) 8 | 9 | Scheme.create(name: 'date-time') 10 | Scheme.create(name: 'email') 11 | Scheme.create(name: 'hostname') 12 | Scheme.create(name: 'ipv4') 13 | Scheme.create(name: 'ipv6') 14 | Scheme.create(name: 'uri') 15 | -------------------------------------------------------------------------------- /app/decorators/json_schema/attribute_decorator.rb: -------------------------------------------------------------------------------- 1 | module JSONSchema 2 | class AttributeDecorator < Draper::Decorator 3 | delegate_all 4 | 5 | def primitive_type 6 | if datetime? || date? 7 | 'string' 8 | elsif object.any? 9 | %w[string number integer boolean null array object] 10 | else 11 | object.primitive_type 12 | end 13 | end 14 | 15 | def scheme 16 | return Scheme.new(name: 'datetime') if datetime? 17 | return Scheme.new(name: 'date') if date? 18 | object.scheme 19 | end 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /app/services/generate_json_instance_service.rb: -------------------------------------------------------------------------------- 1 | class GenerateJsonInstanceService 2 | def initialize(schema) 3 | @schema = schema.is_a?(String) ? JSON.parse(schema) : schema 4 | end 5 | 6 | def execute 7 | return '' if @schema.nil? 8 | 9 | js_file = File.join(Rails.root, 'lib', 'node', 'generate_mock.js') 10 | thread = Thread.new do 11 | JSON.parse(Terrapin::CommandLine.new('node', ':js :schema').run(js: js_file, schema: @schema.to_json)) 12 | end 13 | thread.join(5)&.value || { error: 'A loop prevents this json to be generated' } 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /app/views/security_schemes/index.html.haml: -------------------------------------------------------------------------------- 1 | = content_for :title, "Security Schemes" 2 | - content_for :page_scripts do 3 | = javascript_pack_tag("common/markdown.js") 4 | 5 | .flexspace-and-center 6 | %h1 Security Schemes 7 | = link_to 'New Security Scheme', new_project_security_scheme_path(project), class: "btn btn-primary btn-lg" if user.can_create? Route, project: project 8 | 9 | .margin-top-element 10 | - if @project.security_schemes.empty? 11 | %p= t('.no_security_scheme') 12 | - @project.security_schemes.each do |security_scheme| 13 | = render security_scheme 14 | -------------------------------------------------------------------------------- /config/database.yml: -------------------------------------------------------------------------------- 1 | # SQLite version 3.x 2 | # gem install sqlite3 3 | # 4 | # Ensure the SQLite 3 gem is defined in your Gemfile 5 | # gem 'sqlite3' 6 | # 7 | development: 8 | adapter: postgresql 9 | database: Pericles_GW_dev 10 | pool: 5 11 | timeout: 5000 12 | 13 | # Warning: The database defined as "test" will be erased and 14 | # re-generated from your development database when you run "rake". 15 | # Do not set this db to the same as development or production. 16 | test: 17 | adapter: postgresql 18 | database: Pericles_GW_test 19 | pool: 5 20 | timeout: 5000 21 | -------------------------------------------------------------------------------- /config/initializers/mime_types.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Add new mime types for use in respond_to blocks: 4 | # Mime::Type.register "text/richtext", :rtf 5 | Mime::Type.register "text/markdown", :md 6 | Mime::Type.register "application/schema+json", :json_schema 7 | Mime::Type.register "text/plain", :kotlin 8 | Mime::Type.register "text/plain", :swift 9 | Mime::Type.register "text/plain", :ruby 10 | Mime::Type.register "text/plain", :typescript 11 | Mime::Type.register "text/plain", :graphql 12 | Mime::Type.register "application/x-yaml", :swagger 13 | -------------------------------------------------------------------------------- /app/helpers/sidebar_helper.rb: -------------------------------------------------------------------------------- 1 | module SidebarHelper 2 | def active_class(controller_class) 3 | controller_class == controller.class ? 'active' : '' 4 | end 5 | 6 | def push_class(pusher) 7 | should_add_push_class = ( 8 | (pusher == 'Schemes' && (controller.class == ProjectsController || controller.class.included_modules.include?(ProjectRelated))) || 9 | (pusher == 'JSON Validation' && (controller.class == SchemesController)) || 10 | (pusher == 'Logout' && (controller.class == ValidationsController)) 11 | ) 12 | should_add_push_class ? 'push' : '' 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /app/helpers/validations_helper.rb: -------------------------------------------------------------------------------- 1 | module ValidationsHelper 2 | def validation_string_for_status(status) 3 | t("activerecord.attributes.validation.status.#{status}") 4 | end 5 | 6 | def format_json_text(text) 7 | parsed_json = JSON.parse(text) 8 | JSON.stable_pretty_generate(parsed_json) 9 | rescue JSON::ParserError 10 | text 11 | end 12 | 13 | def self.parse_json_text(text) 14 | if text.is_a? String 15 | begin 16 | JSON.parse(text) 17 | rescue JSON::ParserError 18 | text 19 | end 20 | else 21 | text 22 | end 23 | end 24 | end 25 | -------------------------------------------------------------------------------- /app/services/abstract_zip_builder.rb: -------------------------------------------------------------------------------- 1 | require 'zip' 2 | 3 | class AbstractZipBuilder 4 | def collection 5 | raise 'implement me!' 6 | end 7 | 8 | def filename(_object) 9 | raise 'implement me!' 10 | end 11 | 12 | def file_content(_object) 13 | raise 'implement me!' 14 | end 15 | 16 | def zip_data 17 | stringio = Zip::OutputStream.write_buffer do |zio| 18 | collection.each do |object| 19 | zio.put_next_entry(filename(object)) 20 | zio.write file_content(object) 21 | end 22 | end 23 | stringio.rewind 24 | stringio.sysread 25 | end 26 | end 27 | -------------------------------------------------------------------------------- /app/javascript/packs/resources/index.js: -------------------------------------------------------------------------------- 1 | import 'core-js/fn/promise/finally'; 2 | 3 | import Vue from 'vue/dist/vue.esm' 4 | 5 | import Store from './store.js'; 6 | import ResourcesComponent from './ps-resources.vue'; 7 | import UnsedResourcesComponent from './ps-unused-resources.vue'; 8 | 9 | 10 | document.addEventListener('DOMContentLoaded', () => { 11 | const app = new Vue({ 12 | el: '#resources', 13 | data: Store.state, 14 | components: { 15 | 'ps-resources': ResourcesComponent, 16 | 'ps-unused-resources': UnsedResourcesComponent 17 | } 18 | }); 19 | 20 | Store.init(); 21 | }); -------------------------------------------------------------------------------- /app/validators/json_object_validator.rb: -------------------------------------------------------------------------------- 1 | 2 | class JsonObjectValidator < ActiveModel::EachValidator 3 | def validate_each(record, attribute, value) 4 | if value.blank? 5 | record.errors.add(attribute, :json_object_cannot_be_blank) 6 | return 7 | end 8 | 9 | begin 10 | parsed_json = JSON.parse(value) 11 | rescue JSON::ParserError 12 | record.errors.add(attribute, :could_not_parse_json) 13 | return 14 | end 15 | 16 | unless parsed_json.is_a? Hash 17 | record.errors.add(attribute, :json_must_be_an_object) 18 | return 19 | end 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /app/validators/json_schema_validator.rb: -------------------------------------------------------------------------------- 1 | class JsonSchemaValidator < ActiveModel::EachValidator 2 | def validate_each(record, attribute, value) 3 | return unless value 4 | begin 5 | JSON::Validator.validate!(META_SCHEMA, value, json: true) 6 | rescue JSON::Schema::JsonParseError, JSON::Schema::ValidationError => e 7 | record.errors.add(attribute, :schema_must_be_valid_json) if e.class == JSON::Schema::JsonParseError 8 | record.errors.add(attribute, :schema_must_respect_json_schema_spec, { error: e.message }) if e.class == JSON::Schema::ValidationError 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /test/lib/tasks/proxy_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class CleanOldReportsTest < ActiveSupport::TestCase 4 | def setup 5 | @new_report = create(:report) 6 | travel_to Date.current - 1.month 7 | @old_report = create(:report) 8 | travel_back 9 | Pericles_GWGw::Application.load_tasks 10 | Rake::Task['proxy:clean_reports'].execute 11 | end 12 | 13 | test 'new report is not deleted' do 14 | assert_equal @new_report, Report.find_by(id: @new_report.id) 15 | end 16 | 17 | test 'old report is deleted' do 18 | assert_nil Report.find_by(id: @old_report.id) 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /db/migrate/20190912182400_create_security_schemes.rb: -------------------------------------------------------------------------------- 1 | class CreateSecuritySchemes < ActiveRecord::Migration[5.1] 2 | def up 3 | create_table :security_schemes do |t| 4 | t.string :key 5 | t.string :security_scheme_type 6 | t.string :name 7 | t.string :security_scheme_in 8 | t.text :parameters 9 | t.references :project, foreign_key: true 10 | end 11 | 12 | add_reference :routes, :security_scheme, references: :security_schemes 13 | end 14 | 15 | def down 16 | remove_reference :routes, :security_scheme 17 | 18 | drop_table :security_schemes 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /proxy/lib/pericles_proxy.ex: -------------------------------------------------------------------------------- 1 | defmodule PericlesProxy do 2 | @moduledoc """ 3 | Documentation for PericlesProxy. 4 | """ 5 | 6 | use Application 7 | require Logger 8 | 9 | def start(_type, _args) do 10 | children = [ 11 | { 12 | Plug.Adapters.Cowboy2, 13 | scheme: :http, 14 | plug: PericlesProxy.Router, 15 | options: [port: String.to_integer(System.get_env("PORT") || "8080")] 16 | }, 17 | PericlesProxy.Repo 18 | ] 19 | 20 | Logger.info("Started application") 21 | 22 | Supervisor.start_link(children, strategy: :one_for_one) 23 | end 24 | end 25 | -------------------------------------------------------------------------------- /app/views/projects/index.html.haml: -------------------------------------------------------------------------------- 1 | = content_for :title, "Projects" 2 | 3 | - if user.can_create? Project 4 | .row.margin-top-element 5 | .col-xs-12.flexcontainer.flexcontainer-justify-end 6 | = link_to 'New Project', new_project_path, class: "btn btn-primary btn-lg" 7 | .row.margin-top-element 8 | .col-xs-12 9 | .list-group 10 | - @projects.each do |project| 11 | %a{class: "list-group-item", href: project_path(project)} 12 | = project.title 13 | - if current_user.nil? 14 | %p= t('.visitor_see_only_public', href: link_to(t('actions.sign_in'), new_user_session_path)).html_safe 15 | -------------------------------------------------------------------------------- /app/views/instances/_instance.html.haml: -------------------------------------------------------------------------------- 1 | .row 2 | .col-xs-6 3 | %div 4 | %strong= instance.name 5 | %pre 6 | %code.mock_instance_text_area{disabled: 'true', class: ('invalid-instance' unless instance.valid?)}=format_json(instance.body) 7 | .col-xs-6 8 | .flexcontainer.flexcontainer-justify-end 9 | .btn-group{ role: "group" } 10 | = link_to 'Edit', edit_polymorphic_path(instance), class: "btn btn-primary" if user.can_edit? instance 11 | = link_to 'Delete', polymorphic_path(instance), method: :delete, data: { confirm: 'Are you sure?' }, class: "btn btn-primary" if user.can_delete? instance 12 | -------------------------------------------------------------------------------- /app/decorators/report_decorator.rb: -------------------------------------------------------------------------------- 1 | class ReportDecorator < Draper::Decorator 2 | delegate_all 3 | 4 | def body_errors 5 | factory = BodyError::ViewModelFactory.new 6 | body_error_view_models = object.body_errors.map do |e| 7 | e.description.split("\n") 8 | end.flatten.map do |description| 9 | factory.build(description) 10 | end 11 | BodyError::ViewModels.new(*body_error_view_models) 12 | end 13 | 14 | def tr_class 15 | return 'in_validation' unless object.validated? 16 | return 'missing' if object.route.blank? || object.response.blank? 17 | object.correct? ? '' : 'invalid' 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /app/policies/mock_profile_policy.rb: -------------------------------------------------------------------------------- 1 | class MockProfilePolicy < ProjectRelatedPolicy 2 | def edit? 3 | show? 4 | end 5 | 6 | def permitted_attributes 7 | [ 8 | :name, 9 | :parent_id, 10 | mock_pickers_attributes: [ 11 | :id, 12 | :body_pattern, 13 | :url_pattern, 14 | :resource_instance_ids, 15 | :api_error_instance_ids, 16 | :response_id, 17 | :instances_number, 18 | :priority, 19 | :_destroy, 20 | resource_instance_ids: [], 21 | api_error_instance_ids: [], 22 | metadatum_instance_ids: [] 23 | ] 24 | ] 25 | end 26 | end 27 | -------------------------------------------------------------------------------- /app/views/api_errors/_new_form.html.haml: -------------------------------------------------------------------------------- 1 | = bootstrap_form_for([project, api_error]) do |f| 2 | .flexcontainer-justify-end= f.submit class: 'btn btn-primary' 3 | 4 | = f.text_field :name 5 | 6 | = f.text_area :json_schema, class: 'json' 7 | 8 | .alert.alert-warning= t('.json_instance_explanation') 9 | 10 | .form-group{class: @json_instance_error.blank? ? '' : 'has-error'} 11 | %label.control-label From JSON (BETA) 12 | = text_area_tag(:json_instance, @json_instance, class: 'form-control json', placeholder: format_json({code: 1, message: 'Error'}.to_json)) 13 | - unless @json_instance_error.blank? 14 | %span.help-block= @json_instance_error 15 | -------------------------------------------------------------------------------- /test/models/api_error_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class AttributeTest < ActiveSupport::TestCase 4 | test 'must have a valid json schema' do 5 | assert_not build(:api_error, json_schema: '').valid? 6 | assert_not build(:api_error, json_schema: '{{').valid? 7 | assert_not build(:api_error, json_schema: '{"id": 1}').valid? 8 | 9 | assert build(:api_error, json_schema: '{}').valid? 10 | end 11 | 12 | test 'destroy should delete instances' do 13 | api_error_instance = create(:api_error_instance) 14 | 15 | assert_difference 'ApiErrorInstance.count', -1 do 16 | api_error_instance.api_error.destroy 17 | end 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /app/views/metadata/_metadatum.html.haml: -------------------------------------------------------------------------------- 1 | .flexspace-and-center 2 | %dl.flex 3 | %dt Name 4 | %dd 5 | %strong= metadatum.name 6 | %dl.flex 7 | %dt Type 8 | %dd 9 | %strong= metadatum.primitive_type 10 | .btn-group{ role: "group" } 11 | = link_to 'Show mocks', project_metadatum_path(project, metadatum), class: 'btn btn-primary' if !local_assigns.key? :show || local_assigns[:show] 12 | = link_to 'Edit', edit_metadatum_path(metadatum), class: 'btn btn-primary' if user.can_edit? metadatum 13 | = link_to 'Delete', metadatum_path(metadatum), method: :delete, data: { confirm: 'Are you sure?' }, class: 'btn btn-primary' if user.can_delete? metadatum -------------------------------------------------------------------------------- /app/decorators/json_schema/metadatum_decorator.rb: -------------------------------------------------------------------------------- 1 | module JSONSchema 2 | class MetadatumDecorator < Draper::Decorator 3 | delegate_all 4 | 5 | def json_schema 6 | non_nullable_property = (datetime? || date?) ? { type: :string, format: primitive_type } : { type: primitive_type } 7 | if nullable 8 | if should_use_nullable 9 | non_nullable_property.merge(nullable: true) 10 | else 11 | { anyOf: [non_nullable_property, { type: 'null' }] } 12 | end 13 | else 14 | non_nullable_property 15 | end 16 | end 17 | 18 | def should_use_nullable 19 | context[:use_nullable] 20 | end 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /config/locales/fr.yml: -------------------------------------------------------------------------------- 1 | fr: 2 | required: Requis 3 | optional: Optionnel 4 | actions: 5 | edit: Éditer 6 | download: Télécharger 7 | delete: Supprimer 8 | sign_in: S'identifier 9 | mailer: 10 | confirmation_grettings: "Bienvenue %{email} !" 11 | confirmation_instructions: 'Vous pouvez confirmer votre compte en cliquant sur le lien ci-dessous:' 12 | confirmation_action: Confirmer mon compte 13 | errors: 14 | messages: 15 | taken: "%{value} n'est pas disponible" 16 | could_not_parse_json: Impossible de parser le JSON 17 | json_object_cannot_be_blank: Un JSON ne peut pas être vide 18 | json_must_be_an_object: Ce JSON doit être un objet -------------------------------------------------------------------------------- /db/migrate/20170602161118_create_attributes_resource_representations.rb: -------------------------------------------------------------------------------- 1 | class CreateAttributesResourceRepresentations < ActiveRecord::Migration[5.0] 2 | def change 3 | create_table :attributes_resource_representations do |t| 4 | t.boolean :is_required, null: false, default: false 5 | t.string :custom_enum 6 | t.string :custom_pattern 7 | t.references :resource_representation, foreign_key: true, index: false 8 | t.references :attribute, foreign_key: true 9 | 10 | t.timestamps 11 | end 12 | 13 | add_index :attributes_resource_representations, :resource_representation_id, name: 'index_arr_on_resource_representation_id' 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /proxy/app.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Pericles Proxy", 3 | "description": "Proxy for Pericles, a tool that makes API specification easier.", 4 | "repository": "https://github.com/applidium/pericles/proxy", 5 | "keywords": ["API", "specification", "RESTful", "JSON", "JSON schema", "resource", "route"], 6 | "env": { 7 | "PROJECT_PATH": { 8 | "description": "Required by subdir-heroku-buildpack", 9 | "value": "/proxy" 10 | } 11 | }, 12 | "buildpacks": [ 13 | { 14 | "url": "https://github.com/timanovsky/subdir-heroku-buildpack" 15 | }, 16 | { 17 | "url": "https://github.com/HashNuke/heroku-buildpack-elixir.git" 18 | } 19 | ] 20 | } 21 | 22 | -------------------------------------------------------------------------------- /test/models/metadata_response_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class MetadataResponseTest < ActiveSupport::TestCase 4 | test "shouldn't exist without a metadatum" do 5 | assert_not build(:metadata_response, metadatum: nil).valid? 6 | end 7 | 8 | test "shouldn't exist without a response" do 9 | assert_not build(:metadata_response, response: nil).valid? 10 | end 11 | 12 | test 'couple metadatum/response should be unique' do 13 | metadata_response = create(:metadata_response) 14 | 15 | assert_not build(:metadata_response, 16 | metadatum: metadata_response.metadatum, 17 | response: metadata_response.response 18 | ).valid? 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /proxy/.gitignore: -------------------------------------------------------------------------------- 1 | # The directory Mix will write compiled artifacts to. 2 | /_build/ 3 | 4 | # If you run "mix test --cover", coverage assets end up here. 5 | /cover/ 6 | 7 | # The directory Mix downloads your dependencies sources to. 8 | /deps/ 9 | 10 | # Where 3rd-party dependencies like ExDoc output generated docs. 11 | /doc/ 12 | 13 | # Ignore .fetch files in case you like to edit your project deps locally. 14 | /.fetch 15 | 16 | # If the VM crashes, it generates a dump, let's ignore it too. 17 | erl_crash.dump 18 | 19 | # Also ignore archive artifacts (built via "mix archive.build"). 20 | *.ez 21 | 22 | # Ignore package tarball (built via "mix hex.build"). 23 | pericles_proxy-*.tar 24 | 25 | -------------------------------------------------------------------------------- /test/models/scheme_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class SchemeTest < ActiveSupport::TestCase 4 | test "shouldn't exist without a name" do 5 | assert_not build(:scheme, name: nil).valid? 6 | end 7 | 8 | test 'set scheme to null if destroyed' do 9 | s = create(:scheme) 10 | a = create(:attribute, primitive_type: :string, scheme: s) 11 | assert s.destroy 12 | assert_not a.reload.scheme 13 | end 14 | 15 | test 'is pattern if regexp is set' do 16 | s = create(:scheme, regexp: 'cool') 17 | assert s.pattern? 18 | end 19 | 20 | test 'is format if regexp is not set' do 21 | s = create(:scheme, regexp: nil) 22 | assert s.format? 23 | end 24 | end 25 | -------------------------------------------------------------------------------- /db/migrate/20200417091346_add_confirmable_to_devise.rb: -------------------------------------------------------------------------------- 1 | class AddConfirmableToDevise < ActiveRecord::Migration[5.1] 2 | def up 3 | add_column :users, :confirmation_token, :string 4 | add_column :users, :confirmed_at, :datetime 5 | add_column :users, :confirmation_sent_at, :datetime 6 | add_column :users, :unconfirmed_email, :string # Only if using reconfirmable 7 | add_index :users, :confirmation_token, unique: true 8 | User.update_all confirmed_at: DateTime.now 9 | end 10 | 11 | def down 12 | remove_columns :users, :confirmation_token, :confirmed_at, :confirmation_sent_at 13 | remove_columns :users, :unconfirmed_email # Only if using reconfirmable 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /app/controllers/users/omniauth_callbacks_controller.rb: -------------------------------------------------------------------------------- 1 | class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController 2 | def google_oauth2 3 | # You need to implement the method below in your model (e.g. app/models/user.rb) 4 | @user = User.from_omniauth(request.env['omniauth.auth']) 5 | 6 | if @user&.persisted? 7 | flash[:notice] = I18n.t 'devise.omniauth_callbacks.success', kind: 'Google' 8 | sign_in_and_redirect @user, event: :authentication 9 | else 10 | flash[:alert] = I18n.t 'devise.omniauth_callbacks.failure', kind: 'Google', reason: I18n.t('users.sign_in.check_domain') 11 | redirect_to new_user_session_path 12 | end 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /db/migrate/20170830101250_devise_create_users.rb: -------------------------------------------------------------------------------- 1 | class DeviseCreateUsers < ActiveRecord::Migration[5.0] 2 | def change 3 | create_table :users do |t| 4 | ## Database authenticatable 5 | t.string :email, null: false, default: "" 6 | t.string :encrypted_password, null: false, default: "" 7 | 8 | ## Trackable 9 | t.integer :sign_in_count, default: 0, null: false 10 | t.datetime :current_sign_in_at 11 | t.datetime :last_sign_in_at 12 | t.inet :current_sign_in_ip 13 | t.inet :last_sign_in_ip 14 | 15 | t.timestamps null: false 16 | end 17 | 18 | add_index :users, :email, unique: true 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /app/decorators/news/route_audit_decorator.rb: -------------------------------------------------------------------------------- 1 | module News 2 | class RouteAuditDecorator < AuditDecorator 3 | def partial_name 4 | if audit.action == 'create' 5 | 'audits/route/create' 6 | elsif audit.action == 'update' 7 | 'audits/route/update' 8 | elsif audit.action == 'destroy' 9 | 'audits/route/destroy' 10 | end 11 | end 12 | 13 | def name 14 | audit.audited_changes['url'] 15 | end 16 | 17 | def url 18 | route = audit.auditable or return 19 | h.project_resource_url(route.project, route) 20 | end 21 | 22 | def link_name 23 | route = audit.auditable or return 24 | route.url 25 | end 26 | end 27 | end 28 | -------------------------------------------------------------------------------- /app/assets/javascripts/resources/new_representation.js: -------------------------------------------------------------------------------- 1 | $(document).ready(function() { 2 | $('.btn.selected').on('click', function () { 3 | var id = this.id; 4 | var resourceId = document.location.pathname.split('/')[2]; 5 | var url = '/resources/' + resourceId + '/resource_representations/' + id + '/random'; 6 | 7 | $('#error.error').text(''); 8 | $.ajax({ 9 | type: "GET", 10 | url: url, 11 | contentType: "application/json", 12 | success: function (data) { 13 | $('#resource_instance_body').val(JSON.stringify(data, null, 2)); 14 | }, 15 | error: function () { 16 | $('#error.error').text('An error occurred'); 17 | } 18 | }); 19 | }); 20 | }); -------------------------------------------------------------------------------- /app/assets/stylesheets/styles/projects.scss: -------------------------------------------------------------------------------- 1 | // Place all the styles related to the Projects controller here. 2 | // They will automatically be included in application.css. 3 | // You can use Sass (SCSS) here: http://sass-lang.com/ 4 | 5 | /*! 6 | * Start Bootstrap - Simple Sidebar (http://startbootstrap.com/) 7 | * Copyright 2013-2016 Start Bootstrap 8 | * Licensed under MIT (https://github.com/BlackrockDigital/startbootstrap/blob/gh-pages/LICENSE) 9 | */ 10 | /* Toggle Styles */ 11 | 12 | #project_description { 13 | height: 530px; 14 | } 15 | 16 | .highlight { 17 | background-color: #008afd; 18 | color: white; 19 | } 20 | 21 | #project-show { 22 | .buttons > a { 23 | margin-right: 4px; 24 | } 25 | } -------------------------------------------------------------------------------- /app/views/resources/_create_form.html.haml: -------------------------------------------------------------------------------- 1 | - content_for :page_scripts do 2 | = javascript_include_tag("resources/form.js") 3 | 4 | = bootstrap_form_for([project, @resource_creation_contract]) do |f| 5 | = render 'shared/errors', object: @resource_creation_contract 6 | 7 | .flexcontainer-justify-end= f.submit class: 'btn btn-primary' 8 | 9 | = f.text_field :name, placeholder: 'MyResource' 10 | 11 | = f.text_area :description 12 | 13 | .alert.alert-warning= t('.json_instance_explanation') 14 | 15 | = f.text_area :json_instance, label: 'From JSON (BETA)', placeholder: format_json({username: 'John Do', email: 'jd@fabernovel.com', first_name: 'John', last_name: 'Do', manager: nil}.to_json), class: 'json' 16 | -------------------------------------------------------------------------------- /app/controllers/concerns/project_related.rb: -------------------------------------------------------------------------------- 1 | module ProjectRelated 2 | extend ActiveSupport::Concern 3 | 4 | included do 5 | decorates_method :project 6 | end 7 | 8 | def project 9 | return @project if defined? @project 10 | @project = begin 11 | project = find_project 12 | 13 | policy = ProjectPolicy.new(current_user, project) 14 | raise Pundit::NotAuthorizedError, query: :show?, record: project, policy: policy unless policy.show? 15 | 16 | project 17 | end 18 | end 19 | 20 | def find_project 21 | Project.find(params[:project_id]) if params.key? :project_id 22 | end 23 | 24 | def pundit_user 25 | UserContext.new(current_user, project) 26 | end 27 | end 28 | -------------------------------------------------------------------------------- /app/views/code/rest.swift.erb: -------------------------------------------------------------------------------- 1 | // 2 | // <%= resource.rest_name =%>.swift 3 | // 4 | // Generated by Pericles on <%= Date.today.strftime("%d/%m/%Y") =%> 5 | 6 | // 7 | // 8 | 9 | import Foundation 10 | 11 | struct <%= resource.rest_name =%> : Decodable { 12 | <% resource.resource_attributes.each do |attribute| %> 13 | let <%= attribute.camel_variable_name =%>: <%= attribute.swift_type =%> 14 | 15 | <% end %> 16 | 17 | enum CodingKeys : String, CodingKey { 18 | <% resource.resource_attributes.each do |attribute| %> 19 | case <%= attribute.camel_variable_name =%><% if attribute.camel_variable_name != attribute.key_name %> = "<%= attribute.key_name =%>"<% end %> 20 | <% end %> 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /app/decorators/code/attributes_resource_representation_decorator.rb: -------------------------------------------------------------------------------- 1 | class Code::AttributesResourceRepresentationDecorator < Draper::Decorator 2 | include Code::Field 3 | delegate_all 4 | delegate :name, :is_array, :primitive_type, :date?, :datetime?, to: :resource_attribute 5 | 6 | def resource 7 | Code::ResourceRepresentationDecorator.new(resource_representation) 8 | end 9 | 10 | def code_nullable 11 | !object.is_required || object.resource_attribute.nullable 12 | end 13 | 14 | def graphql_nullable 15 | object.resource_attribute.nullable 16 | end 17 | 18 | def boolean? 19 | object.resource_attribute.boolean? 20 | end 21 | 22 | def enum 23 | object.resource_attribute.enum 24 | end 25 | end 26 | -------------------------------------------------------------------------------- /config/initializers/inflections.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Add new inflection rules using the following format. Inflections 4 | # are locale specific, and you may define rules for as many different 5 | # locales as you wish. All of these examples are active by default: 6 | # ActiveSupport::Inflector.inflections(:en) do |inflect| 7 | # inflect.plural /^(ox)$/i, '\1en' 8 | # inflect.singular /^(ox)en/i, '\1' 9 | # inflect.irregular 'person', 'people' 10 | # inflect.uncountable %w( fish sheep ) 11 | # end 12 | 13 | # These inflection rules are supported but not enabled by default: 14 | # ActiveSupport::Inflector.inflections(:en) do |inflect| 15 | # inflect.acronym 'RESTful' 16 | # end 17 | -------------------------------------------------------------------------------- /app/controllers/schemes_controller.rb: -------------------------------------------------------------------------------- 1 | class SchemesController < ApplicationController 2 | lazy_controller_of :scheme, helper_method: true 3 | 4 | def index 5 | @schemes = policy_scope(Scheme).all 6 | end 7 | 8 | def new; end 9 | 10 | def edit; end 11 | 12 | def update 13 | if scheme.update(permitted_attributes(scheme)) 14 | redirect_to schemes_path 15 | else 16 | render 'edit', status: :unprocessable_entity 17 | end 18 | end 19 | 20 | def create 21 | if scheme.save 22 | redirect_to schemes_path 23 | else 24 | render 'new', status: :unprocessable_entity 25 | end 26 | end 27 | 28 | def destroy 29 | scheme.destroy 30 | redirect_to schemes_path 31 | end 32 | end 33 | -------------------------------------------------------------------------------- /app/views/query_parameters/_query_parameter.html.haml: -------------------------------------------------------------------------------- 1 | .panel.panel-default 2 | .panel-body 3 | .row 4 | .col-xs-4 5 | %dl 6 | %dt Name 7 | %dd 8 | %strong= query_parameter.name 9 | .col-xs-2 10 | %dl 11 | %dt Type 12 | %dd 13 | %strong= query_parameter.primitive_type 14 | .col-xs-2 15 | %dl 16 | %dt Required ? 17 | %dd= query_parameter.is_optional ? t('optional') : t('required') 18 | - unless query_parameter.description.blank? 19 | .col-xs-4 20 | %dl 21 | %dt Description 22 | %dd{class: 'markdown'} 23 | %vue-markdown{source: query_parameter.description} 24 | -------------------------------------------------------------------------------- /config/locales/validations/fr.yml: -------------------------------------------------------------------------------- 1 | fr: 2 | activerecord: 3 | attributes: 4 | validation: 5 | status: 6 | one: statut 7 | other: statuts 8 | success: "L'instance de JSON entrée est validée par le JSON schema entré (JSON Schema Draft 4)." 9 | schema_parse_error: "Le JSON schema entré n'est pas un JSON text valide (RFC 7159)." 10 | instance_parse_error: "L'instance de JSON entrée n'est pas un JSON text valide (RFC 7159)." 11 | schema_validation_error: "Le JSON schema entré n'est pas conforme au JSON Schema Draft 4. Erreurs:" 12 | instance_validation_error: "L'instance de JSON entrée n'est pas validée par le JSON schema entré (JSON Schema Draft 4). Erreurs:" 13 | -------------------------------------------------------------------------------- /app/decorators/news/metadatum_audit_decorator.rb: -------------------------------------------------------------------------------- 1 | module News 2 | class MetadatumAuditDecorator < AuditDecorator 3 | def partial_name 4 | if audit.action == 'create' 5 | 'audits/metadatum/create' 6 | elsif audit.action == 'update' 7 | 'audits/metadatum/update' 8 | elsif audit.action == 'destroy' 9 | 'audits/metadatum/destroy' 10 | end 11 | end 12 | 13 | def name 14 | audit.audited_changes['name'] 15 | end 16 | 17 | def url 18 | metadatum = audit.auditable or return 19 | h.project_metadata_url(metadatum.project) 20 | end 21 | 22 | def link_name 23 | metadatum = audit.auditable or return 24 | metadatum.name 25 | end 26 | end 27 | end 28 | -------------------------------------------------------------------------------- /app/decorators/news/resource_audit_decorator.rb: -------------------------------------------------------------------------------- 1 | module News 2 | class ResourceAuditDecorator < AuditDecorator 3 | def partial_name 4 | if audit.action == 'create' 5 | 'audits/resource/create' 6 | elsif audit.action == 'update' 7 | 'audits/resource/update' 8 | elsif audit.action == 'destroy' 9 | 'audits/resource/destroy' 10 | end 11 | end 12 | 13 | def name 14 | audit.audited_changes['name'] 15 | end 16 | 17 | def url 18 | resource = audit.auditable or return 19 | h.project_resource_url(resource.project, resource) 20 | end 21 | 22 | def link_name 23 | resource = audit.auditable or return 24 | resource.name 25 | end 26 | end 27 | end 28 | -------------------------------------------------------------------------------- /app/services/mocks_zip_builder.rb: -------------------------------------------------------------------------------- 1 | require 'zip' 2 | 3 | class MocksZipBuilder < AbstractZipBuilder 4 | def initialize(mock_profile) 5 | @mock_profile = mock_profile 6 | end 7 | 8 | def collection 9 | @mock_profile.mock_pickers.preload(:resource_instances) 10 | end 11 | 12 | def filename(mock_picker) 13 | if mock_picker.url_pattern.blank? 14 | filename = mock_picker.response.route.url 15 | else 16 | filename = mock_picker.url_pattern 17 | end 18 | filename_without_trailing_slashes = filename.gsub(/(^\/+)|(\/+$)/, '') 19 | filename_without_trailing_slashes + '.json' 20 | end 21 | 22 | def file_content(mock_picker) 23 | JSON.stable_pretty_generate(mock_picker.mock_body) 24 | end 25 | end 26 | -------------------------------------------------------------------------------- /app/services/post_slack_news.rb: -------------------------------------------------------------------------------- 1 | class PostSlackNews 2 | def initialize(project) 3 | @project = project 4 | @attachment_mapper = SlackAttachmentMapper.new 5 | end 6 | 7 | def execute(since = @project.slack_updated_at) 8 | since ||= 1.day.ago 9 | audits = AuditsRepository.new 10 | .news_of_project(@project) 11 | .where('created_at > ?', since) 12 | .order(:created_at) 13 | .map(&:decorate) 14 | 15 | return 0 if audits.empty? 16 | 17 | attachments = audits.map { |a| @attachment_mapper.map(a) } 18 | HTTP.post(@project.slack_incoming_webhook_url, json: { attachments: attachments }) 19 | @project.update(slack_updated_at: audits.map(&:created_at).max) 20 | audits.length 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /app/views/users/index.html.haml: -------------------------------------------------------------------------------- 1 | = content_for :title, 'Users' 2 | 3 | %h1 Users 4 | 5 | %table{class: "table table-striped"} 6 | %thead 7 | %tr 8 | %th Email 9 | %th Internal 10 | %th Projects 11 | %th 12 | %tbody 13 | - @users.each do |user| 14 | %tr 15 | %td= user.email 16 | %td 17 | = form_with model: user, format: :json, class: 'user_form' do |f| 18 | = f.check_box :internal, onchange: '$(this.form).trigger("submit.rails");' 19 | 20 | %td= user.projects.map { |p| link_to(p.title, project_path(p)) }.to_sentence.html_safe 21 | %td= link_to 'Delete', user_path(user), method: :delete, data: { confirm: 'Are you sure?' }, class: 'btn btn-default' 22 | 23 | 24 | -------------------------------------------------------------------------------- /db/migrate/20171229133209_remove_json_errors.rb: -------------------------------------------------------------------------------- 1 | class RemoveJsonErrors < ActiveRecord::Migration[5.0] 2 | def up 3 | drop_table :json_errors 4 | ActiveRecord::Base.connection.execute("TRUNCATE validations") 5 | change_column :validations, :json_schema, 'json USING CAST(json_schema AS json)' 6 | change_column :validations, :json_instance, 'json USING CAST(json_instance AS json)' 7 | end 8 | 9 | def down 10 | change_column :validations, :json_schema, :text 11 | change_column :validations, :json_instance, :text 12 | create_table :json_errors do |t| 13 | t.text :description 14 | t.string :type 15 | t.references :validation, foreign_key: true 16 | 17 | t.timestamps 18 | end 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /test/models/query_parameter_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class QueryParameterTest < ActiveSupport::TestCase 4 | test "shouldn't exist without a name" do 5 | assert_not build(:query_parameter, name: nil).valid? 6 | end 7 | 8 | test "shouldn't exist without a primitive_type" do 9 | assert_not build(:query_parameter, primitive_type: nil).valid? 10 | end 11 | 12 | test "shouldn't exist without a route" do 13 | assert_not build(:query_parameter, route: nil).valid? 14 | end 15 | 16 | test 'QueryParameter should be valid with all attributes set correctly' do 17 | assert build(:query_parameter, name: 'user_id', description: 'New test QueryParameter', primitive_type: :string, is_optional: false).valid? 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /app/services/set_slack_webhook.rb: -------------------------------------------------------------------------------- 1 | class SetSlackWebhook 2 | def initialize(project) 3 | @project = project 4 | end 5 | 6 | def execute(code, redirect_uri) 7 | form = { 8 | client_id: Rails.application.secrets.slack[:client_id], 9 | client_secret: Rails.application.secrets.slack[:client_secret], 10 | code: code, 11 | redirect_uri: redirect_uri 12 | } 13 | resp = HTTP.post('https://slack.com/api/oauth.access', form: form) 14 | incoming_webhook = JSON.parse(resp.body).dig('incoming_webhook') 15 | return unless incoming_webhook 16 | 17 | @project.update( 18 | slack_channel: incoming_webhook.dig('channel'), 19 | slack_incoming_webhook_url: incoming_webhook.dig('url') 20 | ) 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /app/views/security_schemes/_security_scheme.html.haml: -------------------------------------------------------------------------------- 1 | .flexspace-and-center 2 | %dl.flex-150 3 | %dt Key 4 | %dd 5 | %strong= security_scheme.key 6 | %dl.flex-150 7 | %dt Type 8 | %dd 9 | %strong= security_scheme.security_scheme_type 10 | %dl.flex 11 | %dt Description 12 | %dd{class: 'markdown'} 13 | %vue-markdown{source: security_scheme.description} 14 | .btn-group{ role: "group" } 15 | = link_to 'Edit', edit_project_security_scheme_path(project, security_scheme), class: 'btn btn-primary' if user.can_edit? security_scheme 16 | = link_to 'Delete', project_security_scheme_path(project, security_scheme), method: :delete, data: { confirm: 'Are you sure?' }, class: 'btn btn-primary' if user.can_delete? security_scheme 17 | -------------------------------------------------------------------------------- /db/migrate/20171116161642_create_api_errors_and_errors_instances.rb: -------------------------------------------------------------------------------- 1 | class CreateApiErrorsAndErrorsInstances < ActiveRecord::Migration[5.0] 2 | def change 3 | create_table :api_errors do |t| 4 | t.string :name 5 | t.json :json_schema 6 | t.references :project 7 | 8 | t.timestamps 9 | end 10 | 11 | add_reference :responses, :api_error, foreign_key: true 12 | 13 | create_table :api_error_instances do |t| 14 | t.string :name 15 | t.json :body 16 | t.references :api_error, foreign_key: true 17 | 18 | t.timestamps 19 | end 20 | 21 | create_join_table :api_error_instances, :mock_pickers do |t| 22 | t.index :api_error_instance_id 23 | t.index :mock_picker_id 24 | end 25 | end 26 | end 27 | -------------------------------------------------------------------------------- /test/decorators/json_schema/resource_representation_decorator_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class ResourceRepresentationDecoratorTest < ActiveSupport::TestCase 4 | test 'json schema is not looping' do 5 | user = create(:resource) 6 | representation = user.resource_representations.first 7 | managee = create(:attribute, parent_resource: user, resource: user, name: 'managee', primitive_type: nil) 8 | create( 9 | :attributes_resource_representation, 10 | resource_attribute: managee, 11 | parent_resource_representation: representation, 12 | resource_representation: representation 13 | ) 14 | 15 | assert_not_looping { JSONSchema::ResourceRepresentationDecorator.new(representation.reload).json_schema } 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /app/view_models/body_error/required_error_view_model.rb: -------------------------------------------------------------------------------- 1 | module BodyError 2 | class RequiredErrorViewModel < BodyErrorViewModel 3 | attr_reader :required_properties 4 | 5 | def initialize(path, required_properties) 6 | super(path) 7 | @required_properties = required_properties 8 | end 9 | 10 | def description 11 | if @required_properties.count == 1 12 | "#{path} - missing property #{@required_properties.first}" 13 | else 14 | "#{path} - missing properties #{@required_properties.join(', ')}" 15 | end 16 | end 17 | 18 | def type 19 | :required 20 | end 21 | 22 | def merge(vm) 23 | RequiredErrorViewModel.new(path, required_properties + vm.required_properties) 24 | end 25 | end 26 | end -------------------------------------------------------------------------------- /app/view_models/body_error/type_error_view_model.rb: -------------------------------------------------------------------------------- 1 | module BodyError 2 | class TypeErrorViewModel < BodyErrorViewModel 3 | attr_reader :current_type, :target_types 4 | 5 | def initialize(path, current_type, target_types) 6 | super(path) 7 | @current_type = current_type 8 | @target_types = target_types 9 | end 10 | 11 | def type 12 | :type 13 | end 14 | 15 | def description 16 | if @current_type == 'null' 17 | "#{path} - cannot be null" 18 | else 19 | "#{path} - wrong type: #{@current_type} instead of #{@target_types.join(' or ')}" 20 | end 21 | end 22 | 23 | def merge(vm) 24 | TypeErrorViewModel.new(path, current_type, target_types + vm.target_types) 25 | end 26 | end 27 | end 28 | -------------------------------------------------------------------------------- /app/views/validations/new.html.haml: -------------------------------------------------------------------------------- 1 | = content_for :title, "New Validation" 2 | 3 | - content_for :page_scripts do 4 | = javascript_include_tag("validate_instance") 5 | = javascript_include_tag("validations/new") 6 | 7 | 8 | %h1 Validate a JSON instance 9 | 10 | .row 11 | .col-xs-12 12 | #json-validation-result 13 | 14 | .row 15 | .col-xs-6 16 | %h2 JSON Schema 17 | %p 18 | = text_area_tag(:json_schema, @default_json_instance, size: "60x20") 19 | .col-xs-6 20 | %h2 JSON instance 21 | %p 22 | = text_area_tag(:json_instance, @default_json_instance, size: "60x20") 23 | 24 | .row 25 | .col-xs-12 26 | %p 27 | = submit_tag("Validate", id: 'validate_json_instance') 28 | 29 | = link_to 'See Validations History', validations_path 30 | -------------------------------------------------------------------------------- /app/decorators/json_schema/response_decorator.rb: -------------------------------------------------------------------------------- 1 | module JSONSchema 2 | class ResponseDecorator < Draper::Decorator 3 | delegate_all 4 | decorates_association :metadata_responses, with: JSONSchema::MetadataResponseDecorator 5 | 6 | def json_schema 7 | if resource_representation 8 | contextual_representation = JSONSchema::ResourceRepresentationDecorator.new( 9 | resource_representation, context: context 10 | ) 11 | end 12 | 13 | json_schema_source = contextual_representation || api_error 14 | JSONSchemaBuilder.new( 15 | json_schema_source, 16 | is_collection: is_collection, 17 | root_key: root_key, 18 | metadata_responses: metadata_responses 19 | ).execute 20 | end 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /app/helpers/responses_helper.rb: -------------------------------------------------------------------------------- 1 | module ResponsesHelper 2 | def response_status_code_class(status_code) 3 | if status_code < 400 4 | 'valid-response' 5 | else 6 | 'invalid-response' 7 | end 8 | end 9 | 10 | def schema_summary(root_key, representation, is_collection) 11 | return '' if representation&.name.blank? 12 | 13 | summary = link_to( 14 | representation.name, 15 | project_resource_path(representation.resource.project, representation.resource, anchor: "rep-#{representation.id}") 16 | ) 17 | 18 | summary = "[ #{summary} ]" if is_collection 19 | summary = "\"#{root_key}\": #{summary}" if root_key.present? 20 | summary = "{ #{summary} }" unless is_collection && root_key.blank? 21 | 22 | summary 23 | end 24 | end 25 | -------------------------------------------------------------------------------- /app/views/schemes/index.html.haml: -------------------------------------------------------------------------------- 1 | = content_for :title, "Schemes" 2 | 3 | %h1 Schemes 4 | 5 | - if user.can_create? Scheme 6 | .flexcontainer.flexcontainer-justify-end 7 | = link_to 'New Scheme', new_scheme_path, class: "btn btn-primary btn-lg" 8 | 9 | 10 | - if @schemes.any? 11 | %table{class: "table table-striped"} 12 | %thead 13 | %tr 14 | %th Name 15 | %th Regexp 16 | %th 17 | %th 18 | %tbody 19 | - @schemes.each do |scheme| 20 | %tr 21 | %td= scheme.name 22 | %td= scheme.regexp 23 | %td= link_to 'Edit', edit_scheme_path(scheme) if user.can_edit? scheme 24 | %td= link_to 'Delete', scheme_path(scheme), method: :delete, data: { confirm: 'Are you sure?' } if user.can_delete? scheme -------------------------------------------------------------------------------- /app/models/mock_profile.rb: -------------------------------------------------------------------------------- 1 | class MockProfile < ApplicationRecord 2 | belongs_to :project 3 | has_many :mock_pickers, -> { order(:priority) }, dependent: :destroy 4 | has_many :responses, through: :mock_pickers 5 | has_ancestry 6 | 7 | accepts_nested_attributes_for :mock_pickers, allow_destroy: true 8 | 9 | validates :name, presence: true 10 | 11 | def inherited_and_self_mock_pickers_of(route) 12 | sorted_profiles = (ancestors.ordered_by_ancestry.to_a << self).reverse 13 | # Note: Clément Villain 12/12/17 sorted_profiles is a very short list (<30 items max) so there is not that many n+1 queries 14 | # Feel free to fix it ! 15 | sorted_profiles.map { |profile| profile.mock_pickers.joins(:response).where(responses: { route: route }) }.flatten 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /app/assets/stylesheets/styles/audits.scss: -------------------------------------------------------------------------------- 1 | #news { 2 | .card { 3 | min-height: 88px; 4 | margin: 24px; 5 | padding: 24px; 6 | background-color: white; 7 | 8 | box-shadow: 0 2px 4px 0 #f1f2f4; 9 | 10 | border-left-style: solid; 11 | 12 | &.create { 13 | border-color: rgb(0, 181, 147); 14 | } 15 | 16 | &.update { 17 | border-color: rgb(255, 172, 20); 18 | } 19 | 20 | &.destroy { 21 | border-color: rgb(193, 19, 37); 22 | } 23 | } 24 | 25 | .right { 26 | float: right; 27 | color: $grey; 28 | 29 | text-align: right; 30 | font-style: italic; 31 | } 32 | 33 | li { 34 | span { 35 | margin: 0 0.5em; 36 | } 37 | } 38 | 39 | .stroke { 40 | text-decoration: line-through; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /app/decorators/news/response_audit_decorator.rb: -------------------------------------------------------------------------------- 1 | module News 2 | class ResponseAuditDecorator < AuditDecorator 3 | def partial_name 4 | if audit.action == 'create' 5 | 'audits/response/create' 6 | elsif audit.action == 'update' 7 | 'audits/response/update' 8 | elsif audit.action == 'destroy' 9 | 'audits/response/destroy' 10 | end 11 | end 12 | 13 | def type 14 | audit.auditable_type 15 | end 16 | def name 17 | audit.audited_changes['status_code'] 18 | end 19 | 20 | def link_name 21 | route = audit.associated or return 22 | route.url 23 | end 24 | 25 | def url 26 | route = audit.associated or return 27 | h.project_route_url(route.project, route) 28 | end 29 | end 30 | end 31 | -------------------------------------------------------------------------------- /test/transactions/create_rest_routes_transaction_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class CreateRestRoutesTransactionTest < ActiveSupport::TestCase 4 | setup do 5 | @project = create(:project) 6 | @resource = create(:resource, project: @project) 7 | end 8 | 9 | test 'create 5 routes and 5 responses' do 10 | assert_difference 'Route.count', 5 do 11 | assert_difference 'Response.count', 5 do 12 | CreateRestRoutesTransaction.new.call( 13 | url: '/route', 14 | resource: @resource, 15 | request_resource_representation: create(:resource_representation, resource: @resource), 16 | response_resource_representation: create(:resource_representation, resource: @resource) 17 | ) 18 | end 19 | end 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /db/migrate/20170921083345_create_schemes.rb: -------------------------------------------------------------------------------- 1 | class CreateSchemes < ActiveRecord::Migration[5.0] 2 | def change 3 | create_table :schemes do |t| 4 | t.string :name 5 | t.string :regexp 6 | 7 | t.timestamps 8 | end 9 | 10 | add_reference :attributes, :scheme, foreign_key: true 11 | reversible do |dir| 12 | Attribute.find_each do |a| 13 | dir.up do 14 | unless a.pattern.blank? 15 | a.scheme_id = Scheme.find_or_create_by(name: a.pattern, regexp: a.pattern).id 16 | a.save 17 | end 18 | end 19 | dir.down do 20 | a.pattern = Scheme.find_by(id: a.scheme_id)&.regexp 21 | a.save 22 | end 23 | end 24 | end 25 | remove_column :attributes, :pattern, :string 26 | end 27 | end 28 | -------------------------------------------------------------------------------- /test/models/metadatum_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class MetadatumTest < ActiveSupport::TestCase 4 | test "shouldn't exist without a name" do 5 | assert_not build(:metadatum, name: nil).valid? 6 | end 7 | 8 | test "shouldn't exist without a primitive_type" do 9 | assert_not build(:metadatum, primitive_type: nil).valid? 10 | end 11 | 12 | test "shouldn't exist without a project" do 13 | assert_not build(:metadatum, project: nil).valid? 14 | end 15 | 16 | test "Two Metadata within the same project shouldn't have the same name" do 17 | metadatum = create(:metadatum) 18 | assert_not build(:metadatum, name: metadatum.name, project: metadatum.project).valid? 19 | assert build(:metadatum, name: metadatum.name.upcase, project: metadatum.project).valid? 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /app/views/api_errors/index.html.haml: -------------------------------------------------------------------------------- 1 | = content_for :title, "API Errors" 2 | 3 | %h1 Errors 4 | 5 | 6 | - if user.can_create? ApiError, project: project 7 | .flexcontainer.flexcontainer-justify-end 8 | = link_to 'New Error', new_project_api_error_path(project), class: "btn btn-primary btn-lg" 9 | 10 | .list-group.margin-top-element 11 | - @api_errors.each do |api_error| 12 | %a{class: "list-group-item", href: project_api_error_path(project, api_error)} 13 | .flexcontainer.flexcontainer-space-between 14 | .name 15 | = api_error.name 16 | - if api_error.has_invalid_mocks? 17 | .error 18 | .tool-tip{'data-toggle' => "tooltip", 'data-placement' => "top", title: "Invalid mocks !"} 19 | \/!\ 20 | 21 | - if @api_errors.empty? 22 | %p= t('.no_errors') -------------------------------------------------------------------------------- /db/migrate/20171004090741_create_report.rb: -------------------------------------------------------------------------------- 1 | class CreateReport < ActiveRecord::Migration[5.0] 2 | def change 3 | create_table :reports do |t| 4 | t.integer :response_status_code 5 | t.string :response_body 6 | t.json :response_headers 7 | t.string :request_body 8 | t.json :request_headers 9 | t.string :request_method 10 | t.string :url 11 | t.references :route, foreign_key: true 12 | t.references :response, foreign_key: true 13 | t.references :project, foreign_key: true 14 | 15 | t.timestamps null: false 16 | end 17 | 18 | create_table :validation_errors do |t| 19 | t.integer :category 20 | t.string :description 21 | t.references :report, foreign_key: true 22 | 23 | t.timestamps null: false 24 | end 25 | end 26 | end 27 | -------------------------------------------------------------------------------- /app/decorators/code/data_class.rb: -------------------------------------------------------------------------------- 1 | module Code 2 | module DataClass 3 | extend ActiveSupport::Concern 4 | 5 | def rest_name 6 | "Rest#{pascal_name}" 7 | end 8 | 9 | def graphql_name 10 | "#{pascal_name}Type" 11 | end 12 | 13 | def pascal_name 14 | name.parameterize(separator: '_', preserve_case: true).camelcase 15 | end 16 | 17 | def kotlin_filename 18 | "#{rest_name}.kt" 19 | end 20 | 21 | def swift_filename 22 | "#{rest_name}.swift" 23 | end 24 | 25 | def ruby_filename 26 | "#{name.underscore}_serializer.rb" 27 | end 28 | 29 | def typescript_filename 30 | "#{name.underscore}.ts" 31 | end 32 | 33 | def should_import_nullable_annotation 34 | resource_attributes.any?(&:code_nullable) 35 | end 36 | end 37 | end 38 | -------------------------------------------------------------------------------- /app/models/report.rb: -------------------------------------------------------------------------------- 1 | class Report < ApplicationRecord 2 | belongs_to :project 3 | belongs_to :route, optional: true 4 | belongs_to :response, optional: true 5 | 6 | has_many :validation_errors, dependent: :delete_all 7 | 8 | default_scope { includes(:validation_errors) } 9 | 10 | validates :response_status_code, :response_headers, :request_headers, presence: true 11 | 12 | def correct? 13 | validation_errors.empty? 14 | end 15 | 16 | def errors? 17 | !correct? 18 | end 19 | 20 | def valid_status? 21 | status_error.blank? 22 | end 23 | 24 | def status_error 25 | validation_errors.find(&:status_code?) 26 | end 27 | 28 | def header_errors 29 | validation_errors.select(&:header?) 30 | end 31 | 32 | def body_errors 33 | validation_errors.select(&:body?) 34 | end 35 | end 36 | -------------------------------------------------------------------------------- /app/views/resource_instances/_form.html.haml: -------------------------------------------------------------------------------- 1 | = bootstrap_form_for(model_instance.persisted? ? model_instance : [model, model_instance]) do |f| 2 | .flexcontainer-justify-end 3 | = f.submit class: 'btn btn-primary' 4 | = f.text_field :name 5 | .flexcontainer.flexwrap.flex-v-center 6 | - model.resource_representations.each_with_index do |r, i| 7 | .btn.selected{id: r.id, class: "color-#{i}"}=r.name 8 | #error.error 9 | = f.text_area :body, value: format_json(model_instance.body), class: 'json' 10 | 11 | - model_instance.body_errors_by_representations.each_pair do |rep, body_errors| 12 | = link_to rep.name, project_resource_path(project, rep.resource, anchor: "rep-#{rep.id}") 13 | = render partial: 'shared/schema_errors', locals: { body_errors: body_errors } 14 | 15 | = javascript_include_tag 'resources/new_representation' -------------------------------------------------------------------------------- /app/controllers/users_controller.rb: -------------------------------------------------------------------------------- 1 | class UsersController < ApplicationController 2 | include Authenticated 3 | 4 | lazy_controller_of :user 5 | 6 | def index 7 | authorize User 8 | @users = policy_scope(User).order(:email) 9 | end 10 | 11 | def update 12 | if user.update(permitted_attributes(user)) 13 | respond_to do |format| 14 | format.json { render json: user } 15 | end 16 | else 17 | respond_to do |format| 18 | format.json { render json: user.errors, status: :unprocessable_entity } 19 | end 20 | end 21 | end 22 | 23 | def destroy 24 | if user.destroy 25 | redirect_to users_path, notice: "#{user.email} has been deleted." 26 | else 27 | redirect_to users_path, alert: users_path.errors.full_messages 28 | end 29 | end 30 | 31 | def show; end 32 | end 33 | -------------------------------------------------------------------------------- /app/decorators/news/attribute_audit_decorator.rb: -------------------------------------------------------------------------------- 1 | module News 2 | class AttributeAuditDecorator < AuditDecorator 3 | def partial_name 4 | if audit.action == 'create' 5 | 'audits/attribute/create' 6 | elsif audit.action == 'update' 7 | 'audits/attribute/update' 8 | elsif audit.action == 'destroy' 9 | 'audits/attribute/destroy' 10 | end 11 | end 12 | 13 | def name 14 | audit.audited_changes['name'] 15 | end 16 | 17 | def type 18 | resource = audit.auditable or return 19 | resource.type 20 | end 21 | 22 | def url 23 | resource = audit.associated or return 24 | h.project_resource_url(resource.project, resource) 25 | end 26 | 27 | def link_name 28 | resource = audit.associated or return 29 | resource.name 30 | end 31 | end 32 | end 33 | --------------------------------------------------------------------------------