diff --git a/.gitignore b/.gitignore index 587c808837..2b9041979e 100644 --- a/.gitignore +++ b/.gitignore @@ -11,11 +11,32 @@ logs/ log/ .yardoc -.coverage *.env .ruby-gemset +.history -#IDEs -.idea -.history +.byebug_history + +# Ignore Rubocop files +.rubocop-* + +# Ignore coverage reports +coverage/ +.coverage/ + +# Ignore editor specific configs +/.idea +/.vscode +.project +.classpath +.c9/ +*.launch +.settings/ +*.sublime-workspace +.generators +.rakeTasks + +# System Files +.DS_Store +Thumbs.db diff --git a/lib/travis/api/v3/insights_client.rb b/lib/travis/api/v3/insights_client.rb new file mode 100644 index 0000000000..b4822b42ed --- /dev/null +++ b/lib/travis/api/v3/insights_client.rb @@ -0,0 +1,266 @@ +# frozen_string_literal: true + +module Travis::API::V3 + class InsightsClient + class ConfigurationError < StandardError; end + + def initialize(user_id) + @user_id = user_id + end + + def user_notifications(filter, page, active, sort_by, sort_direction) + query_string = query_string_from_params( + value: filter, + page: page || '1', + active: active, + order: sort_by, + order_dir: sort_direction + ) + response = connection.get("/user_notifications?#{query_string}") + + handle_errors_and_respond(response) do |body| + notifications = body['data'].map do |notification| + Travis::API::V3::Models::InsightsNotification.new(notification) + end + + Travis::API::V3::Models::InsightsCollection.new(notifications, body.fetch('total_count')) + end + end + + def toggle_snooze_user_notifications(notification_ids) + response = connection.put('/user_notifications/toggle_snooze', snooze_ids: notification_ids) + + handle_errors_and_respond(response) + end + + def user_plugins(filter, page, active, sort_by, sort_direction) + query_string = query_string_from_params( + value: filter, + page: page || '1', + active: active, + order: sort_by, + order_dir: sort_direction + ) + response = connection.get("/user_plugins?#{query_string}") + + handle_errors_and_respond(response) do |body| + plugins = body['data'].map do |plugin| + Travis::API::V3::Models::InsightsPlugin.new(plugin) + end + + Travis::API::V3::Models::InsightsCollection.new(plugins, body.fetch('total_count')) + end + end + + def create_plugin(params) + response = connection.post("/user_plugins", user_plugin: params) + handle_errors_and_respond(response) do |body| + Travis::API::V3::Models::InsightsPlugin.new(body['plugin']) + end + end + + def toggle_active_plugins(plugin_ids) + response = connection.put('/user_plugins/toggle_active', toggle_ids: plugin_ids) + + handle_errors_and_respond(response) do |body| + Travis::API::V3::Models::InsightsCollection.new([], 0) + end + end + + def delete_many_plugins(plugin_ids) + response = connection.delete('/user_plugins/delete_many', delete_ids: plugin_ids) + + handle_errors_and_respond(response) do |body| + Travis::API::V3::Models::InsightsCollection.new([], 0) + end + end + + def run_scan + response = connection.get('/user_plugins/run_scan') + + handle_errors_and_respond(response) do |body| + Travis::API::V3::Models::InsightsCollection.new([], 0) + end + end + + def generate_key(plugin_name, plugin_type) + response = connection.get('/user_plugins/generate_key', name: plugin_name, plugin_type: plugin_type) + + handle_errors_and_respond(response) do |body| + body + end + end + + def authenticate_key(params) + response = connection.post('/user_plugins/authenticate_key', params) + + handle_errors_and_respond(response) do |body| + body + end + end + + def template_plugin_tests(plugin_type) + response = connection.get("/user_plugins/#{plugin_type}/template_plugin_tests") + + handle_errors_and_respond(response) do |body| + body + end + end + + def get_scan_logs(plugin_id, last_id) + params = last_id ? { last: last_id, poll: true } : {} + response = connection.get("/user_plugins/#{plugin_id}/get_scan_logs", params) + + handle_errors_and_respond(response) do |body| + body + end + end + + def probes(filter, page, active, sort_by, sort_direction) + query_string = query_string_from_params( + value: filter, + page: page || '1', + active: active, + order: sort_by, + order_dir: sort_direction + ) + response = connection.get("/probes?#{query_string}") + + handle_errors_and_respond(response) do |body| + probes = body['data'].map do |probe| + Travis::API::V3::Models::InsightsProbe.new(probe) + end + + Travis::API::V3::Models::InsightsCollection.new(probes, body.fetch('total_count')) + end + end + + def create_probe(params) + response = connection.post("/probes", test_template: params) + handle_errors_and_respond(response) do |body| + Travis::API::V3::Models::InsightsProbe.new(body) + end + end + + def update_probe(params) + response = connection.patch("/probes/#{params['probe_id']}", params) + handle_errors_and_respond(response) do |body| + Travis::API::V3::Models::InsightsProbe.new(body) + end + end + + def get_probe(params) + response = connection.get("/probes/#{params['probe_id']}/template_test", params) + handle_errors_and_respond(response) do |body| + Travis::API::V3::Models::InsightsProbe.new(body) + end + end + + def toggle_active_probes(probe_ids) + response = connection.put('/probes/toggle_active', toggle_ids: probe_ids) + + handle_errors_and_respond(response) do |body| + Travis::API::V3::Models::InsightsCollection.new([], 0) + end + end + + def delete_many_probes(probe_ids) + response = connection.delete('/probes/delete_many', delete_ids: probe_ids) + + handle_errors_and_respond(response) do |body| + Travis::API::V3::Models::InsightsCollection.new([], 0) + end + end + + def sandbox_plugins(plugin_type) + response = connection.post('/sandbox/plugins', plugin_type: plugin_type) + + handle_errors_and_respond(response) do |body| + body + end + end + + def sandbox_plugin_data(plugin_id) + response = connection.post('/sandbox/plugin_data', plugin_id: plugin_id) + + handle_errors_and_respond(response) do |body| + body + end + end + + def sandbox_run_query(plugin_id, query) + response = connection.post('/sandbox/run_query', plugin_id: plugin_id, query: query) + + handle_errors_and_respond(response) do |body| + body + end + end + + def public_key + response = connection.get('/api/v1/public_keys/latest.json') + + handle_errors_and_respond(response) do |body| + Travis::API::V3::Models::InsightsPublicKey.new(body) + end + end + + def search_tags + response = connection.get('/tags') + + handle_errors_and_respond(response) do |body| + tags = body.map do |tag| + Travis::API::V3::Models::InsightsTag.new(tag) + end + end + end + + private + + def handle_errors_and_respond(response) + case response.status + when 200, 201 + yield(response.body) if block_given? + when 202 + true + when 204 + true + when 400 + raise Travis::API::V3::ClientError, response.body&.fetch('error', '') + when 403 + raise Travis::API::V3::InsufficientAccess, response.body&.fetch('rejection_code', '') + when 404 + raise Travis::API::V3::NotFound, response.body&.fetch('error', '') + when 422 + raise Travis::API::V3::UnprocessableEntity, response.body&.fetch('error', '') + else + raise Travis::API::V3::ServerError, 'Insights API failed' + end + end + + def connection(timeout: 20) + @connection ||= Faraday.new(url: insights_url, ssl: { ca_path: '/usr/lib/ssl/certs' }) do |conn| + conn.headers[:Authorization] = "Token token=\"#{insights_auth_token}\"" + conn.headers['X-Travis-User-Id'] = @user_id.to_s + conn.headers['Content-Type'] = 'application/json' + conn.request :json + conn.response :json + conn.options[:open_timeout] = timeout + conn.options[:timeout] = timeout + conn.use OpenCensus::Trace::Integrations::FaradayMiddleware if Travis::Api::App::Middleware::OpenCensus.enabled? + conn.adapter :net_http + end + end + + def insights_url + Travis.config.new_insights.insights_url || raise(ConfigurationError, 'No Insights API URL configured!') + end + + def insights_auth_token + Travis.config.new_insights.insights_auth_token || raise(ConfigurationError, 'No Insights Auth Token configured!') + end + + def query_string_from_params(params) + params.delete_if { |_, v| v.nil? || v.empty? }.to_query + end + end +end diff --git a/lib/travis/api/v3/models/insights_collection.rb b/lib/travis/api/v3/models/insights_collection.rb new file mode 100644 index 0000000000..4b4f0c03f7 --- /dev/null +++ b/lib/travis/api/v3/models/insights_collection.rb @@ -0,0 +1,32 @@ +# frozen_string_literal: true + +module Travis::API::V3 + class Models::InsightsCollection + def initialize(collection, total_count) + @collection = collection + @total_count = total_count + end + + def count(*) + @total_count + end + + def limit(*) + self + end + + def offset(*) + self + end + + def map + return @collection.map unless block_given? + + @collection.map { |x| yield x } + end + + def to_sql + "insights_query:#{Time.now.to_i}" + end + end +end diff --git a/lib/travis/api/v3/models/insights_notification.rb b/lib/travis/api/v3/models/insights_notification.rb new file mode 100644 index 0000000000..a619616965 --- /dev/null +++ b/lib/travis/api/v3/models/insights_notification.rb @@ -0,0 +1,19 @@ +module Travis::API::V3 + class Models::InsightsNotification + attr_reader :id, :type, :active, :weight, :message, :plugin_name, :plugin_type, :plugin_category, :probe_severity, :description, :description_link + + def initialize(attributes = {}) + @id = attributes.fetch('id') + @type = attributes.fetch('type') + @active = attributes.fetch('active') + @weight = attributes.fetch('weight') + @message = attributes.fetch('message') + @plugin_name = attributes.fetch('plugin_name') + @plugin_type = attributes.fetch('plugin_type') + @plugin_category = attributes.fetch('plugin_category') + @probe_severity = attributes.fetch('probe_severity') + @description = attributes.fetch('description', '') + @description_link = attributes.fetch('description_link', '') + end + end +end diff --git a/lib/travis/api/v3/models/insights_plugin.rb b/lib/travis/api/v3/models/insights_plugin.rb new file mode 100644 index 0000000000..30fa4b9204 --- /dev/null +++ b/lib/travis/api/v3/models/insights_plugin.rb @@ -0,0 +1,17 @@ +module Travis::API::V3 + class Models::InsightsPlugin + attr_reader :id, :name, :public_id, :plugin_type, :plugin_category, :last_scan_end, :scan_status, :plugin_status, :active + + def initialize(attributes = {}) + @id = attributes.fetch('id') + @name = attributes.fetch('name') + @public_id = attributes.fetch('public_id') + @plugin_type = attributes.fetch('plugin_type') + @plugin_category = attributes.fetch('plugin_category') + @last_scan_end = attributes.fetch('last_scan_end') + @scan_status = attributes.fetch('scan_status') + @plugin_status = attributes.fetch('plugin_status') + @active = attributes.fetch('active') + end + end +end diff --git a/lib/travis/api/v3/models/insights_probe.rb b/lib/travis/api/v3/models/insights_probe.rb new file mode 100644 index 0000000000..1bf47a8cfd --- /dev/null +++ b/lib/travis/api/v3/models/insights_probe.rb @@ -0,0 +1,37 @@ +module Travis::API::V3 + class Models::InsightsProbe + attr_reader :id, :user_id, :user_plugin_id, :test_template_id, :uuid, :uuid_group, :type, + :notification, :description, :description_link, :test, :base_object_locator, :preconditions, :conditionals, + :object_key_locator, :active, :editable, :template_type, :cruncher_type, :status, :labels, :plugin_type, + :plugin_type_name, :plugin_category, :tag_list, :severity + + def initialize(attributes = {}) + @id = attributes.fetch('id') + @user_id = attributes.fetch('user_id') + @user_plugin_id = attributes.fetch('user_plugin_id') + @test_template_id = attributes.fetch('test_template_id') + @uuid = attributes.fetch('uuid') + @uuid_group = attributes.fetch('uuid_group') + @type = attributes.fetch('type') + @notification = attributes.fetch('notification') + @description = attributes.fetch('description') + @description_link = attributes.fetch('description_link') + @test = attributes.fetch('test') + @base_object_locator = attributes.fetch('base_object_locator') + @preconditions = attributes.fetch('preconditions') + @conditionals = attributes.fetch('conditionals') + @object_key_locator = attributes.fetch('object_key_locator') + @active = attributes.fetch('active') + @editable = attributes.fetch('editable') + @template_type = attributes.fetch('template_type') + @cruncher_type = attributes.fetch('cruncher_type') + @status = attributes.fetch('status', '') + @labels = attributes.fetch('labels') + @plugin_type = attributes.fetch('plugin_type') + @plugin_type_name = attributes.fetch('plugin_type_name', '') + @plugin_category = attributes.fetch('plugin_category') + @tag_list = attributes.fetch('tag_list') + @severity = attributes.fetch('severity') + end + end +end diff --git a/lib/travis/api/v3/models/insights_public_key.rb b/lib/travis/api/v3/models/insights_public_key.rb new file mode 100644 index 0000000000..62fae05d3b --- /dev/null +++ b/lib/travis/api/v3/models/insights_public_key.rb @@ -0,0 +1,11 @@ +module Travis::API::V3 + class Models::InsightsPublicKey + attr_reader :key_hash, :key_body, :ordinal_value + + def initialize(attributes = {}) + @key_hash = attributes.fetch('key_hash') + @key_body = attributes.fetch('key_body') + @ordinal_value = attributes.fetch('ordinal_value') + end + end +end diff --git a/lib/travis/api/v3/models/insights_tag.rb b/lib/travis/api/v3/models/insights_tag.rb new file mode 100644 index 0000000000..2566dd42f5 --- /dev/null +++ b/lib/travis/api/v3/models/insights_tag.rb @@ -0,0 +1,9 @@ +module Travis::API::V3 + class Models::InsightsTag + attr_reader :name + + def initialize(attributes = {}) + @name = attributes.fetch('name') + end + end +end diff --git a/lib/travis/api/v3/models/user_preferences.rb b/lib/travis/api/v3/models/user_preferences.rb index 91878210d5..ee31bbfe16 100644 --- a/lib/travis/api/v3/models/user_preferences.rb +++ b/lib/travis/api/v3/models/user_preferences.rb @@ -13,5 +13,15 @@ class Models::UserPreferences < Models::JsonSlice # repositories are always public) attribute :private_insights_visibility, String, default: 'private' validates :private_insights_visibility, inclusion: { in: %w{private public}, message: "'%{value}' is not allowed" } + + attribute :insights_scan_notifications, Boolean, default: true + + attribute :insights_time_zone, String, default: '' + + attribute :insights_date_format, String, default: '' + validates :insights_date_format, inclusion: { in: %w{DD/MM/YYYY MM/DD/YYYY YYYY/MM/DD}, message: "'%{value}' is not allowed" }, allow_blank: true + + attribute :insights_time_format, String, default: '' + validates :insights_time_format, inclusion: { in: ['h:mm:ss A', 'HH:mm:ss'], message: "'%{value}' is not allowed" }, allow_blank: true end end diff --git a/lib/travis/api/v3/queries/insights_notifications.rb b/lib/travis/api/v3/queries/insights_notifications.rb new file mode 100644 index 0000000000..1f5d39b57a --- /dev/null +++ b/lib/travis/api/v3/queries/insights_notifications.rb @@ -0,0 +1,25 @@ +module Travis::API::V3 + class Queries::InsightsNotifications < Query + params :filter, :page, :limit, :active, :sort_by, :sort_direction + + def all(user_id) + insights_client(user_id).user_notifications( + params['filter'], + params['page'], + params['active'], + params['sort_by'], + params['sort_direction'] + ) + end + + def toggle_snooze(user_id) + insights_client(user_id).toggle_snooze_user_notifications(params['notification_ids']) + end + + private + + def insights_client(user_id) + @_insights_client ||= InsightsClient.new(user_id) + end + end +end diff --git a/lib/travis/api/v3/queries/insights_plugins.rb b/lib/travis/api/v3/queries/insights_plugins.rb new file mode 100644 index 0000000000..23ebd073b9 --- /dev/null +++ b/lib/travis/api/v3/queries/insights_plugins.rb @@ -0,0 +1,54 @@ +module Travis::API::V3 + class Queries::InsightsPlugins < Query + params :filter, :page, :limit, :active, :sort_by, :sort_direction, :key_hash, :plugin_id, :name, :plugin_type, :public_id, + :private_key, :account_name, :app_key, :domain, :sub_plugin, :ids + + def all(user_id) + insights_client(user_id).user_plugins( + params['filter'], + params['page'], + params['active'], + params['sort_by'], + params['sort_direction'] + ) + end + + def create(user_id) + insights_client(user_id).create_plugin(params.slice(*%w(key_hash name plugin_type public_id private_key account_name app_key domain sub_plugin))) + end + + def toggle_active(user_id) + insights_client(user_id).toggle_active_plugins(params['ids']) + end + + def delete_many(user_id) + insights_client(user_id).delete_many_plugins(params['ids']) + end + + def run_scan(user_id) + insights_client(user_id).run_scan + end + + def generate_key(user_id) + insights_client(user_id).generate_key(params['plugin_name'], params['plugin_type']) + end + + def authenticate_key(user_id) + insights_client(user_id).authenticate_key(params) + end + + def template_plugin_tests(user_id) + insights_client(user_id).template_plugin_tests(params['plugin_type']) + end + + def get_scan_logs(user_id) + insights_client(user_id).get_scan_logs(params['plugin_id'], params['last_id']) + end + + private + + def insights_client(user_id) + @_insights_client ||= InsightsClient.new(user_id) + end + end +end diff --git a/lib/travis/api/v3/queries/insights_probes.rb b/lib/travis/api/v3/queries/insights_probes.rb new file mode 100644 index 0000000000..a8195280a5 --- /dev/null +++ b/lib/travis/api/v3/queries/insights_probes.rb @@ -0,0 +1,43 @@ +module Travis::API::V3 + class Queries::InsightsProbes < Query + params :filter, :page, :limit, :active, :sort_by, :sort_direction, :ids, + :test_template_id, :test, :plugin_type, + :notification, :description, :description_link, :type, :labels, :tag_list + + def all(user_id) + insights_client(user_id).probes( + params['filter'], + params['page'], + params['active'], + params['sort_by'], + params['sort_direction'] + ) + end + + def create(user_id) + insights_client(user_id).create_probe(params) + end + + def update(user_id) + insights_client(user_id).update_probe(params) + end + + def get(user_id) + insights_client(user_id).get_probe(params) + end + + def toggle_active(user_id) + insights_client(user_id).toggle_active_probes(params['ids']) + end + + def delete_many(user_id) + insights_client(user_id).delete_many_probes(params['ids']) + end + + private + + def insights_client(user_id) + @_insights_client ||= InsightsClient.new(user_id) + end + end +end diff --git a/lib/travis/api/v3/queries/insights_public_key.rb b/lib/travis/api/v3/queries/insights_public_key.rb new file mode 100644 index 0000000000..1c60fecb14 --- /dev/null +++ b/lib/travis/api/v3/queries/insights_public_key.rb @@ -0,0 +1,13 @@ +module Travis::API::V3 + class Queries::InsightsPublicKey < Query + def latest(user_id) + insights_client(user_id).public_key + end + + private + + def insights_client(user_id) + @_insights_client ||= InsightsClient.new(user_id) + end + end +end diff --git a/lib/travis/api/v3/queries/insights_sandbox.rb b/lib/travis/api/v3/queries/insights_sandbox.rb new file mode 100644 index 0000000000..3b9099a336 --- /dev/null +++ b/lib/travis/api/v3/queries/insights_sandbox.rb @@ -0,0 +1,23 @@ +module Travis::API::V3 + class Queries::InsightsSandbox < Query + params :plugin_type, :plugin_id, :query + + def plugins(user_id) + insights_client(user_id).sandbox_plugins(params['plugin_type']) + end + + def plugin_data(user_id) + insights_client(user_id).sandbox_plugin_data(params['plugin_id']) + end + + def run_query(user_id) + insights_client(user_id).sandbox_run_query(params['plugin_id'], params['query']) + end + + private + + def insights_client(user_id) + @_insights_client ||= InsightsClient.new(user_id) + end + end +end diff --git a/lib/travis/api/v3/queries/insights_tags.rb b/lib/travis/api/v3/queries/insights_tags.rb new file mode 100644 index 0000000000..0f885810e9 --- /dev/null +++ b/lib/travis/api/v3/queries/insights_tags.rb @@ -0,0 +1,13 @@ +module Travis::API::V3 + class Queries::InsightsTags < Query + def search_tags(user_id) + insights_client(user_id).search_tags + end + + private + + def insights_client(user_id) + @_insights_client ||= InsightsClient.new(user_id) + end + end +end diff --git a/lib/travis/api/v3/renderer/insights_notification.rb b/lib/travis/api/v3/renderer/insights_notification.rb new file mode 100644 index 0000000000..27f2d6ba2c --- /dev/null +++ b/lib/travis/api/v3/renderer/insights_notification.rb @@ -0,0 +1,6 @@ +module Travis::API::V3 + class Renderer::InsightsNotification < ModelRenderer + representation :standard, :id, :type, :active, :weight, :message, :plugin_name, :plugin_type, :plugin_category, :probe_severity, :description, :description_link + representation :minimal, :id, :type, :active, :weight, :probe_severity, :description, :description_link + end +end diff --git a/lib/travis/api/v3/renderer/insights_notifications.rb b/lib/travis/api/v3/renderer/insights_notifications.rb new file mode 100644 index 0000000000..ccd756a049 --- /dev/null +++ b/lib/travis/api/v3/renderer/insights_notifications.rb @@ -0,0 +1,6 @@ +module Travis::API::V3 + class Renderer::InsightsNotifications < CollectionRenderer + type :notifications + collection_key :notifications + end +end diff --git a/lib/travis/api/v3/renderer/insights_plugin.rb b/lib/travis/api/v3/renderer/insights_plugin.rb new file mode 100644 index 0000000000..3a69f8eae0 --- /dev/null +++ b/lib/travis/api/v3/renderer/insights_plugin.rb @@ -0,0 +1,6 @@ +module Travis::API::V3 + class Renderer::InsightsPlugin < ModelRenderer + representation :standard, :id, :name, :public_id, :plugin_type, :plugin_category, :last_scan_end, :scan_status, :plugin_status, :active + representation :minimal, :id, :name, :public_id, :plugin_type, :last_scan_end, :scan_status, :plugin_status, :active + end +end diff --git a/lib/travis/api/v3/renderer/insights_plugin_authenticate.rb b/lib/travis/api/v3/renderer/insights_plugin_authenticate.rb new file mode 100644 index 0000000000..bf65e8e7a2 --- /dev/null +++ b/lib/travis/api/v3/renderer/insights_plugin_authenticate.rb @@ -0,0 +1,19 @@ +module Travis::API::V3 + module Renderer::InsightsPluginAuthenticate + extend self + + AVAILABLE_ATTRIBUTES = [:success, :error_msg] + + def available_attributes + AVAILABLE_ATTRIBUTES + end + + def render(object, **) + { + '@type': 'insights_plugin_authenticate'.freeze, + success: object['success'], + error_msg: object['error_msg'] + } + end + end +end diff --git a/lib/travis/api/v3/renderer/insights_plugin_key.rb b/lib/travis/api/v3/renderer/insights_plugin_key.rb new file mode 100644 index 0000000000..40a7cbf0bf --- /dev/null +++ b/lib/travis/api/v3/renderer/insights_plugin_key.rb @@ -0,0 +1,18 @@ +module Travis::API::V3 + module Renderer::InsightsPluginKey + extend self + + AVAILABLE_ATTRIBUTES = [:keys] + + def available_attributes + AVAILABLE_ATTRIBUTES + end + + def render(object, **) + { + '@type': 'insights_plugin_key'.freeze, + keys: object['keys'] + } + end + end +end diff --git a/lib/travis/api/v3/renderer/insights_plugin_scan_logs.rb b/lib/travis/api/v3/renderer/insights_plugin_scan_logs.rb new file mode 100644 index 0000000000..e8ed9a8914 --- /dev/null +++ b/lib/travis/api/v3/renderer/insights_plugin_scan_logs.rb @@ -0,0 +1,19 @@ +module Travis::API::V3 + module Renderer::InsightsPluginScanLogs + extend self + + AVAILABLE_ATTRIBUTES = [:meta, :scan_logs] + + def available_attributes + AVAILABLE_ATTRIBUTES + end + + def render(object, **) + { + '@type': 'insights_plugin_scan_logs'.freeze, + meta: object.fetch('meta', {}), + scan_logs: object.fetch('scan_logs', []) + } + end + end +end diff --git a/lib/travis/api/v3/renderer/insights_plugin_tests.rb b/lib/travis/api/v3/renderer/insights_plugin_tests.rb new file mode 100644 index 0000000000..d3b04ef9fd --- /dev/null +++ b/lib/travis/api/v3/renderer/insights_plugin_tests.rb @@ -0,0 +1,19 @@ +module Travis::API::V3 + module Renderer::InsightsPluginTests + extend self + + AVAILABLE_ATTRIBUTES = [:template_tests, :plugin_category] + + def available_attributes + AVAILABLE_ATTRIBUTES + end + + def render(object, **) + { + '@type': 'insights_plugin_tests'.freeze, + template_tests: object['template_tests'], + plugin_category: object['plugin_category'] + } + end + end +end diff --git a/lib/travis/api/v3/renderer/insights_plugins.rb b/lib/travis/api/v3/renderer/insights_plugins.rb new file mode 100644 index 0000000000..38af87c850 --- /dev/null +++ b/lib/travis/api/v3/renderer/insights_plugins.rb @@ -0,0 +1,6 @@ +module Travis::API::V3 + class Renderer::InsightsPlugins < CollectionRenderer + type :plugins + collection_key :plugins + end +end diff --git a/lib/travis/api/v3/renderer/insights_probe.rb b/lib/travis/api/v3/renderer/insights_probe.rb new file mode 100644 index 0000000000..ac35db1c4e --- /dev/null +++ b/lib/travis/api/v3/renderer/insights_probe.rb @@ -0,0 +1,9 @@ +module Travis::API::V3 + class Renderer::InsightsProbe < ModelRenderer + representation :standard, :id, :user_id, :user_plugin_id, :test_template_id, :uuid, :uuid_group, :type, + :notification, :description, :description_link, :test, :base_object_locator, :preconditions, :conditionals, + :object_key_locator, :active, :editable, :template_type, + :cruncher_type, :status, :labels, :plugin_type, :plugin_type_name, :plugin_category, :tag_list, :severity + representation :minimal, :id, :type, :plugin_type, :plugin_type_name, :plugin_category, :label, :notification, :status, :tag_list, :severity + end +end diff --git a/lib/travis/api/v3/renderer/insights_probes.rb b/lib/travis/api/v3/renderer/insights_probes.rb new file mode 100644 index 0000000000..950797fd37 --- /dev/null +++ b/lib/travis/api/v3/renderer/insights_probes.rb @@ -0,0 +1,6 @@ +module Travis::API::V3 + class Renderer::InsightsProbes < CollectionRenderer + type :tests + collection_key :tests + end +end diff --git a/lib/travis/api/v3/renderer/insights_public_key.rb b/lib/travis/api/v3/renderer/insights_public_key.rb new file mode 100644 index 0000000000..fc3cf695d5 --- /dev/null +++ b/lib/travis/api/v3/renderer/insights_public_key.rb @@ -0,0 +1,5 @@ +module Travis::API::V3 + class Renderer::InsightsPublicKey < ModelRenderer + representation(:standard, :key_hash, :key_body, :ordinal_value) + end +end diff --git a/lib/travis/api/v3/renderer/insights_sandbox_plugin_data.rb b/lib/travis/api/v3/renderer/insights_sandbox_plugin_data.rb new file mode 100644 index 0000000000..04ea4a9f1f --- /dev/null +++ b/lib/travis/api/v3/renderer/insights_sandbox_plugin_data.rb @@ -0,0 +1,18 @@ +module Travis::API::V3 + module Renderer::InsightsSandboxPluginData + extend self + + AVAILABLE_ATTRIBUTES = [:data] + + def available_attributes + AVAILABLE_ATTRIBUTES + end + + def render(object, **) + { + '@type': 'insights_sandbox_plugin_data'.freeze, + data: object + } + end + end +end diff --git a/lib/travis/api/v3/renderer/insights_sandbox_plugins.rb b/lib/travis/api/v3/renderer/insights_sandbox_plugins.rb new file mode 100644 index 0000000000..75cfb8ce8a --- /dev/null +++ b/lib/travis/api/v3/renderer/insights_sandbox_plugins.rb @@ -0,0 +1,20 @@ +module Travis::API::V3 + module Renderer::InsightsSandboxPlugins + extend self + + AVAILABLE_ATTRIBUTES = [:plugins, :in_progress, :no_plugins] + + def available_attributes + AVAILABLE_ATTRIBUTES + end + + def render(object, **) + { + '@type': 'insights_sandbox_plugins'.freeze, + plugins: object.fetch('plugins', []), + in_progress: object.fetch('in_progress', false), + no_plugins: object.fetch('no_plugins', false) + } + end + end +end diff --git a/lib/travis/api/v3/renderer/insights_sandbox_query_result.rb b/lib/travis/api/v3/renderer/insights_sandbox_query_result.rb new file mode 100644 index 0000000000..f8d6d2b258 --- /dev/null +++ b/lib/travis/api/v3/renderer/insights_sandbox_query_result.rb @@ -0,0 +1,20 @@ +module Travis::API::V3 + module Renderer::InsightsSandboxQueryResult + extend self + + AVAILABLE_ATTRIBUTES = [:negative_results, :positive_results, :success] + + def available_attributes + AVAILABLE_ATTRIBUTES + end + + def render(object, **) + { + '@type': 'insights_sandbox_query_result'.freeze, + negative_results: object['negative_results'], + positive_results: object['positive_results'], + success: object['success'] + } + end + end +end diff --git a/lib/travis/api/v3/renderer/insights_tag.rb b/lib/travis/api/v3/renderer/insights_tag.rb new file mode 100644 index 0000000000..9531035702 --- /dev/null +++ b/lib/travis/api/v3/renderer/insights_tag.rb @@ -0,0 +1,6 @@ +module Travis::API::V3 + class Renderer::InsightsTag < ModelRenderer + representation :standard, :name + representation :minimal, :name + end +end diff --git a/lib/travis/api/v3/renderer/insights_tags.rb b/lib/travis/api/v3/renderer/insights_tags.rb new file mode 100644 index 0000000000..5489fd49ea --- /dev/null +++ b/lib/travis/api/v3/renderer/insights_tags.rb @@ -0,0 +1,6 @@ +module Travis::API::V3 + class Renderer::InsightsTags < CollectionRenderer + type :tags + collection_key :tags + end +end diff --git a/lib/travis/api/v3/routes.rb b/lib/travis/api/v3/routes.rb index 5ecd8407fa..90d9704f8f 100644 --- a/lib/travis/api/v3/routes.rb +++ b/lib/travis/api/v3/routes.rb @@ -426,5 +426,59 @@ module Routes route '/leads' post :create end + + resource :insights_notifications do + route '/insights_notifications' + get :all + patch :toggle_snooze, '/toggle_snooze' + end + + resource :insights_plugin do + route '/insights_plugin/{plugin_id}' + get :get_scan_logs, '/get_scan_logs' + end + + resource :insights_plugins do + route '/insights_plugins' + get :all + get :generate_key, '/generate_key' + post :create + post :authenticate_key, '/authenticate_key' + patch :toggle_active, '/toggle_active' + delete :delete_many, '/delete_many' + get :template_plugin_tests, '/template_plugin_tests' + get :run_scan, '/run_scan' + end + + resource :insights_probe do + route '/insights_probe/{probe_id}' + patch :update + get :get + end + + resource :insights_probes do + route '/insights_probes' + get :all + post :create + patch :toggle_active, '/toggle_active' + delete :delete_many, '/delete_many' + end + + resource :insights_sandbox do + route '/insights_sandbox' + post :plugins, '/plugins' + post :plugin_data, '/plugin_data' + post :run_query, '/run_query' + end + + resource :insights_public_key do + route '/insights_public_key' + get :latest + end + + resource :insights_tags do + route '/insights_tags' + get :search_tags + end end end diff --git a/lib/travis/api/v3/services.rb b/lib/travis/api/v3/services.rb index dc47f38fde..0a93bd8a90 100644 --- a/lib/travis/api/v3/services.rb +++ b/lib/travis/api/v3/services.rb @@ -30,6 +30,14 @@ module Services Executions = Module.new { extend Services } Gdpr = Module.new { extend Services } Insights = Module.new { extend Services } + InsightsNotifications = Module.new { extend Services } + InsightsPlugin = Module.new { extend Services } + InsightsPlugins = Module.new { extend Services } + InsightsProbe = Module.new { extend Services } + InsightsProbes = Module.new { extend Services } + InsightsPublicKey = Module.new { extend Services } + InsightsSandbox = Module.new { extend Services } + InsightsTags = Module.new { extend Services } Installation = Module.new { extend Services } Job = Module.new { extend Services } Jobs = Module.new { extend Services } diff --git a/lib/travis/api/v3/services/insights_notifications/all.rb b/lib/travis/api/v3/services/insights_notifications/all.rb new file mode 100644 index 0000000000..df4f0555ef --- /dev/null +++ b/lib/travis/api/v3/services/insights_notifications/all.rb @@ -0,0 +1,11 @@ +module Travis::API::V3 + class Services::InsightsNotifications::All < Service + params :filter, :page, :limit, :active, :sort_by, :sort_direction + paginate + + def run! + raise LoginRequired unless access_control.full_access_or_logged_in? + result query(:insights_notifications).all(access_control.user.id) + end + end +end diff --git a/lib/travis/api/v3/services/insights_notifications/toggle_snooze.rb b/lib/travis/api/v3/services/insights_notifications/toggle_snooze.rb new file mode 100644 index 0000000000..6cce4e475c --- /dev/null +++ b/lib/travis/api/v3/services/insights_notifications/toggle_snooze.rb @@ -0,0 +1,11 @@ +module Travis::API::V3 + class Services::InsightsNotifications::ToggleSnooze < Service + params :notification_ids + + def run! + raise LoginRequired unless access_control.full_access_or_logged_in? + query(:insights_notifications).toggle_snooze(access_control.user.id) + no_content + end + end +end diff --git a/lib/travis/api/v3/services/insights_plugin/get_scan_logs.rb b/lib/travis/api/v3/services/insights_plugin/get_scan_logs.rb new file mode 100644 index 0000000000..fa50996b9e --- /dev/null +++ b/lib/travis/api/v3/services/insights_plugin/get_scan_logs.rb @@ -0,0 +1,11 @@ +module Travis::API::V3 + class Services::InsightsPlugin::GetScanLogs < Service + params :plugin_id, :last_id + result_type :insights_plugin_scan_logs + + def run! + raise LoginRequired unless access_control.full_access_or_logged_in? + result query(:insights_plugins).get_scan_logs(access_control.user.id) + end + end +end diff --git a/lib/travis/api/v3/services/insights_plugins/all.rb b/lib/travis/api/v3/services/insights_plugins/all.rb new file mode 100644 index 0000000000..26c98ff58e --- /dev/null +++ b/lib/travis/api/v3/services/insights_plugins/all.rb @@ -0,0 +1,12 @@ +module Travis::API::V3 + class Services::InsightsPlugins::All < Service + params :filter, :page, :limit, :active, :sort_by, :sort_direction + result_type :insights_plugins + paginate + + def run! + raise LoginRequired unless access_control.full_access_or_logged_in? + result query(:insights_plugins).all(access_control.user.id) + end + end +end diff --git a/lib/travis/api/v3/services/insights_plugins/authenticate_key.rb b/lib/travis/api/v3/services/insights_plugins/authenticate_key.rb new file mode 100644 index 0000000000..a88b1e9ae3 --- /dev/null +++ b/lib/travis/api/v3/services/insights_plugins/authenticate_key.rb @@ -0,0 +1,11 @@ +module Travis::API::V3 + class Services::InsightsPlugins::AuthenticateKey < Service + params :plugin_type, :public_id, :private_key, :app_key, :domain, :key_hash + result_type :insights_plugin_authenticate + + def run! + raise LoginRequired unless access_control.full_access_or_logged_in? + result query(:insights_plugins).authenticate_key(access_control.user.id) + end + end +end diff --git a/lib/travis/api/v3/services/insights_plugins/create.rb b/lib/travis/api/v3/services/insights_plugins/create.rb new file mode 100644 index 0000000000..b2fe669589 --- /dev/null +++ b/lib/travis/api/v3/services/insights_plugins/create.rb @@ -0,0 +1,11 @@ +module Travis::API::V3 + class Services::InsightsPlugins::Create < Service + params :key_hash, :name, :plugin_type, :public_id, :private_key, :account_name, :app_key, :domain, :sub_plugin + result_type :insights_plugin + + def run! + raise LoginRequired unless access_control.full_access_or_logged_in? + result query(:insights_plugins).create(access_control.user.id) + end + end +end diff --git a/lib/travis/api/v3/services/insights_plugins/delete_many.rb b/lib/travis/api/v3/services/insights_plugins/delete_many.rb new file mode 100644 index 0000000000..1474847f9d --- /dev/null +++ b/lib/travis/api/v3/services/insights_plugins/delete_many.rb @@ -0,0 +1,12 @@ +module Travis::API::V3 + class Services::InsightsPlugins::DeleteMany < Service + params :ids + result_type :insights_plugins + paginate + + def run! + raise LoginRequired unless access_control.full_access_or_logged_in? + result query(:insights_plugins).delete_many(access_control.user.id) + end + end +end diff --git a/lib/travis/api/v3/services/insights_plugins/generate_key.rb b/lib/travis/api/v3/services/insights_plugins/generate_key.rb new file mode 100644 index 0000000000..6adcbd2e82 --- /dev/null +++ b/lib/travis/api/v3/services/insights_plugins/generate_key.rb @@ -0,0 +1,11 @@ +module Travis::API::V3 + class Services::InsightsPlugins::GenerateKey < Service + params :plugin_name, :plugin_type + result_type :insights_plugin_key + + def run! + raise LoginRequired unless access_control.full_access_or_logged_in? + result query(:insights_plugins).generate_key(access_control.user.id) + end + end +end diff --git a/lib/travis/api/v3/services/insights_plugins/run_scan.rb b/lib/travis/api/v3/services/insights_plugins/run_scan.rb new file mode 100644 index 0000000000..b41b25c2aa --- /dev/null +++ b/lib/travis/api/v3/services/insights_plugins/run_scan.rb @@ -0,0 +1,11 @@ +module Travis::API::V3 + class Services::InsightsPlugins::RunScan < Service + result_type :insights_plugins + paginate + + def run! + raise LoginRequired unless access_control.full_access_or_logged_in? + result query(:insights_plugins).run_scan(access_control.user.id) + end + end +end diff --git a/lib/travis/api/v3/services/insights_plugins/template_plugin_tests.rb b/lib/travis/api/v3/services/insights_plugins/template_plugin_tests.rb new file mode 100644 index 0000000000..bcac097a46 --- /dev/null +++ b/lib/travis/api/v3/services/insights_plugins/template_plugin_tests.rb @@ -0,0 +1,11 @@ +module Travis::API::V3 + class Services::InsightsPlugins::TemplatePluginTests < Service + params :plugin_type, :public_id, :private_key, :app_key, :domain, :key_hash + result_type :insights_plugin_tests + + def run! + raise LoginRequired unless access_control.full_access_or_logged_in? + result query(:insights_plugins).template_plugin_tests(access_control.user.id) + end + end +end diff --git a/lib/travis/api/v3/services/insights_plugins/toggle_active.rb b/lib/travis/api/v3/services/insights_plugins/toggle_active.rb new file mode 100644 index 0000000000..c20beb4113 --- /dev/null +++ b/lib/travis/api/v3/services/insights_plugins/toggle_active.rb @@ -0,0 +1,11 @@ +module Travis::API::V3 + class Services::InsightsPlugins::ToggleActive < Service + params :ids + paginate + + def run! + raise LoginRequired unless access_control.full_access_or_logged_in? + result query(:insights_plugins).toggle_active(access_control.user.id) + end + end +end diff --git a/lib/travis/api/v3/services/insights_probe/get.rb b/lib/travis/api/v3/services/insights_probe/get.rb new file mode 100644 index 0000000000..6766ba031f --- /dev/null +++ b/lib/travis/api/v3/services/insights_probe/get.rb @@ -0,0 +1,12 @@ +module Travis::API::V3 + class Services::InsightsProbe::Get < Service + params :test_template_id, :test, :plugin_type, + :notification, :description, :description_link, :type, :labels, :tag_list, :severity + result_type :insights_probe + + def run! + raise LoginRequired unless access_control.full_access_or_logged_in? + result query(:insights_probes).get(access_control.user.id) + end + end +end diff --git a/lib/travis/api/v3/services/insights_probe/update.rb b/lib/travis/api/v3/services/insights_probe/update.rb new file mode 100644 index 0000000000..44220dd973 --- /dev/null +++ b/lib/travis/api/v3/services/insights_probe/update.rb @@ -0,0 +1,12 @@ +module Travis::API::V3 + class Services::InsightsProbe::Update < Service + params :test_template_id, :test, :plugin_type, + :notification, :description, :description_link, :type, :labels, :tag_list, :severity + result_type :insights_probe + + def run! + raise LoginRequired unless access_control.full_access_or_logged_in? + result query(:insights_probes).update(access_control.user.id) + end + end +end diff --git a/lib/travis/api/v3/services/insights_probes/all.rb b/lib/travis/api/v3/services/insights_probes/all.rb new file mode 100644 index 0000000000..1b859be39b --- /dev/null +++ b/lib/travis/api/v3/services/insights_probes/all.rb @@ -0,0 +1,12 @@ +module Travis::API::V3 + class Services::InsightsProbes::All < Service + params :filter, :page, :limit, :active, :sort_by, :sort_direction + result_type :insights_probes + paginate + + def run! + raise LoginRequired unless access_control.full_access_or_logged_in? + result query(:insights_probes).all(access_control.user.id) + end + end +end diff --git a/lib/travis/api/v3/services/insights_probes/create.rb b/lib/travis/api/v3/services/insights_probes/create.rb new file mode 100644 index 0000000000..d3043f11ee --- /dev/null +++ b/lib/travis/api/v3/services/insights_probes/create.rb @@ -0,0 +1,12 @@ +module Travis::API::V3 + class Services::InsightsProbes::Create < Service + params :test_template_id, :test, :plugin_type, + :notification, :description, :description_link, :type, :labels, :tag_list, :severity + result_type :insights_probe + + def run! + raise LoginRequired unless access_control.full_access_or_logged_in? + result query(:insights_probes).create(access_control.user.id) + end + end +end diff --git a/lib/travis/api/v3/services/insights_probes/delete_many.rb b/lib/travis/api/v3/services/insights_probes/delete_many.rb new file mode 100644 index 0000000000..c21f648bfa --- /dev/null +++ b/lib/travis/api/v3/services/insights_probes/delete_many.rb @@ -0,0 +1,11 @@ +module Travis::API::V3 + class Services::InsightsProbes::DeleteMany < Service + params :ids + + def run! + raise LoginRequired unless access_control.full_access_or_logged_in? + query(:insights_probes).delete_many(access_control.user.id) + no_content + end + end +end diff --git a/lib/travis/api/v3/services/insights_probes/toggle_active.rb b/lib/travis/api/v3/services/insights_probes/toggle_active.rb new file mode 100644 index 0000000000..4aff1d0d26 --- /dev/null +++ b/lib/travis/api/v3/services/insights_probes/toggle_active.rb @@ -0,0 +1,11 @@ +module Travis::API::V3 + class Services::InsightsProbes::ToggleActive < Service + params :ids + + def run! + raise LoginRequired unless access_control.full_access_or_logged_in? + query(:insights_probes).toggle_active(access_control.user.id) + no_content + end + end +end diff --git a/lib/travis/api/v3/services/insights_public_key/latest.rb b/lib/travis/api/v3/services/insights_public_key/latest.rb new file mode 100644 index 0000000000..1235b7e52b --- /dev/null +++ b/lib/travis/api/v3/services/insights_public_key/latest.rb @@ -0,0 +1,8 @@ +module Travis::API::V3 + class Services::InsightsPublicKey::Latest < Service + def run! + raise LoginRequired unless access_control.full_access_or_logged_in? + result query(:insights_public_key).latest(access_control.user.id) + end + end +end diff --git a/lib/travis/api/v3/services/insights_sandbox/plugin_data.rb b/lib/travis/api/v3/services/insights_sandbox/plugin_data.rb new file mode 100644 index 0000000000..778ef5b99a --- /dev/null +++ b/lib/travis/api/v3/services/insights_sandbox/plugin_data.rb @@ -0,0 +1,11 @@ +module Travis::API::V3 + class Services::InsightsSandbox::PluginData < Service + params :plugin_type + result_type :insights_sandbox_plugin_data + + def run! + raise LoginRequired unless access_control.full_access_or_logged_in? + result query(:insights_sandbox).plugin_data(access_control.user.id) + end + end +end diff --git a/lib/travis/api/v3/services/insights_sandbox/plugins.rb b/lib/travis/api/v3/services/insights_sandbox/plugins.rb new file mode 100644 index 0000000000..a25f408972 --- /dev/null +++ b/lib/travis/api/v3/services/insights_sandbox/plugins.rb @@ -0,0 +1,11 @@ +module Travis::API::V3 + class Services::InsightsSandbox::Plugins < Service + params :plugin_type + result_type :insights_sandbox_plugins + + def run! + raise LoginRequired unless access_control.full_access_or_logged_in? + result query(:insights_sandbox).plugins(access_control.user.id) + end + end +end diff --git a/lib/travis/api/v3/services/insights_sandbox/run_query.rb b/lib/travis/api/v3/services/insights_sandbox/run_query.rb new file mode 100644 index 0000000000..5300de58af --- /dev/null +++ b/lib/travis/api/v3/services/insights_sandbox/run_query.rb @@ -0,0 +1,11 @@ +module Travis::API::V3 + class Services::InsightsSandbox::RunQuery < Service + params :plugin_id, :query + result_type :insights_sandbox_query_result + + def run! + raise LoginRequired unless access_control.full_access_or_logged_in? + result query(:insights_sandbox).run_query(access_control.user.id) + end + end +end diff --git a/lib/travis/api/v3/services/insights_tags/search_tags.rb b/lib/travis/api/v3/services/insights_tags/search_tags.rb new file mode 100644 index 0000000000..dc93f860cc --- /dev/null +++ b/lib/travis/api/v3/services/insights_tags/search_tags.rb @@ -0,0 +1,10 @@ +module Travis::API::V3 + class Services::InsightsTags::SearchTags < Service + result_type :insights_tags + + def run! + raise LoginRequired unless access_control.full_access_or_logged_in? + result query(:insights_tags).search_tags(access_control.user.id) + end + end +end diff --git a/lib/travis/config/defaults.rb b/lib/travis/config/defaults.rb index caedc2019c..bf4f37a577 100644 --- a/lib/travis/config/defaults.rb +++ b/lib/travis/config/defaults.rb @@ -45,6 +45,7 @@ def fallback_logs_api_auth_token closeio: { key: 'key' }, gdpr: {}, insights: { endpoint: 'https://insights.travis-ci.dev/', auth_token: 'secret' }, + new_insights: { insights_url: 'http://insights:3000', insights_auth_token: '660e632d4f3bfc6398ba5f6376be986d9ab18d6ee3723cdea8fbfe80c224dad8' }, database: { adapter: 'postgresql', database: "travis_#{Travis.env}", encoding: 'unicode', min_messages: 'warning', variables: { statement_timeout: 10_000 } }, fallback_logs_api: { url: fallback_logs_api_auth_url, token: fallback_logs_api_auth_token }, logs_api: { url: logs_api_url, token: logs_api_auth_token }, @@ -88,7 +89,7 @@ def fallback_logs_api_auth_token force_authentication: false, yml: { url: 'https://yml.travis-ci.org', token: 'secret', auth_key: 'abc123' }, read_only: ENV['READ_ONLY'] || false, - vcs: {} + vcs: {} default :_access => [:key] diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index f384c29916..addc91ec22 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -31,6 +31,7 @@ require 'auth/helpers' require 'support/active_record' require 'support/billing_spec_helper' +require 'support/insights_spec_helper' require 'support/env' require 'support/formats' require 'support/gcs' @@ -79,6 +80,7 @@ def parsed_body c.include Support::Env c.include Support::AuthHelpers, auth_helpers: true c.include Support::BillingSpecHelper, billing_spec_helper: true + c.include Support::InsightsSpecHelper, insights_spec_helper: true c.include Support::GdprSpecHelper, gdpr_spec_helper: true # for auth tests against staging, how the hell does this work, if at all diff --git a/spec/support/insights_spec_helper.rb b/spec/support/insights_spec_helper.rb new file mode 100644 index 0000000000..9ab362cfe5 --- /dev/null +++ b/spec/support/insights_spec_helper.rb @@ -0,0 +1,299 @@ +module Support + module InsightsSpecHelper + def stub_insights_request(method, path, query: '', auth_key:, user_id:) + url = URI(insights_url).tap do |url| + url.path = path + url.query = query + end.to_s + stub_request(method, url).with(headers: { 'X-Travis-User-Id' => user_id, 'Authorization' => "Token token=\"#{auth_key}\"" }) + end + + def insights_notifications_response + { + "data" => [ + { + "id"=>8, + "type"=>nil, + "active"=>true, + "weight"=>nil, + "message"=>"This is a test notification", + "plugin_name"=>"Travis Insights", + "plugin_type"=>"Travis Insights", + "plugin_category"=>"Monitoring", + "probe_severity"=>"high", + "description"=>"This is a test notification", + "description_link"=>nil + }, + { + "id"=>7, + "type"=>nil, + "active"=>true, + "weight"=>nil, + "message"=>"This is a test notification", + "plugin_name"=>"Travis Insights", + "plugin_type"=>"Travis Insights", + "plugin_category"=>"Monitoring", + "probe_severity"=>"high", + "description"=>"This is a test notification", + "description_link"=>nil + }, + ], + "total_count"=>2 + } + end + + def insights_probes_response + { + "data" => [ + { + "id"=>312, + "user_id"=>45, + "user_plugin_id"=>nil, + "test_template_id"=>312, + "uuid"=>"d0286ba6-ee08-4d87-9fb5-e8709fd9d2c3", + "uuid_group"=>"4bf1205a-e030-4da9-ad16-6d4ac2c654c3", + "type"=>"native", + "notification"=>"You need more plugins.", + "description"=>"Travis Insights description.", + "description_link"=>"link", + "test"=>"assert count($.Plugins) > 4", + "base_object_locator"=>nil, + "preconditions"=>nil, + "conditionals"=>nil, + "object_key_locator"=>nil, + "active"=>true, + "editable"=>false, + "template_type"=>"TestDefinitions::Sre::YouNeedMorePlugins", + "cruncher_type"=>"sreql", + "status"=>"Active", + "labels"=>{}, + "plugin_type"=>"sre", + "plugin_type_name"=>"Travis Insights", + "plugin_category"=>"Monitoring", + "tag_list"=> [ + { + "id"=>3, + "name"=>"TI", + "created_at"=>"2022-01-03T09:21:12.390Z", + "updated_at"=>"2022-01-03T09:21:12.390Z", + "taggings_count"=>1 + } + ], + "severity"=>"info" + }, + { + "id"=>313, + "user_id"=>45, + "user_plugin_id"=>nil, + "test_template_id"=>313, + "uuid"=>"f3abd5e4-8231-4afa-9b84-56bfa0264f34", + "uuid_group"=>"d968832e-1b04-4b05-b810-884d0fb5fdee", + "type"=>"native", + "notification"=>"You need some deployment pipeline plugins.", + "description"=>"Description", + "description_link"=>"", + "test"=>"assert count($.Plugins[@.plugin_category is \"deployment_pipeline\"]) > 0", + "base_object_locator"=>nil, + "preconditions"=>nil, + "conditionals"=>nil, + "object_key_locator"=>nil, + "active"=>true, + "editable"=>false, + "template_type"=>"TestDefinitions::Sre::YouNeedSomeDeploymentPipelinePlugins", + "cruncher_type"=>"sreql", + "status"=>"Active", + "labels"=>{}, + "plugin_type"=>"sre", + "plugin_type_name"=>"Travis Insights", + "plugin_category"=>"Monitoring", + "tag_list"=>[], + "severity"=>"high" + }, + ], + "total_count"=>2 + } + end + + def insights_create_probe_response(attributes={}) + { + "id"=>313, + "user_id"=>45, + "user_plugin_id"=>nil, + "test_template_id"=>313, + "uuid"=>"f3abd5e4-8231-4afa-9b84-56bfa0264f34", + "uuid_group"=>"d968832e-1b04-4b05-b810-884d0fb5fdee", + "type"=>"native", + "notification"=>"You need some deployment pipeline plugins.", + "description"=>"Description", + "description_link"=>"", + "test"=>"assert count($.Plugins[@.plugin_category is \"deployment_pipeline\"]) > 0", + "base_object_locator"=>nil, + "preconditions"=>nil, + "conditionals"=>nil, + "object_key_locator"=>nil, + "active"=>true, + "editable"=>false, + "template_type"=>"TestDefinitions::Sre::YouNeedSomeDeploymentPipelinePlugins", + "cruncher_type"=>"sreql", + "status"=>"Active", + "labels"=>{}, + "plugin_type"=>"sre", + "plugin_type_name"=>"Travis Insights", + "plugin_category"=>"Monitoring", + "tag_list"=>[], + "severity"=>"high" + }.deep_merge(attributes) + end + + def insights_plugins_response + { + "data"=> [ + { + "id"=>5, + "name"=>"KubePlugin", + "public_id"=>"TID6CD47CD6E26", + "plugin_type"=>"Kubernetes Cluster", + "plugin_category"=>"Monitoring", + "last_scan_end"=>nil, + "scan_status"=>"In Progress", + "plugin_status"=>"Active", + "active"=>true + }, + { + "id"=>3, + "name"=>"KubePlugin2", + "public_id"=>"TI74D0AACAC0BD", + "plugin_type"=>"Kubernetes Cluster", + "plugin_category"=>"Monitoring", + "last_scan_end"=>"2021-12-01 10:44:32", + "scan_status"=>"Success", + "plugin_status"=>"Active", + "active"=>true + } + ], + "total_count"=>2 + } + end + + def insights_create_plugin_response(attributes={}) + { + "plugin" => { + "id"=>3, + "name"=>"KubePlugin2", + "public_id"=>"TI74D0AACAC0BD", + "plugin_type"=>"Kubernetes Cluster", + "plugin_category"=>"Monitoring", + "last_scan_end"=>"2021-12-01 10:44:32", + "scan_status"=>"Success", + "plugin_status"=>"Active", + "active"=>true + }.deep_merge(attributes) + } + end + + def insights_public_key_response + { + "key_hash"=>"KEY_HASH", + "key_body"=>"PUBLIC_KEY", + "ordinal_value"=>1 + } + end + + def insights_authenticate_key_response + { + "success"=>true, + "error_msg"=>"" + } + end + + def insights_scan_log_response + { + "scan_logs"=>[ + { + "id"=>97396, + "user_plugin_id"=>255, + "test_template_id"=>nil, + "log_type"=>"notifications", + "text"=>"Scheduling scan", + "additional_text_type"=>nil, + "additional_text"=>nil, + "created_at"=>"2021-11-18 04:00:05" + }, + { + "id"=>97432, + "user_plugin_id"=>255, + "test_template_id"=>nil, + "log_type"=>"plugin", + "text"=>"Scan started at", + "additional_text_type"=>nil, + "additional_text"=>nil, + "created_at"=>"2021-11-18 04:00:07" + } + ], + "meta"=>{ + "scan_status_in_progress"=>true + } + } + end + + def insights_template_plugin_tests_response + { + "template_tests"=>[ + { + "id"=>3232, + "name"=>"This is a test probe" + }, + { + "id"=>3234, + "name"=>"This is a test probe 2" + } + ], + "plugin_category"=>"Monitoring" + } + end + + def insights_sandbox_plugins_response + { + "plugins"=>[ + { + "id"=>4, + "name"=>"Travis Insights", + "data"=>"{\n \"Plugins\": [\n {\n \"id\": 255,\n \"plugin_category\": \"monitoring\",\n \"plugin_type\": \"sre\",\n \"scan_logs\": [\n {\n \"additional_text\": null,\n \"additional_text_type\": null,\n \"created_at\": \"2021-11-18T04:00:05.072Z\",\n \"id\": 97396,\n \"log_type\": \"notifications\",\n \"tenant_id\": 39,\n \"test_template_id\": null,\n \"text\": \"Scheduling scan\",\n \"updated_at\": \"2021-11-18T04:00:05.072Z\",\n \"user_plugin_id\": 255\n },\n {\n \"additional_text\": null,\n \"additional_text_type\": null,\n \"created_at\": \"2021-11-18T04:00:07.010Z\",\n \"id\": 97432,\n \"log_type\": \"plugin\",\n \"tenant_id\": 39,\n \"test_template_id\": null,\n \"text\": \"Scan started at\",\n \"updated_at\": \"2021-11-18T04:00:07.010Z\",\n \"user_plugin_id\": 255\n },\n {\n \"additional_text\": \"\",\n \"additional_text_type\": \"\",\n \"created_at\": \"2021-11-18T04:00:07.068Z\",\n \"id\": 97435,\n \"log_type\": \"plugin\",\n \"tenant_id\": 39,\n \"test_template_id\": null,\n \"text\": \"Accessing APIs:\",\n \"updated_at\": \"2021-11-18T04:00:07.068Z\",\n \"user_plugin_id\": 255\n },\n {\n \"additional_text\": \"- User Plugins\",\n \"additional_text_type\": \"info\",\n \"created_at\": \"2021-11-18T04:00:07.148Z\",\n \"id\": 97438,\n \"log_type\": \"plugin\",\n \"tenant_id\": 39,\n \"test_template_id\": null,\n \"text\": \"\",\n \"updated_at\": \"2021-11-18T04:00:07.148Z\",\n \"user_plugin_id\": 255\n }\n ],\n \"user_id\": 28\n }\n ]\n}", + "ready"=>true + } + ] + } + end + + def insights_sandbox_plugin_data_response + "{\n \"Plugins\": [\n {\n \"id\": 255,\n \"plugin_category\": \"monitoring\",\n \"plugin_type\": \"sre\",\n \"scan_logs\": [\n {\n \"additional_text\": null,\n \"additional_text_type\": null,\n \"created_at\": \"2021-11-18T04:00:05.072Z\",\n \"id\": 97396,\n \"log_type\": \"notifications\",\n \"tenant_id\": 39,\n \"test_template_id\": null,\n \"text\": \"Scheduling scan\",\n \"updated_at\": \"2021-11-18T04:00:05.072Z\",\n \"user_plugin_id\": 255\n },\n {\n \"additional_text\": null,\n \"additional_text_type\": null,\n \"created_at\": \"2021-11-18T04:00:07.010Z\",\n \"id\": 97432,\n \"log_type\": \"plugin\",\n \"tenant_id\": 39,\n \"test_template_id\": null,\n \"text\": \"Scan started at\",\n \"updated_at\": \"2021-11-18T04:00:07.010Z\",\n \"user_plugin_id\": 255\n },\n {\n \"additional_text\": \"\",\n \"additional_text_type\": \"\",\n \"created_at\": \"2021-11-18T04:00:07.068Z\",\n \"id\": 97435,\n \"log_type\": \"plugin\",\n \"tenant_id\": 39,\n \"test_template_id\": null,\n \"text\": \"Accessing APIs:\",\n \"updated_at\": \"2021-11-18T04:00:07.068Z\",\n \"user_plugin_id\": 255\n },\n {\n \"additional_text\": \"- User Plugins\",\n \"additional_text_type\": \"info\",\n \"created_at\": \"2021-11-18T04:00:07.148Z\",\n \"id\": 97438,\n \"log_type\": \"plugin\",\n \"tenant_id\": 39,\n \"test_template_id\": null,\n \"text\": \"\",\n \"updated_at\": \"2021-11-18T04:00:07.148Z\",\n \"user_plugin_id\": 255\n }\n ],\n \"user_id\": 28\n }\n ]\n}" + end + + def insights_sandbox_query_response + { + "negative_results"=>[ + false + ], + "positive_results"=>nil, + "success"=>true + } + end + + def insights_tags_response + [ + { 'name'=>'Tag1' }, + { 'name'=>'Tag2' }, + { 'name'=>'Tag3' } + ] + end + + def insights_generate_key_response + { + "keys" => [ + "TIDE0C7A9C1D5E", + "a8f702e9363e8573dd476c116e62cf6e04e44c8610dc939c67e45777f2b6cbdb" + ] + } + end + end +end diff --git a/spec/v3/insights_client_spec.rb b/spec/v3/insights_client_spec.rb new file mode 100644 index 0000000000..874c4ccc3d --- /dev/null +++ b/spec/v3/insights_client_spec.rb @@ -0,0 +1,406 @@ +describe Travis::API::V3::InsightsClient, insights_spec_helper: true do + let(:insights) { described_class.new(user_id) } + let(:user_id) { rand(999) } + let(:insights_url) { 'https://new-insights.travis-ci.com/' } + let(:auth_key) { 'supersecret' } + + before do + Travis.config.new_insights.insights_url = insights_url + Travis.config.new_insights.insights_auth_token = auth_key + end + + describe '#user_notifications' do + let(:filter) { nil } + let(:page) { '1' } + let(:active) { '0' } + let(:sort_by) { 'probe_severity' } + let(:sort_direction) { 'desc' } + + subject { insights.user_notifications(filter, page, active, sort_by, sort_direction) } + + it 'requests user notifications with specified query' do + stub_insights_request(:get, '/user_notifications', query: "page=#{page}&active=#{active}&order=#{sort_by}&order_dir=#{sort_direction}", auth_key: auth_key, user_id: user_id) + .to_return(body: JSON.dump(insights_notifications_response)) + expect(subject).to be_a(Travis::API::V3::Models::InsightsCollection) + expect(subject.map { |e| e }.first).to be_a(Travis::API::V3::Models::InsightsNotification) + expect(subject.map { |e| e }.size).to eq(insights_notifications_response['data'].size) + expect(subject.count).to eq(insights_notifications_response['total_count']) + end + end + + describe '#toggle_snooze_user_notifications' do + let(:notification_ids) { [123, 345] } + subject { insights.toggle_snooze_user_notifications(notification_ids) } + + it 'requests the toggle of user notifications' do + stubbed_request = stub_insights_request(:put, '/user_notifications/toggle_snooze', auth_key: auth_key, user_id: user_id) + .with(body: JSON.dump(snooze_ids: notification_ids)) + .to_return(status: 204) + + expect { subject }.to_not raise_error + expect(stubbed_request).to have_been_made + end + end + + describe '#user_plugins' do + let(:filter) { nil } + let(:page) { '1' } + let(:active) { '1' } + let(:sort_by) { 'name' } + let(:sort_direction) { 'desc' } + + subject { insights.user_plugins(filter, page, active, sort_by, sort_direction) } + + it 'requests user plugins with specified query' do + stub_insights_request(:get, '/user_plugins', query: "page=#{page}&active=#{active}&order=#{sort_by}&order_dir=#{sort_direction}", auth_key: auth_key, user_id: user_id) + .to_return(body: JSON.dump(insights_plugins_response)) + expect(subject).to be_a(Travis::API::V3::Models::InsightsCollection) + expect(subject.map { |e| e }.first).to be_a(Travis::API::V3::Models::InsightsPlugin) + expect(subject.map { |e| e }.size).to eq(insights_plugins_response['data'].size) + expect(subject.count).to eq(insights_plugins_response['total_count']) + end + end + + describe '#create_plugin' do + let(:name) { 'Test Plugin' } + let(:plugin_data) { { 'name' => name } } + subject { insights.create_plugin(plugin_data) } + + it 'requests the creation and returns the representation' do + stubbed_request = stub_insights_request(:post, '/user_plugins', auth_key: auth_key, user_id: user_id) + .with(body: JSON.dump(user_plugin: plugin_data)) + .to_return(status: 201, body: JSON.dump(insights_create_plugin_response('name' => name))) + + expect(subject).to be_a(Travis::API::V3::Models::InsightsPlugin) + expect(subject.name).to eq(name) + expect(stubbed_request).to have_been_made + end + end + + describe '#toggle_active_plugins' do + let(:plugin_ids) { [123, 345] } + subject { insights.toggle_active_plugins(plugin_ids) } + + it 'requests the toggle of plugins' do + stubbed_request = stub_insights_request(:put, '/user_plugins/toggle_active', auth_key: auth_key, user_id: user_id) + .with(body: JSON.dump(toggle_ids: plugin_ids)) + .to_return(status: 200, body: '') + + expect { subject }.to_not raise_error + expect(stubbed_request).to have_been_made + end + end + + describe '#delete_many_plugins' do + let(:plugin_ids) { [123, 345] } + subject { insights.delete_many_plugins(plugin_ids) } + + it 'requests the delete' do + stubbed_request = stub_insights_request(:delete, '/user_plugins/delete_many', query: { delete_ids: plugin_ids }.to_query, auth_key: auth_key, user_id: user_id) + .to_return(status: 200, body: '') + + expect { subject }.to_not raise_error + expect(stubbed_request).to have_been_made + end + end + + describe '#run_scan' do + subject { insights.run_scan } + + it 'requests to run scan' do + stubbed_request = stub_insights_request(:get, '/user_plugins/run_scan', auth_key: auth_key, user_id: user_id) + .to_return(status: 200, body: '') + + expect { subject }.to_not raise_error + expect(stubbed_request).to have_been_made + end + end + + describe '#generate_key' do + let(:plugin_name) { 'name' } + let(:plugin_type) { 'type' } + subject { insights.generate_key(plugin_name, plugin_type) } + + it 'requests the creation and returns the representation' do + stubbed_request = stub_insights_request(:get, '/user_plugins/generate_key', query: { name: plugin_name, plugin_type: plugin_type }.to_query, auth_key: auth_key, user_id: user_id) + .to_return(status: 201, body: JSON.dump(insights_generate_key_response)) + + expect(subject['keys'][0]).to eq('TIDE0C7A9C1D5E') + expect(stubbed_request).to have_been_made + end + end + + describe '#authenticate_key' do + let(:key_data) { { 'public_id' => 'id', 'private_key' => 'key' } } + subject { insights.authenticate_key(key_data) } + + it 'requests the creation and returns the representation' do + stubbed_request = stub_insights_request(:post, '/user_plugins/authenticate_key', auth_key: auth_key, user_id: user_id) + .with(body: JSON.dump(key_data)) + .to_return(status: 201, body: JSON.dump(insights_authenticate_key_response)) + + expect(subject['success']).to be_truthy + expect(stubbed_request).to have_been_made + end + end + + describe '#template_plugin_tests' do + let(:plugin_type) { 'sre' } + subject { insights.template_plugin_tests(plugin_type) } + + it 'requests the template tests' do + stubbed_request = stub_insights_request(:get, "/user_plugins/#{plugin_type}/template_plugin_tests", auth_key: auth_key, user_id: user_id) + .to_return(status: 201, body: JSON.dump(insights_template_plugin_tests_response)) + + expect(subject['template_tests']).to eq(insights_template_plugin_tests_response['template_tests']) + expect(subject['plugin_category']).to eq(insights_template_plugin_tests_response['plugin_category']) + expect(stubbed_request).to have_been_made + end + end + + describe '#get_scan_logs' do + subject { insights.get_scan_logs(plugin_id, last_id) } + + context 'when last_id is not present' do + let(:plugin_id) { rand(999) } + let(:last_id) { nil } + + it 'requests scan logs for specified plugin' do + stub_insights_request(:get, "/user_plugins/#{plugin_id}/get_scan_logs", auth_key: auth_key, user_id: user_id) + .to_return(body: JSON.dump(insights_scan_log_response)) + + expect(subject['scan_logs']).to eq(insights_scan_log_response['scan_logs']) + end + end + + context 'when last_id is present' do + let(:plugin_id) { rand(999) } + let(:last_id) { rand(999) } + + it 'requests scan logs for specified plugin' do + stub_insights_request(:get, "/user_plugins/#{plugin_id}/get_scan_logs", query: "last=#{last_id}&poll=true", auth_key: auth_key, user_id: user_id) + .to_return(body: JSON.dump(insights_scan_log_response)) + + expect(subject['scan_logs']).to eq(insights_scan_log_response['scan_logs']) + end + end + end + + describe '#probes' do + let(:filter) { nil } + let(:page) { '1' } + let(:active) { '1' } + let(:sort_by) { 'name' } + let(:sort_direction) { 'desc' } + + subject { insights.probes(filter, page, active, sort_by, sort_direction) } + + it 'requests probes with specified query' do + stub_insights_request(:get, '/probes', query: "page=#{page}&active=#{active}&order=#{sort_by}&order_dir=#{sort_direction}", auth_key: auth_key, user_id: user_id) + .to_return(body: JSON.dump(insights_probes_response)) + expect(subject).to be_a(Travis::API::V3::Models::InsightsCollection) + expect(subject.map { |e| e }.first).to be_a(Travis::API::V3::Models::InsightsProbe) + expect(subject.map { |e| e }.size).to eq(insights_probes_response['data'].size) + expect(subject.count).to eq(insights_probes_response['total_count']) + end + end + + describe '#create_probe' do + let(:notification) { 'Test Probe' } + let(:probe_data) { { 'notification' => notification } } + subject { insights.create_probe(probe_data) } + + it 'requests the creation and returns the representation' do + stubbed_request = stub_insights_request(:post, '/probes', auth_key: auth_key, user_id: user_id) + .with(body: JSON.dump(test_template: probe_data)) + .to_return(status: 201, body: JSON.dump(insights_create_probe_response('notification' => notification))) + + expect(subject).to be_a(Travis::API::V3::Models::InsightsProbe) + expect(subject.notification).to eq(notification) + expect(stubbed_request).to have_been_made + end + end + + describe '#update_probe' do + let(:probe_id) { 444 } + let(:notification) { 'Test Probe' } + let(:probe_data) { { 'probe_id' => probe_id, 'notification' => notification } } + subject { insights.update_probe(probe_data) } + + it 'requests the update' do + stubbed_request = stub_insights_request(:patch, "/probes/#{probe_id}", auth_key: auth_key, user_id: user_id) + .with(body: JSON.dump(probe_data)) + .to_return(status: 201, body: JSON.dump(insights_create_probe_response('id' => probe_id, 'notification' => notification))) + + expect(subject).to be_a(Travis::API::V3::Models::InsightsProbe) + expect(subject.id).to eq(probe_id) + expect(subject.notification).to eq(notification) + expect(stubbed_request).to have_been_made + end + end + + describe '#get_probe' do + let(:probe_id) { 444 } + let(:probe_data) { { 'probe_id' => probe_id } } + subject { insights.get_probe(probe_data) } + + it 'requests the probe returns the representation' do + stubbed_request = stub_insights_request(:get, "/probes/#{probe_id}/template_test", query: "probe_id=#{probe_id}", auth_key: auth_key, user_id: user_id) + .to_return(status: 201, body: JSON.dump(insights_create_probe_response('id' => probe_id))) + + expect(subject).to be_a(Travis::API::V3::Models::InsightsProbe) + expect(subject.id).to eq(probe_id) + expect(stubbed_request).to have_been_made + end + end + + describe '#toggle_active_probes' do + let(:probe_ids) { [123, 345] } + subject { insights.toggle_active_probes(probe_ids) } + + it 'requests the toggle of probes' do + stubbed_request = stub_insights_request(:put, '/probes/toggle_active', auth_key: auth_key, user_id: user_id) + .with(body: JSON.dump(toggle_ids: probe_ids)) + .to_return(status: 200, body: '') + + expect { subject }.to_not raise_error + expect(stubbed_request).to have_been_made + end + end + + describe '#delete_many_probes' do + let(:probe_ids) { [123, 345] } + subject { insights.delete_many_probes(probe_ids) } + + it 'requests the delete' do + stubbed_request = stub_insights_request(:delete, '/probes/delete_many', query: { delete_ids: probe_ids }.to_query, auth_key: auth_key, user_id: user_id) + .to_return(status: 200, body: '') + + expect { subject }.to_not raise_error + expect(stubbed_request).to have_been_made + end + end + + describe '#sandbox_plugins' do + let(:plugin_type) { 'sre' } + subject { insights.sandbox_plugins(plugin_type) } + + it 'requests the sandbox plugins and returns the representation' do + stubbed_request = stub_insights_request(:post, '/sandbox/plugins', auth_key: auth_key, user_id: user_id) + .to_return(status: 201, body: JSON.dump(insights_sandbox_plugins_response)) + + expect(subject['name']).to eq(insights_sandbox_plugins_response['name']) + expect(subject['data']).to eq(insights_sandbox_plugins_response['data']) + expect(stubbed_request).to have_been_made + end + end + + describe '#sandbox_plugin_data' do + let(:plugin_id) { 333 } + subject { insights.sandbox_plugin_data(plugin_id) } + + it 'requests the plugin sandbox data and returns the representation' do + stubbed_request = stub_insights_request(:post, '/sandbox/plugin_data', auth_key: auth_key, user_id: user_id) + .to_return(status: 201, body: insights_sandbox_plugin_data_response) + + expect(subject).to eq(JSON.parse(insights_sandbox_plugin_data_response)) + expect(stubbed_request).to have_been_made + end + end + + describe '#sandbox_run_query' do + let(:plugin_id) { 333 } + let(:query) { 'assert count($.Plugins) > 4' } + subject { insights.sandbox_run_query(plugin_id, query) } + + it 'requests the result of query and returns the representation' do + stubbed_request = stub_insights_request(:post, '/sandbox/run_query', auth_key: auth_key, user_id: user_id) + .to_return(status: 201, body: JSON.dump(insights_sandbox_query_response)) + + expect(subject['positive_results']).to eq(insights_sandbox_query_response['positive_results']) + expect(subject['negative_results']).to eq(insights_sandbox_query_response['negative_results']) + expect(stubbed_request).to have_been_made + end + end + + describe '#public_key' do + subject { insights.public_key } + + it 'requests the public key' do + stubbed_request = stub_insights_request(:get, '/api/v1/public_keys/latest.json', auth_key: auth_key, user_id: user_id) + .to_return(status: 201, body: JSON.dump(insights_public_key_response)) + + expect(subject).to be_a(Travis::API::V3::Models::InsightsPublicKey) + expect(subject.key_hash).to eq(insights_public_key_response['key_hash']) + expect(stubbed_request).to have_been_made + end + end + + describe '#search_tags' do + subject { insights.search_tags } + + it 'requests available tags' do + stubbed_request = stub_insights_request(:get, '/tags', auth_key: auth_key, user_id: user_id) + .to_return(status: 201, body: JSON.dump(insights_tags_response)) + + expect(subject.first).to be_a(Travis::API::V3::Models::InsightsTag) + expect(subject.first.name).to eq(insights_tags_response[0]['name']) + expect(stubbed_request).to have_been_made + end + end + + describe 'error handling' do + subject { insights.search_tags } + + it 'returns true when 202' do + stubbed_request = stub_insights_request(:get, '/tags', auth_key: auth_key, user_id: user_id) + .to_return(status: 202) + + expect(subject).to be_truthy + expect(stubbed_request).to have_been_made + end + + it 'returns true when 204' do + stubbed_request = stub_insights_request(:get, '/tags', auth_key: auth_key, user_id: user_id) + .to_return(status: 204) + + expect(subject).to be_truthy + expect(stubbed_request).to have_been_made + end + + it 'raises error when 400' do + stubbed_request = stub_insights_request(:get, '/tags', auth_key: auth_key, user_id: user_id) + .to_return(status: 400, body: JSON.dump({error: 'error text'})) + + expect { subject }.to raise_error(Travis::API::V3::ClientError) + end + + it 'raises error when 403' do + stubbed_request = stub_insights_request(:get, '/tags', auth_key: auth_key, user_id: user_id) + .to_return(status: 403, body: JSON.dump({rejection_code: 'error text'})) + + expect { subject }.to raise_error(Travis::API::V3::InsufficientAccess) + end + + it 'raises error when 404' do + stubbed_request = stub_insights_request(:get, '/tags', auth_key: auth_key, user_id: user_id) + .to_return(status: 404, body: JSON.dump({error: 'error text'})) + + expect { subject }.to raise_error(Travis::API::V3::NotFound) + end + + it 'raises error when 422' do + stubbed_request = stub_insights_request(:get, '/tags', auth_key: auth_key, user_id: user_id) + .to_return(status: 422, body: JSON.dump({error: 'error text'})) + + expect { subject }.to raise_error(Travis::API::V3::UnprocessableEntity) + end + + it 'raises error when 500' do + stubbed_request = stub_insights_request(:get, '/tags', auth_key: auth_key, user_id: user_id) + .to_return(status: 500) + + expect { subject }.to raise_error(Travis::API::V3::ServerError) + end + end +end \ No newline at end of file diff --git a/spec/v3/models/insights_collection_spec.rb b/spec/v3/models/insights_collection_spec.rb new file mode 100644 index 0000000000..75ae823d32 --- /dev/null +++ b/spec/v3/models/insights_collection_spec.rb @@ -0,0 +1,36 @@ +describe Travis::API::V3::Models::InsightsCollection do + let(:collection) { [ { id: 1, name: 'test1' }, { id: 2, name: 'test2' }, { id: 3, name: 'test3' } ] } + subject { Travis::API::V3::Models::InsightsCollection.new(collection, collection.count) } + + describe "#count" do + it 'returns total_count' do + expect(subject.count).to eq(collection.count) + end + end + + describe "#limit" do + it 'returns self' do + expect(subject.limit).to eq(subject) + end + end + + describe "#offset" do + it 'returns self' do + expect(subject.offset).to eq(subject) + end + end + + describe "#map" do + it 'returns map on collection' do + expect(subject.map { |e| e[:id] }).to eq([1, 2, 3]) + end + end + + describe "#to_sql" do + before { Timecop.freeze(Time.now.utc) } + + it 'returns placeholder string' do + expect(subject.to_sql).to eq("insights_query:#{Time.now.to_i}") + end + end +end diff --git a/spec/v3/renderer/insights_plugin_authenticate_spec.rb b/spec/v3/renderer/insights_plugin_authenticate_spec.rb new file mode 100644 index 0000000000..4e1e32022e --- /dev/null +++ b/spec/v3/renderer/insights_plugin_authenticate_spec.rb @@ -0,0 +1,23 @@ +describe Travis::API::V3::Renderer::InsightsPluginAuthenticate do + let(:object) { { 'success' => 'test', 'error_msg' => nil } } + + subject { Travis::API::V3::Renderer::InsightsPluginAuthenticate } + + describe "basic check" do + it "returns a basic representation of the object" do + expect(subject.render(object)).to eq( + { + '@type': 'insights_plugin_authenticate', + success: object['success'], + error_msg: object['error_msg'] + } + ) + end + end + + describe '#available_attributes' do + it 'returns available attributes' do + expect(subject.available_attributes).to eq([:success, :error_msg]) + end + end +end diff --git a/spec/v3/renderer/insights_plugin_key_spec.rb b/spec/v3/renderer/insights_plugin_key_spec.rb new file mode 100644 index 0000000000..2c2715e9de --- /dev/null +++ b/spec/v3/renderer/insights_plugin_key_spec.rb @@ -0,0 +1,22 @@ +describe Travis::API::V3::Renderer::InsightsPluginKey do + let(:object) { { 'keys' => ['test', 'test2'] } } + + subject { Travis::API::V3::Renderer::InsightsPluginKey } + + describe "basic check" do + it "returns a basic representation of the object" do + expect(subject.render(object)).to eq( + { + '@type': 'insights_plugin_key', + keys: object['keys'] + } + ) + end + end + + describe '#available_attributes' do + it 'returns available attributes' do + expect(subject.available_attributes).to eq([:keys]) + end + end +end diff --git a/spec/v3/renderer/insights_plugin_scan_logs_spec.rb b/spec/v3/renderer/insights_plugin_scan_logs_spec.rb new file mode 100644 index 0000000000..f92f60887a --- /dev/null +++ b/spec/v3/renderer/insights_plugin_scan_logs_spec.rb @@ -0,0 +1,23 @@ +describe Travis::API::V3::Renderer::InsightsPluginScanLogs do + let(:object) { { 'meta' => { 'key' => 'test' }, 'scan_logs' => ['test', 'test2'] } } + + subject { Travis::API::V3::Renderer::InsightsPluginScanLogs } + + describe "basic check" do + it "returns a basic representation of the object" do + expect(subject.render(object)).to eq( + { + '@type': 'insights_plugin_scan_logs', + meta: object['meta'], + scan_logs: object['scan_logs'] + } + ) + end + end + + describe '#available_attributes' do + it 'returns available attributes' do + expect(subject.available_attributes).to eq([:meta, :scan_logs]) + end + end +end diff --git a/spec/v3/renderer/insights_plugin_tests_spec.rb b/spec/v3/renderer/insights_plugin_tests_spec.rb new file mode 100644 index 0000000000..9a7bfa6d5b --- /dev/null +++ b/spec/v3/renderer/insights_plugin_tests_spec.rb @@ -0,0 +1,23 @@ +describe Travis::API::V3::Renderer::InsightsPluginTests do + let(:object) { { 'template_tests' => { 'key' => 'test' }, 'plugin_category' => 'test' } } + + subject { Travis::API::V3::Renderer::InsightsPluginTests } + + describe "basic check" do + it "returns a basic representation of the object" do + expect(subject.render(object)).to eq( + { + '@type': 'insights_plugin_tests', + template_tests: object['template_tests'], + plugin_category: object['plugin_category'] + } + ) + end + end + + describe '#available_attributes' do + it 'returns available attributes' do + expect(subject.available_attributes).to eq([:template_tests, :plugin_category]) + end + end +end diff --git a/spec/v3/renderer/insights_sandbox_plugin_data_spec.rb b/spec/v3/renderer/insights_sandbox_plugin_data_spec.rb new file mode 100644 index 0000000000..49719c76f8 --- /dev/null +++ b/spec/v3/renderer/insights_sandbox_plugin_data_spec.rb @@ -0,0 +1,22 @@ +describe Travis::API::V3::Renderer::InsightsSandboxPluginData do + let(:object) { { 'key' => 'test', 'key2' => 'test' } } + + subject { Travis::API::V3::Renderer::InsightsSandboxPluginData } + + describe "basic check" do + it "returns a basic representation of the object" do + expect(subject.render(object)).to eq( + { + '@type': 'insights_sandbox_plugin_data', + data: object + } + ) + end + end + + describe '#available_attributes' do + it 'returns available attributes' do + expect(subject.available_attributes).to eq([:data]) + end + end +end diff --git a/spec/v3/renderer/insights_sandbox_plugins_spec.rb b/spec/v3/renderer/insights_sandbox_plugins_spec.rb new file mode 100644 index 0000000000..774d2bb4df --- /dev/null +++ b/spec/v3/renderer/insights_sandbox_plugins_spec.rb @@ -0,0 +1,24 @@ +describe Travis::API::V3::Renderer::InsightsSandboxPlugins do + let(:object) { { 'in_progress' => false, 'no_plugins' => false, 'plugins' => ['test'] } } + + subject { Travis::API::V3::Renderer::InsightsSandboxPlugins } + + describe "basic check" do + it "returns a basic representation of the object" do + expect(subject.render(object)).to eq( + { + '@type': 'insights_sandbox_plugins', + plugins: object['plugins'], + in_progress: object['in_progress'], + no_plugins: object['no_plugins'] + } + ) + end + end + + describe '#available_attributes' do + it 'returns available attributes' do + expect(subject.available_attributes).to eq([:plugins, :in_progress, :no_plugins]) + end + end +end diff --git a/spec/v3/renderer/insights_sandbox_query_result_spec.rb b/spec/v3/renderer/insights_sandbox_query_result_spec.rb new file mode 100644 index 0000000000..613bd31302 --- /dev/null +++ b/spec/v3/renderer/insights_sandbox_query_result_spec.rb @@ -0,0 +1,24 @@ +describe Travis::API::V3::Renderer::InsightsSandboxQueryResult do + let(:object) { { 'negative_results' => [], 'positive_results' => ['test'], 'success' => true } } + + subject { Travis::API::V3::Renderer::InsightsSandboxQueryResult } + + describe "basic check" do + it "returns a basic representation of the object" do + expect(subject.render(object)).to eq( + { + '@type': 'insights_sandbox_query_result', + negative_results: object['negative_results'], + positive_results: object['positive_results'], + success: object['success'] + } + ) + end + end + + describe '#available_attributes' do + it 'returns available attributes' do + expect(subject.available_attributes).to eq([:negative_results, :positive_results, :success]) + end + end +end diff --git a/spec/v3/services/insights_notifications/all_spec.rb b/spec/v3/services/insights_notifications/all_spec.rb new file mode 100644 index 0000000000..a07966ca4d --- /dev/null +++ b/spec/v3/services/insights_notifications/all_spec.rb @@ -0,0 +1,94 @@ +describe Travis::API::V3::Services::InsightsNotifications::All, set_app: true, insights_spec_helper: true do + let(:parsed_body) { JSON.load(last_response.body) } + let(:insights_url) { 'http://insightsfake.travis-ci.com' } + let(:insights_auth_key) { 'secret' } + + before do + Travis.config.new_insights.insights_url = insights_url + Travis.config.new_insights.insights_auth_token = insights_auth_key + end + + context 'unauthenticated' do + it 'responds 403' do + get('/v3/insights_notifications') + + expect(last_response.status).to eq(403) + end + end + + context 'authenticated' do + let(:user) { FactoryBot.create(:user) } + let(:token) { Travis::Api::App::AccessToken.create(user: user, app_id: 1) } + let(:headers) {{ 'HTTP_AUTHORIZATION' => "token #{token}" }} + let(:page) { '1' } + let(:expected_json) do + { + "@type" => "notifications", + "@href" => "/v3/insights_notifications", + "@representation" => "standard", + "@pagination" => { + "limit" => 25, + "offset" => 0, + "count" => 2, + "is_first" => true, + "is_last" => true, + "next" => nil, + "prev" => nil, + "first" => { + "@href" => "/v3/insights_notifications", + "offset" => 0, + "limit" => 25 + }, + "last" => { + "@href" => "/v3/insights_notifications", + "offset" => 0, + "limit" => 25 + } + }, + "notifications" => [ + { + "@type" => "insights_notification", + "@representation" => "standard", + "id" => 8, + "type" => nil, + "active" => true, + "weight" => nil, + "message" => "This is a test notification", + "plugin_name" => "Travis Insights", + "plugin_type" => "Travis Insights", + "plugin_category" => "Monitoring", + "probe_severity" => "high", + "description" => "This is a test notification", + "description_link" => nil + }, + { + "@type" => "insights_notification", + "@representation" => "standard", + "id" => 7, + "type" => nil, + "active" => true, + "weight" => nil, + "message" => "This is a test notification", + "plugin_name" => "Travis Insights", + "plugin_type" => "Travis Insights", + "plugin_category" => "Monitoring", + "probe_severity" => "high", + "description" => "This is a test notification", + "description_link" => nil + } + ] + } + end + + before do + stub_insights_request(:get, '/user_notifications', query: "page=#{page}", auth_key: insights_auth_key, user_id: user.id) + .to_return(body: JSON.dump(insights_notifications_response)) + end + + it 'responds with list of plugins' do + get('/v3/insights_notifications', {}, headers) + expect(last_response.status).to eq(200) + expect(parsed_body).to eql_json(expected_json) + end + end +end diff --git a/spec/v3/services/insights_notifications/toggle_snooze_spec.rb b/spec/v3/services/insights_notifications/toggle_snooze_spec.rb new file mode 100644 index 0000000000..abd61673d4 --- /dev/null +++ b/spec/v3/services/insights_notifications/toggle_snooze_spec.rb @@ -0,0 +1,36 @@ +describe Travis::API::V3::Services::InsightsNotifications::ToggleSnooze, set_app: true, insights_spec_helper: true do + let(:parsed_body) { JSON.load(last_response.body) } + let(:insights_url) { 'http://insightsfake.travis-ci.com' } + let(:insights_auth_key) { 'secret' } + + before do + Travis.config.new_insights.insights_url = insights_url + Travis.config.new_insights.insights_auth_token = insights_auth_key + end + + context 'unauthenticated' do + it 'responds 403' do + patch('/v3/insights_notifications/toggle_snooze') + + expect(last_response.status).to eq(403) + end + end + + context 'authenticated' do + let(:user) { FactoryBot.create(:user) } + let(:token) { Travis::Api::App::AccessToken.create(user: user, app_id: 1) } + let(:headers) {{ 'HTTP_AUTHORIZATION' => "token #{token}" }} + let(:notification_ids) { ["123", "345"] } + + before do + stub_insights_request(:put, '/user_notifications/toggle_snooze', auth_key: insights_auth_key, user_id: user.id) + .with(body: JSON.dump(snooze_ids: notification_ids)) + .to_return(status: 204) + end + + it 'responds with list of subscriptions' do + patch('/v3/insights_notifications/toggle_snooze', { notification_ids: notification_ids }, headers) + expect(last_response.status).to eq(204) + end + end +end diff --git a/spec/v3/services/insights_plugin/get_scan_logs_spec.rb b/spec/v3/services/insights_plugin/get_scan_logs_spec.rb new file mode 100644 index 0000000000..536454fdac --- /dev/null +++ b/spec/v3/services/insights_plugin/get_scan_logs_spec.rb @@ -0,0 +1,66 @@ +describe Travis::API::V3::Services::InsightsPlugin::GetScanLogs, set_app: true, insights_spec_helper: true do + let(:parsed_body) { JSON.load(last_response.body) } + let(:insights_url) { 'http://insightsfake.travis-ci.com' } + let(:insights_auth_key) { 'secret' } + let(:plugin_id) { 1 } + + before do + Travis.config.new_insights.insights_url = insights_url + Travis.config.new_insights.insights_auth_token = insights_auth_key + end + + context 'unauthenticated' do + it 'responds 403' do + get("/v3/insights_plugin/#{plugin_id}/get_scan_logs") + + expect(last_response.status).to eq(403) + end + end + + context 'authenticated' do + let(:user) { FactoryBot.create(:user) } + let(:token) { Travis::Api::App::AccessToken.create(user: user, app_id: 1) } + let(:headers) {{ 'HTTP_AUTHORIZATION' => "token #{token}" }} + let(:expected_json) do + { + "@type"=>"insights_plugin_scan_logs", + "meta"=>{ + "scan_status_in_progress"=>true + }, + "scan_logs"=>[ + { + "id"=>97396, + "user_plugin_id"=>255, + "test_template_id"=>nil, + "log_type"=>"notifications", + "text"=>"Scheduling scan", + "additional_text_type"=>nil, + "additional_text"=>nil, + "created_at"=>"2021-11-18 04:00:05" + }, + { + "id"=>97432, + "user_plugin_id"=>255, + "test_template_id"=>nil, + "log_type"=>"plugin", + "text"=>"Scan started at", + "additional_text_type"=>nil, + "additional_text"=>nil, + "created_at"=>"2021-11-18 04:00:07" + } + ] + } + end + + before do + stub_insights_request(:get, "/user_plugins/#{plugin_id}/get_scan_logs", auth_key: insights_auth_key, user_id: user.id) + .to_return(body: JSON.dump(insights_scan_log_response)) + end + + it 'responds with authenticate result' do + get("/v3/insights_plugin/#{plugin_id}/get_scan_logs", {}, headers) + expect(last_response.status).to eq(200) + expect(parsed_body).to eql_json(expected_json) + end + end +end diff --git a/spec/v3/services/insights_plugins/all_spec.rb b/spec/v3/services/insights_plugins/all_spec.rb new file mode 100644 index 0000000000..0b5846c5c6 --- /dev/null +++ b/spec/v3/services/insights_plugins/all_spec.rb @@ -0,0 +1,90 @@ +describe Travis::API::V3::Services::InsightsPlugins::All, set_app: true, insights_spec_helper: true do + let(:parsed_body) { JSON.load(last_response.body) } + let(:insights_url) { 'http://insightsfake.travis-ci.com' } + let(:insights_auth_key) { 'secret' } + + before do + Travis.config.new_insights.insights_url = insights_url + Travis.config.new_insights.insights_auth_token = insights_auth_key + end + + context 'unauthenticated' do + it 'responds 403' do + get('/v3/insights_plugins') + + expect(last_response.status).to eq(403) + end + end + + context 'authenticated' do + let(:user) { FactoryBot.create(:user) } + let(:token) { Travis::Api::App::AccessToken.create(user: user, app_id: 1) } + let(:headers) {{ 'HTTP_AUTHORIZATION' => "token #{token}" }} + let(:page) { '1' } + let(:expected_json) do + { + "@type" => "plugins", + "@href" => "/v3/insights_plugins", + "@representation" => "standard", + "@pagination" => { + "limit" => 25, + "offset" => 0, + "count" => 2, + "is_first" => true, + "is_last" => true, + "next" => nil, + "prev" => nil, + "first" => { + "@href" => "/v3/insights_plugins", + "offset" => 0, + "limit" => 25 + }, + "last" => { + "@href" => "/v3/insights_plugins", + "offset" => 0, + "limit" => 25 + } + }, + "plugins" => [ + { + "@type" => "insights_plugin", + "@representation" => "standard", + "id" => 5, + "name" => "KubePlugin", + "public_id" => "TID6CD47CD6E26", + "plugin_type" => "Kubernetes Cluster", + "plugin_category" => "Monitoring", + "last_scan_end" => nil, + "scan_status" => "In Progress", + "plugin_status" => "Active", + "active" => true + }, + { + "@type" => "insights_plugin", + "@representation" => "standard", + "id" => 3, + "name" => "KubePlugin2", + "public_id" => "TI74D0AACAC0BD", + "plugin_type" => "Kubernetes Cluster", + "plugin_category" => "Monitoring", + "last_scan_end" => "2021-12-01 10:44:32", + "scan_status" => "Success", + "plugin_status" => "Active", + "active" => true + } + ] + } + end + + before do + stub_insights_request(:get, '/user_plugins', query: "page=#{page}", auth_key: insights_auth_key, user_id: user.id) + .to_return(body: JSON.dump(insights_plugins_response)) + end + + it 'responds with list of plugins' do + get('/v3/insights_plugins', {}, headers) + expect(last_response.status).to eq(200) + expect(parsed_body).to eql_json(expected_json) + end + end +end diff --git a/spec/v3/services/insights_plugins/authenticate_key_spec.rb b/spec/v3/services/insights_plugins/authenticate_key_spec.rb new file mode 100644 index 0000000000..07a335ae76 --- /dev/null +++ b/spec/v3/services/insights_plugins/authenticate_key_spec.rb @@ -0,0 +1,44 @@ +describe Travis::API::V3::Services::InsightsPlugins::AuthenticateKey, set_app: true, insights_spec_helper: true do + let(:parsed_body) { JSON.load(last_response.body) } + let(:insights_url) { 'http://insightsfake.travis-ci.com' } + let(:insights_auth_key) { 'secret' } + + before do + Travis.config.new_insights.insights_url = insights_url + Travis.config.new_insights.insights_auth_token = insights_auth_key + end + + context 'unauthenticated' do + it 'responds 403' do + post('/v3/insights_plugins/authenticate_key') + + expect(last_response.status).to eq(403) + end + end + + context 'authenticated' do + let(:user) { FactoryBot.create(:user) } + let(:token) { Travis::Api::App::AccessToken.create(user: user, app_id: 1) } + let(:headers) {{ 'HTTP_AUTHORIZATION' => "token #{token}" }} + let(:key_data) { { 'public_id' => 'id', 'private_key' => 'key' } } + let(:expected_json) do + { + "@type" => "insights_plugin_authenticate", + "success" => true, + "error_msg" => "" + } + end + + before do + stub_insights_request(:post, '/user_plugins/authenticate_key', auth_key: insights_auth_key, user_id: user.id) + .with(body: JSON.dump(key_data)) + .to_return(status: 201, body: JSON.dump(insights_authenticate_key_response)) + end + + it 'responds with authenticate result' do + post('/v3/insights_plugins/authenticate_key', key_data, headers) + expect(last_response.status).to eq(200) + expect(parsed_body).to eql_json(expected_json) + end + end +end diff --git a/spec/v3/services/insights_plugins/create_spec.rb b/spec/v3/services/insights_plugins/create_spec.rb new file mode 100644 index 0000000000..eb5127cf83 --- /dev/null +++ b/spec/v3/services/insights_plugins/create_spec.rb @@ -0,0 +1,53 @@ +describe Travis::API::V3::Services::InsightsPlugins::Create, set_app: true, insights_spec_helper: true do + let(:parsed_body) { JSON.load(last_response.body) } + let(:insights_url) { 'http://insightsfake.travis-ci.com' } + let(:insights_auth_key) { 'secret' } + + before do + Travis.config.new_insights.insights_url = insights_url + Travis.config.new_insights.insights_auth_token = insights_auth_key + end + + context 'unauthenticated' do + it 'responds 403' do + post('/v3/insights_plugins') + + expect(last_response.status).to eq(403) + end + end + + context 'authenticated' do + let(:user) { FactoryBot.create(:user) } + let(:token) { Travis::Api::App::AccessToken.create(user: user, app_id: 1) } + let(:headers) {{ 'HTTP_AUTHORIZATION' => "token #{token}" }} + let(:name) { 'plugin' } + let(:plugin_data) { { 'name' => name } } + let(:expected_json) do + { + "@type"=>"insights_plugin", + "@representation"=>"standard", + "id"=>3, + "name"=>"plugin", + "public_id"=>"TI74D0AACAC0BD", + "plugin_type"=>"Kubernetes Cluster", + "plugin_category"=>"Monitoring", + "last_scan_end"=>"2021-12-01 10:44:32", + "scan_status"=>"Success", + "plugin_status"=>"Active", + "active"=>true + } + end + + before do + stub_insights_request(:post, '/user_plugins', auth_key: insights_auth_key, user_id: user.id) + .with(body: JSON.dump(user_plugin: plugin_data)) + .to_return(status: 201, body: JSON.dump(insights_create_plugin_response('name' => name))) + end + + it 'responds with list of subscriptions' do + post('/v3/insights_plugins', plugin_data, headers) + expect(last_response.status).to eq(200) + expect(parsed_body).to eql_json(expected_json) + end + end +end diff --git a/spec/v3/services/insights_plugins/delete_many_spec.rb b/spec/v3/services/insights_plugins/delete_many_spec.rb new file mode 100644 index 0000000000..9b154f809b --- /dev/null +++ b/spec/v3/services/insights_plugins/delete_many_spec.rb @@ -0,0 +1,49 @@ +describe Travis::API::V3::Services::InsightsPlugins::DeleteMany, set_app: true, insights_spec_helper: true do + let(:parsed_body) { JSON.load(last_response.body) } + let(:insights_url) { 'http://insightsfake.travis-ci.com' } + let(:insights_auth_key) { 'secret' } + + before do + Travis.config.new_insights.insights_url = insights_url + Travis.config.new_insights.insights_auth_token = insights_auth_key + end + + context 'unauthenticated' do + it 'responds 403' do + delete('/v3/insights_plugins/delete_many') + + expect(last_response.status).to eq(403) + end + end + + context 'authenticated' do + let(:user) { FactoryBot.create(:user) } + let(:token) { Travis::Api::App::AccessToken.create(user: user, app_id: 1) } + let(:headers) {{ 'HTTP_AUTHORIZATION' => "token #{token}" }} + let(:plugin_ids) { ["123", "345"] } + let(:expected_json) do + { + "@type"=>"plugins", + "@representation"=>"standard", + "@pagination"=> + { + "limit"=>25, + "offset"=>0, + "count"=>0 + }, + "plugins"=>[] + } + end + + before do + stub_insights_request(:delete, '/user_plugins/delete_many', query: { delete_ids: plugin_ids }.to_query, auth_key: insights_auth_key, user_id: user.id) + .to_return(status: 200, body: '') + end + + it 'responds with list of subscriptions' do + delete('/v3/insights_plugins/delete_many', { ids: plugin_ids }, headers) + expect(last_response.status).to eq(200) + expect(parsed_body).to eql_json(expected_json) + end + end +end diff --git a/spec/v3/services/insights_plugins/generate_key_spec.rb b/spec/v3/services/insights_plugins/generate_key_spec.rb new file mode 100644 index 0000000000..9298f87a61 --- /dev/null +++ b/spec/v3/services/insights_plugins/generate_key_spec.rb @@ -0,0 +1,46 @@ +describe Travis::API::V3::Services::InsightsPlugins::GenerateKey, set_app: true, insights_spec_helper: true do + let(:parsed_body) { JSON.load(last_response.body) } + let(:insights_url) { 'http://insightsfake.travis-ci.com' } + let(:insights_auth_key) { 'secret' } + + before do + Travis.config.new_insights.insights_url = insights_url + Travis.config.new_insights.insights_auth_token = insights_auth_key + end + + context 'unauthenticated' do + it 'responds 403' do + get('/v3/insights_plugins/generate_key') + + expect(last_response.status).to eq(403) + end + end + + context 'authenticated' do + let(:user) { FactoryBot.create(:user) } + let(:token) { Travis::Api::App::AccessToken.create(user: user, app_id: 1) } + let(:headers) {{ 'HTTP_AUTHORIZATION' => "token #{token}" }} + let(:plugin_name) { 'name' } + let(:plugin_type) { 'type' } + let(:expected_json) do + { + "@type" => "insights_plugin_key", + "keys" => [ + "TIDE0C7A9C1D5E", + "a8f702e9363e8573dd476c116e62cf6e04e44c8610dc939c67e45777f2b6cbdb" + ] + } + end + + before do + stub_insights_request(:get, '/user_plugins/generate_key', query: { name: plugin_name, plugin_type: plugin_type }.to_query, auth_key: insights_auth_key, user_id: user.id) + .to_return(status: 201, body: JSON.dump(insights_generate_key_response)) + end + + it 'responds with list of subscriptions' do + get("/v3/insights_plugins/generate_key?plugin_name=#{plugin_name}&plugin_type=#{plugin_type}", {}, headers) + expect(last_response.status).to eq(200) + expect(parsed_body).to eql_json(expected_json) + end + end +end diff --git a/spec/v3/services/insights_plugins/run_scan_spec.rb b/spec/v3/services/insights_plugins/run_scan_spec.rb new file mode 100644 index 0000000000..408a2d6f69 --- /dev/null +++ b/spec/v3/services/insights_plugins/run_scan_spec.rb @@ -0,0 +1,48 @@ +describe Travis::API::V3::Services::InsightsPlugins::RunScan, set_app: true, insights_spec_helper: true do + let(:parsed_body) { JSON.load(last_response.body) } + let(:insights_url) { 'http://insightsfake.travis-ci.com' } + let(:insights_auth_key) { 'secret' } + + before do + Travis.config.new_insights.insights_url = insights_url + Travis.config.new_insights.insights_auth_token = insights_auth_key + end + + context 'unauthenticated' do + it 'responds 403' do + delete('/v3/insights_plugins/run_scan') + + expect(last_response.status).to eq(403) + end + end + + context 'authenticated' do + let(:user) { FactoryBot.create(:user) } + let(:token) { Travis::Api::App::AccessToken.create(user: user, app_id: 1) } + let(:headers) {{ 'HTTP_AUTHORIZATION' => "token #{token}" }} + let(:expected_json) do + { + "@type"=>"plugins", + "@representation"=>"standard", + "@pagination"=> + { + "limit"=>25, + "offset"=>0, + "count"=>0 + }, + "plugins"=>[] + } + end + + before do + stub_insights_request(:get, '/user_plugins/run_scan', auth_key: insights_auth_key, user_id: user.id) + .to_return(status: 200, body: '') + end + + it 'responds with list of subscriptions' do + get('/v3/insights_plugins/run_scan', {}, headers) + expect(last_response.status).to eq(200) + expect(parsed_body).to eql_json(expected_json) + end + end +end diff --git a/spec/v3/services/insights_plugins/template_plugin_tests_spec.rb b/spec/v3/services/insights_plugins/template_plugin_tests_spec.rb new file mode 100644 index 0000000000..d7757d25c8 --- /dev/null +++ b/spec/v3/services/insights_plugins/template_plugin_tests_spec.rb @@ -0,0 +1,52 @@ +describe Travis::API::V3::Services::InsightsPlugins::TemplatePluginTests, set_app: true, insights_spec_helper: true do + let(:parsed_body) { JSON.load(last_response.body) } + let(:insights_url) { 'http://insightsfake.travis-ci.com' } + let(:insights_auth_key) { 'secret' } + + before do + Travis.config.new_insights.insights_url = insights_url + Travis.config.new_insights.insights_auth_token = insights_auth_key + end + + context 'unauthenticated' do + it 'responds 403' do + get('/v3/insights_plugins/template_plugin_tests') + + expect(last_response.status).to eq(403) + end + end + + context 'authenticated' do + let(:user) { FactoryBot.create(:user) } + let(:token) { Travis::Api::App::AccessToken.create(user: user, app_id: 1) } + let(:headers) {{ 'HTTP_AUTHORIZATION' => "token #{token}" }} + let(:plugin_type) { 'sre' } + let(:expected_json) do + { + "@type"=>"insights_plugin_tests", + "template_tests"=>[ + { + "id"=>3232, + "name"=>"This is a test probe" + }, + { + "id"=>3234, + "name"=>"This is a test probe 2" + } + ], + "plugin_category"=>"Monitoring" + } + end + + before do + stub_insights_request(:get, "/user_plugins/#{plugin_type}/template_plugin_tests", auth_key: insights_auth_key, user_id: user.id) + .to_return(status: 201, body: JSON.dump(insights_template_plugin_tests_response)) + end + + it 'responds with list of subscriptions' do + get("/v3/insights_plugins/template_plugin_tests?plugin_type=#{plugin_type}", {}, headers) + expect(last_response.status).to eq(200) + expect(parsed_body).to eql_json(expected_json) + end + end +end diff --git a/spec/v3/services/insights_plugins/toggle_active_spec.rb b/spec/v3/services/insights_plugins/toggle_active_spec.rb new file mode 100644 index 0000000000..c5fd0c3611 --- /dev/null +++ b/spec/v3/services/insights_plugins/toggle_active_spec.rb @@ -0,0 +1,50 @@ +describe Travis::API::V3::Services::InsightsPlugins::ToggleActive, set_app: true, insights_spec_helper: true do + let(:parsed_body) { JSON.load(last_response.body) } + let(:insights_url) { 'http://insightsfake.travis-ci.com' } + let(:insights_auth_key) { 'secret' } + + before do + Travis.config.new_insights.insights_url = insights_url + Travis.config.new_insights.insights_auth_token = insights_auth_key + end + + context 'unauthenticated' do + it 'responds 403' do + patch('/v3/insights_plugins/toggle_active') + + expect(last_response.status).to eq(403) + end + end + + context 'authenticated' do + let(:user) { FactoryBot.create(:user) } + let(:token) { Travis::Api::App::AccessToken.create(user: user, app_id: 1) } + let(:headers) {{ 'HTTP_AUTHORIZATION' => "token #{token}" }} + let(:plugin_ids) { ["123", "345"] } + let(:expected_json) do + { + "@type"=>"plugins", + "@representation"=>"standard", + "@pagination"=> + { + "limit"=>25, + "offset"=>0, + "count"=>0 + }, + "plugins"=>[] + } + end + + before do + stub_insights_request(:put, '/user_plugins/toggle_active', auth_key: insights_auth_key, user_id: user.id) + .with(body: JSON.dump(toggle_ids: plugin_ids)) + .to_return(status: 200, body: '') + end + + it 'responds with list of subscriptions' do + patch('/v3/insights_plugins/toggle_active', { ids: plugin_ids }, headers) + expect(last_response.status).to eq(200) + expect(parsed_body).to eql_json(expected_json) + end + end +end diff --git a/spec/v3/services/insights_probe/get_spec.rb b/spec/v3/services/insights_probe/get_spec.rb new file mode 100644 index 0000000000..59d3a5c320 --- /dev/null +++ b/spec/v3/services/insights_probe/get_spec.rb @@ -0,0 +1,68 @@ +describe Travis::API::V3::Services::InsightsProbe::Get, set_app: true, insights_spec_helper: true do + let(:parsed_body) { JSON.load(last_response.body) } + let(:insights_url) { 'http://insightsfake.travis-ci.com' } + let(:insights_auth_key) { 'secret' } + let(:probe_id) { 1 } + + before do + Travis.config.new_insights.insights_url = insights_url + Travis.config.new_insights.insights_auth_token = insights_auth_key + end + + context 'unauthenticated' do + it 'responds 403' do + get("/v3/insights_probe/#{probe_id}") + + expect(last_response.status).to eq(403) + end + end + + context 'authenticated' do + let(:user) { FactoryBot.create(:user) } + let(:token) { Travis::Api::App::AccessToken.create(user: user, app_id: 1) } + let(:headers) {{ 'HTTP_AUTHORIZATION' => "token #{token}" }} + let(:expected_json) do + { + "@type"=>"insights_probe", + "@representation"=>"standard", + "id"=>1, + "user_id"=>45, + "user_plugin_id"=>nil, + "test_template_id"=>313, + "uuid"=>"f3abd5e4-8231-4afa-9b84-56bfa0264f34", + "uuid_group"=>"d968832e-1b04-4b05-b810-884d0fb5fdee", + "type"=>"native", + "notification"=>"You need some deployment pipeline plugins.", + "description"=>"Description", + "description_link"=>"", + "test"=>"assert count($.Plugins[@.plugin_category is \"deployment_pipeline\"]) > 0", + "base_object_locator"=>nil, + "preconditions"=>nil, + "conditionals"=>nil, + "object_key_locator"=>nil, + "active"=>true, + "editable"=>false, + "template_type"=>"TestDefinitions::Sre::YouNeedSomeDeploymentPipelinePlugins", + "cruncher_type"=>"sreql", + "status"=>"Active", + "labels"=>{}, + "plugin_type"=>"sre", + "plugin_type_name"=>"Travis Insights", + "plugin_category"=>"Monitoring", + "tag_list"=>[], + "severity"=>"high" + } + end + + before do + stub_insights_request(:get, "/probes/#{probe_id}/template_test", query: "probe_id=#{probe_id}", auth_key: insights_auth_key, user_id: user.id) + .to_return(status: 201, body: JSON.dump(insights_create_probe_response('id' => probe_id))) + end + + it 'responds with authenticate result' do + get("/v3/insights_probe/#{probe_id}", {}, headers) + expect(last_response.status).to eq(200) + expect(parsed_body).to eql_json(expected_json) + end + end +end diff --git a/spec/v3/services/insights_probe/update_spec.rb b/spec/v3/services/insights_probe/update_spec.rb new file mode 100644 index 0000000000..cfc3488b09 --- /dev/null +++ b/spec/v3/services/insights_probe/update_spec.rb @@ -0,0 +1,71 @@ +describe Travis::API::V3::Services::InsightsProbe::Update, set_app: true, insights_spec_helper: true do + let(:parsed_body) { JSON.load(last_response.body) } + let(:insights_url) { 'http://insightsfake.travis-ci.com' } + let(:insights_auth_key) { 'secret' } + let(:probe_id) { "1" } + + before do + Travis.config.new_insights.insights_url = insights_url + Travis.config.new_insights.insights_auth_token = insights_auth_key + end + + context 'unauthenticated' do + it 'responds 403' do + patch("/v3/insights_probe/#{probe_id}") + + expect(last_response.status).to eq(403) + end + end + + context 'authenticated' do + let(:user) { FactoryBot.create(:user) } + let(:token) { Travis::Api::App::AccessToken.create(user: user, app_id: 1) } + let(:headers) {{ 'HTTP_AUTHORIZATION' => "token #{token}" }} + let(:notification) { 'Test Probe' } + let(:probe_data) { { 'notification' => notification, 'probe_id' => probe_id } } + let(:expected_json) do + { + "@type"=>"insights_probe", + "@representation"=>"standard", + "id"=>"1", + "user_id"=>45, + "user_plugin_id"=>nil, + "test_template_id"=>313, + "uuid"=>"f3abd5e4-8231-4afa-9b84-56bfa0264f34", + "uuid_group"=>"d968832e-1b04-4b05-b810-884d0fb5fdee", + "type"=>"native", + "notification"=>notification, + "description"=>"Description", + "description_link"=>"", + "test"=>"assert count($.Plugins[@.plugin_category is \"deployment_pipeline\"]) > 0", + "base_object_locator"=>nil, + "preconditions"=>nil, + "conditionals"=>nil, + "object_key_locator"=>nil, + "active"=>true, + "editable"=>false, + "template_type"=>"TestDefinitions::Sre::YouNeedSomeDeploymentPipelinePlugins", + "cruncher_type"=>"sreql", + "status"=>"Active", + "labels"=>{}, + "plugin_type"=>"sre", + "plugin_type_name"=>"Travis Insights", + "plugin_category"=>"Monitoring", + "tag_list"=>[], + "severity"=>"high" + } + end + + before do + stub_insights_request(:patch, "/probes/#{probe_id}", auth_key: insights_auth_key, user_id: user.id) + .with(body: JSON.dump(probe_data)) + .to_return(status: 201, body: JSON.dump(insights_create_probe_response('id' => probe_id, 'notification' => notification))) + end + + it 'responds with authenticate result' do + patch("/v3/insights_probe/#{probe_id}", { notification: notification }, headers) + expect(last_response.status).to eq(200) + expect(parsed_body).to eql_json(expected_json) + end + end +end diff --git a/spec/v3/services/insights_probes/all_spec.rb b/spec/v3/services/insights_probes/all_spec.rb new file mode 100644 index 0000000000..ee27df94be --- /dev/null +++ b/spec/v3/services/insights_probes/all_spec.rb @@ -0,0 +1,131 @@ +describe Travis::API::V3::Services::InsightsProbes::All, set_app: true, insights_spec_helper: true do + let(:parsed_body) { JSON.load(last_response.body) } + let(:insights_url) { 'http://insightsfake.travis-ci.com' } + let(:insights_auth_key) { 'secret' } + + before do + Travis.config.new_insights.insights_url = insights_url + Travis.config.new_insights.insights_auth_token = insights_auth_key + end + + context 'unauthenticated' do + it 'responds 403' do + get('/v3/insights_probes') + + expect(last_response.status).to eq(403) + end + end + + context 'authenticated' do + let(:user) { FactoryBot.create(:user) } + let(:token) { Travis::Api::App::AccessToken.create(user: user, app_id: 1) } + let(:headers) {{ 'HTTP_AUTHORIZATION' => "token #{token}" }} + let(:page) { '1' } + let(:expected_json) do + { + "@type"=>"tests", + "@href"=>"/v3/insights_probes", + "@representation"=>"standard", + "@pagination"=>{ + "limit"=>25, + "offset"=>0, + "count"=>2, + "is_first"=>true, + "is_last"=>true, + "next"=>nil, + "prev"=>nil, + "first"=>{ + "@href"=>"/v3/insights_probes", + "offset"=>0, + "limit"=>25 + }, + "last"=>{ + "@href"=>"/v3/insights_probes", + "offset"=>0, + "limit"=>25 + } + }, + "tests"=>[ + { + "@type"=>"insights_probe", + "@representation"=>"standard", + "id"=>312, + "user_id"=>45, + "user_plugin_id"=>nil, + "test_template_id"=>312, + "uuid"=>"d0286ba6-ee08-4d87-9fb5-e8709fd9d2c3", + "uuid_group"=>"4bf1205a-e030-4da9-ad16-6d4ac2c654c3", + "type"=>"native", "notification"=>"You need more plugins.", + "description"=>"Travis Insights description.", + "description_link"=>"link", + "test"=>"assert count($.Plugins) > 4", + "base_object_locator"=>nil, + "preconditions"=>nil, + "conditionals"=>nil, + "object_key_locator"=>nil, + "active"=>true, + "editable"=>false, + "template_type"=>"TestDefinitions::Sre::YouNeedMorePlugins", + "cruncher_type"=>"sreql", + "status"=>"Active", + "labels"=>{}, + "plugin_type"=>"sre", + "plugin_type_name"=>"Travis Insights", + "plugin_category"=>"Monitoring", + "tag_list"=>[ + { + "id"=>3, + "name"=>"TI", + "created_at"=>"2022-01-03T09:21:12.390Z", + "updated_at"=>"2022-01-03T09:21:12.390Z", + "taggings_count"=>1 + } + ], + "severity"=>"info" + }, + { + "@type"=>"insights_probe", + "@representation"=>"standard", + "id"=>313, + "user_id"=>45, + "user_plugin_id"=>nil, + "test_template_id"=>313, + "uuid"=>"f3abd5e4-8231-4afa-9b84-56bfa0264f34", + "uuid_group"=>"d968832e-1b04-4b05-b810-884d0fb5fdee", + "type"=>"native", + "notification"=>"You need some deployment pipeline plugins.", + "description"=>"Description", + "description_link"=>"", + "test"=>"assert count($.Plugins[@.plugin_category is \"deployment_pipeline\"]) > 0", + "base_object_locator"=>nil, + "preconditions"=>nil, + "conditionals"=>nil, + "object_key_locator"=>nil, + "active"=>true, + "editable"=>false, + "template_type"=>"TestDefinitions::Sre::YouNeedSomeDeploymentPipelinePlugins", + "cruncher_type"=>"sreql", + "status"=>"Active", + "labels"=>{}, + "plugin_type"=>"sre", + "plugin_type_name"=>"Travis Insights", + "plugin_category"=>"Monitoring", + "tag_list"=>[], + "severity"=>"high" + } + ] + } + end + + before do + stub_insights_request(:get, '/probes', query: "page=#{page}", auth_key: insights_auth_key, user_id: user.id) + .to_return(body: JSON.dump(insights_probes_response)) + end + + it 'responds with list of plugins' do + get('/v3/insights_probes', {}, headers) + expect(last_response.status).to eq(200) + expect(parsed_body).to eql_json(expected_json) + end + end +end diff --git a/spec/v3/services/insights_probes/create_spec.rb b/spec/v3/services/insights_probes/create_spec.rb new file mode 100644 index 0000000000..c66ba60b75 --- /dev/null +++ b/spec/v3/services/insights_probes/create_spec.rb @@ -0,0 +1,70 @@ +describe Travis::API::V3::Services::InsightsProbes::Create, set_app: true, insights_spec_helper: true do + let(:parsed_body) { JSON.load(last_response.body) } + let(:insights_url) { 'http://insightsfake.travis-ci.com' } + let(:insights_auth_key) { 'secret' } + + before do + Travis.config.new_insights.insights_url = insights_url + Travis.config.new_insights.insights_auth_token = insights_auth_key + end + + context 'unauthenticated' do + it 'responds 403' do + post('/v3/insights_probes') + + expect(last_response.status).to eq(403) + end + end + + context 'authenticated' do + let(:user) { FactoryBot.create(:user) } + let(:token) { Travis::Api::App::AccessToken.create(user: user, app_id: 1) } + let(:headers) {{ 'HTTP_AUTHORIZATION' => "token #{token}" }} + let(:notification) { 'Test Probe' } + let(:probe_data) { { 'notification' => notification } } + let(:expected_json) do + { + "@type"=>"insights_probe", + "@representation"=>"standard", + "id"=>313, + "user_id"=>45, + "user_plugin_id"=>nil, + "test_template_id"=>313, + "uuid"=>"f3abd5e4-8231-4afa-9b84-56bfa0264f34", + "uuid_group"=>"d968832e-1b04-4b05-b810-884d0fb5fdee", + "type"=>"native", + "notification"=>"Test Probe", + "description"=>"Description", + "description_link"=>"", + "test"=>"assert count($.Plugins[@.plugin_category is \"deployment_pipeline\"]) > 0", + "base_object_locator"=>nil, + "preconditions"=>nil, + "conditionals"=>nil, + "object_key_locator"=>nil, + "active"=>true, + "editable"=>false, + "template_type"=>"TestDefinitions::Sre::YouNeedSomeDeploymentPipelinePlugins", + "cruncher_type"=>"sreql", + "status"=>"Active", + "labels"=>{}, + "plugin_type"=>"sre", + "plugin_type_name"=>"Travis Insights", + "plugin_category"=>"Monitoring", + "tag_list"=>[], + "severity"=>"high" + } + end + + before do + stub_insights_request(:post, '/probes', auth_key: insights_auth_key, user_id: user.id) + .with(body: JSON.dump(test_template: probe_data)) + .to_return(status: 201, body: JSON.dump(insights_create_probe_response('notification' => notification))) + end + + it 'responds with list of subscriptions' do + post('/v3/insights_probes', probe_data, headers) + expect(last_response.status).to eq(200) + expect(parsed_body).to eql_json(expected_json) + end + end +end diff --git a/spec/v3/services/insights_probes/delete_many_spec.rb b/spec/v3/services/insights_probes/delete_many_spec.rb new file mode 100644 index 0000000000..6fce8d12d6 --- /dev/null +++ b/spec/v3/services/insights_probes/delete_many_spec.rb @@ -0,0 +1,35 @@ +describe Travis::API::V3::Services::InsightsProbes::DeleteMany, set_app: true, insights_spec_helper: true do + let(:parsed_body) { JSON.load(last_response.body) } + let(:insights_url) { 'http://insightsfake.travis-ci.com' } + let(:insights_auth_key) { 'secret' } + + before do + Travis.config.new_insights.insights_url = insights_url + Travis.config.new_insights.insights_auth_token = insights_auth_key + end + + context 'unauthenticated' do + it 'responds 403' do + delete('/v3/insights_probes/delete_many') + + expect(last_response.status).to eq(403) + end + end + + context 'authenticated' do + let(:user) { FactoryBot.create(:user) } + let(:token) { Travis::Api::App::AccessToken.create(user: user, app_id: 1) } + let(:headers) {{ 'HTTP_AUTHORIZATION' => "token #{token}" }} + let(:probe_ids) { ["123", "345"] } + + before do + stub_insights_request(:delete, '/probes/delete_many', query: { delete_ids: probe_ids }.to_query, auth_key: insights_auth_key, user_id: user.id) + .to_return(status: 200, body: '') + end + + it 'responds with list of subscriptions' do + delete('/v3/insights_probes/delete_many', { ids: probe_ids }, headers) + expect(last_response.status).to eq(204) + end + end +end diff --git a/spec/v3/services/insights_probes/toggle_active_spec.rb b/spec/v3/services/insights_probes/toggle_active_spec.rb new file mode 100644 index 0000000000..a5278effa4 --- /dev/null +++ b/spec/v3/services/insights_probes/toggle_active_spec.rb @@ -0,0 +1,36 @@ +describe Travis::API::V3::Services::InsightsProbes::ToggleActive, set_app: true, insights_spec_helper: true do + let(:parsed_body) { JSON.load(last_response.body) } + let(:insights_url) { 'http://insightsfake.travis-ci.com' } + let(:insights_auth_key) { 'secret' } + + before do + Travis.config.new_insights.insights_url = insights_url + Travis.config.new_insights.insights_auth_token = insights_auth_key + end + + context 'unauthenticated' do + it 'responds 403' do + patch('/v3/insights_probes/toggle_active') + + expect(last_response.status).to eq(403) + end + end + + context 'authenticated' do + let(:user) { FactoryBot.create(:user) } + let(:token) { Travis::Api::App::AccessToken.create(user: user, app_id: 1) } + let(:headers) {{ 'HTTP_AUTHORIZATION' => "token #{token}" }} + let(:probe_ids) { ["123", "345"] } + + before do + stub_insights_request(:put, '/probes/toggle_active', auth_key: insights_auth_key, user_id: user.id) + .with(body: JSON.dump(toggle_ids: probe_ids)) + .to_return(status: 200, body: '') + end + + it 'responds with list of subscriptions' do + patch('/v3/insights_probes/toggle_active', { ids: probe_ids }, headers) + expect(last_response.status).to eq(204) + end + end +end diff --git a/spec/v3/services/insights_public_key/latest_spec.rb b/spec/v3/services/insights_public_key/latest_spec.rb new file mode 100644 index 0000000000..db4423287a --- /dev/null +++ b/spec/v3/services/insights_public_key/latest_spec.rb @@ -0,0 +1,45 @@ +describe Travis::API::V3::Services::InsightsPublicKey::Latest, set_app: true, insights_spec_helper: true do + let(:parsed_body) { JSON.load(last_response.body) } + let(:insights_url) { 'http://insightsfake.travis-ci.com' } + let(:insights_auth_key) { 'secret' } + let(:probe_id) { 1 } + + before do + Travis.config.new_insights.insights_url = insights_url + Travis.config.new_insights.insights_auth_token = insights_auth_key + end + + context 'unauthenticated' do + it 'responds 403' do + get('/v3/insights_public_key') + + expect(last_response.status).to eq(403) + end + end + + context 'authenticated' do + let(:user) { FactoryBot.create(:user) } + let(:token) { Travis::Api::App::AccessToken.create(user: user, app_id: 1) } + let(:headers) {{ 'HTTP_AUTHORIZATION' => "token #{token}" }} + let(:expected_json) do + { + "@type"=>"insights_public_key", + "@representation"=>"standard", + "key_hash"=>"KEY_HASH", + "key_body"=>"PUBLIC_KEY", + "ordinal_value"=>1 + } + end + + before do + stub_insights_request(:get, '/api/v1/public_keys/latest.json', auth_key: insights_auth_key, user_id: user.id) + .to_return(status: 201, body: JSON.dump(insights_public_key_response)) + end + + it 'responds with authenticate result' do + get('/v3/insights_public_key', {}, headers) + expect(last_response.status).to eq(200) + expect(parsed_body).to eql_json(expected_json) + end + end +end diff --git a/spec/v3/services/insights_sandbox/plugin_data_spec.rb b/spec/v3/services/insights_sandbox/plugin_data_spec.rb new file mode 100644 index 0000000000..13b14feaaa --- /dev/null +++ b/spec/v3/services/insights_sandbox/plugin_data_spec.rb @@ -0,0 +1,101 @@ +describe Travis::API::V3::Services::InsightsSandbox::PluginData, set_app: true, insights_spec_helper: true do + let(:parsed_body) { JSON.load(last_response.body) } + let(:insights_url) { 'http://insightsfake.travis-ci.com' } + let(:insights_auth_key) { 'secret' } + + before do + Travis.config.new_insights.insights_url = insights_url + Travis.config.new_insights.insights_auth_token = insights_auth_key + end + + context 'unauthenticated' do + it 'responds 403' do + post('/v3/insights_sandbox/plugin_data') + + expect(last_response.status).to eq(403) + end + end + + context 'authenticated' do + let(:user) { FactoryBot.create(:user) } + let(:token) { Travis::Api::App::AccessToken.create(user: user, app_id: 1) } + let(:headers) {{ 'HTTP_AUTHORIZATION' => "token #{token}" }} + let(:plugin_type) { 'sre' } + let(:expected_json) do + { + "@type"=>"insights_sandbox_plugin_data", + "data"=>{ + "Plugins"=>[ + { + "id"=>255, + "plugin_category"=>"monitoring", + "plugin_type"=>"sre", + "scan_logs"=>[ + { + "additional_text"=>nil, + "additional_text_type"=>nil, + "created_at"=>"2021-11-18T04:00:05.072Z", + "id"=>97396, + "log_type"=>"notifications", + "tenant_id"=>39, + "test_template_id"=>nil, + "text"=>"Scheduling scan", + "updated_at"=>"2021-11-18T04:00:05.072Z", + "user_plugin_id"=>255 + }, + { + "additional_text"=>nil, + "additional_text_type"=>nil, + "created_at"=>"2021-11-18T04:00:07.010Z", + "id"=>97432, + "log_type"=>"plugin", + "tenant_id"=>39, + "test_template_id"=>nil, + "text"=>"Scan started at", + "updated_at"=>"2021-11-18T04:00:07.010Z", + "user_plugin_id"=>255 + }, + { + "additional_text"=>"", + "additional_text_type"=>"", + "created_at"=>"2021-11-18T04:00:07.068Z", + "id"=>97435, + "log_type"=>"plugin", + "tenant_id"=>39, + "test_template_id"=>nil, + "text"=>"Accessing APIs:", + "updated_at"=>"2021-11-18T04:00:07.068Z", + "user_plugin_id"=>255 + }, + { + "additional_text"=>"- User Plugins", + "additional_text_type"=>"info", + "created_at"=>"2021-11-18T04:00:07.148Z", + "id"=>97438, + "log_type"=>"plugin", + "tenant_id"=>39, + "test_template_id"=>nil, + "text"=>"", + "updated_at"=>"2021-11-18T04:00:07.148Z", + "user_plugin_id"=>255 + } + ], + "user_id"=>28 + } + ] + } + } + end + + before do + stub_insights_request(:post, '/sandbox/plugin_data', auth_key: insights_auth_key, user_id: user.id) + .to_return(status: 201, body: insights_sandbox_plugin_data_response) + end + + it 'responds with list of subscriptions' do + post('/v3/insights_sandbox/plugin_data', { plugin_type: plugin_type }, headers) + expect(last_response.status).to eq(200) + expect(parsed_body).to eql_json(expected_json) + end + end +end diff --git a/spec/v3/services/insights_sandbox/plugins_spec.rb b/spec/v3/services/insights_sandbox/plugins_spec.rb new file mode 100644 index 0000000000..ac6f26c85d --- /dev/null +++ b/spec/v3/services/insights_sandbox/plugins_spec.rb @@ -0,0 +1,51 @@ +describe Travis::API::V3::Services::InsightsSandbox::Plugins, set_app: true, insights_spec_helper: true do + let(:parsed_body) { JSON.load(last_response.body) } + let(:insights_url) { 'http://insightsfake.travis-ci.com' } + let(:insights_auth_key) { 'secret' } + + before do + Travis.config.new_insights.insights_url = insights_url + Travis.config.new_insights.insights_auth_token = insights_auth_key + end + + context 'unauthenticated' do + it 'responds 403' do + post('/v3/insights_sandbox/plugins') + + expect(last_response.status).to eq(403) + end + end + + context 'authenticated' do + let(:user) { FactoryBot.create(:user) } + let(:token) { Travis::Api::App::AccessToken.create(user: user, app_id: 1) } + let(:headers) {{ 'HTTP_AUTHORIZATION' => "token #{token}" }} + let(:plugin_type) { 'sre' } + let(:expected_json) do + { + "@type"=>"insights_sandbox_plugins", + "plugins"=>[ + { + "id"=>4, + "name"=>"Travis Insights", + "data"=>"{\n \"Plugins\": [\n {\n \"id\": 255,\n \"plugin_category\": \"monitoring\",\n \"plugin_type\": \"sre\",\n \"scan_logs\": [\n {\n \"additional_text\": null,\n \"additional_text_type\": null,\n \"created_at\": \"2021-11-18T04:00:05.072Z\",\n \"id\": 97396,\n \"log_type\": \"notifications\",\n \"tenant_id\": 39,\n \"test_template_id\": null,\n \"text\": \"Scheduling scan\",\n \"updated_at\": \"2021-11-18T04:00:05.072Z\",\n \"user_plugin_id\": 255\n },\n {\n \"additional_text\": null,\n \"additional_text_type\": null,\n \"created_at\": \"2021-11-18T04:00:07.010Z\",\n \"id\": 97432,\n \"log_type\": \"plugin\",\n \"tenant_id\": 39,\n \"test_template_id\": null,\n \"text\": \"Scan started at\",\n \"updated_at\": \"2021-11-18T04:00:07.010Z\",\n \"user_plugin_id\": 255\n },\n {\n \"additional_text\": \"\",\n \"additional_text_type\": \"\",\n \"created_at\": \"2021-11-18T04:00:07.068Z\",\n \"id\": 97435,\n \"log_type\": \"plugin\",\n \"tenant_id\": 39,\n \"test_template_id\": null,\n \"text\": \"Accessing APIs:\",\n \"updated_at\": \"2021-11-18T04:00:07.068Z\",\n \"user_plugin_id\": 255\n },\n {\n \"additional_text\": \"- User Plugins\",\n \"additional_text_type\": \"info\",\n \"created_at\": \"2021-11-18T04:00:07.148Z\",\n \"id\": 97438,\n \"log_type\": \"plugin\",\n \"tenant_id\": 39,\n \"test_template_id\": null,\n \"text\": \"\",\n \"updated_at\": \"2021-11-18T04:00:07.148Z\",\n \"user_plugin_id\": 255\n }\n ],\n \"user_id\": 28\n }\n ]\n}", + "ready"=>true + } + ], + "in_progress"=>false, + "no_plugins"=>false + } + end + + before do + stub_insights_request(:post, '/sandbox/plugins', auth_key: insights_auth_key, user_id: user.id) + .to_return(status: 201, body: JSON.dump(insights_sandbox_plugins_response)) + end + + it 'responds with list of subscriptions' do + post('/v3/insights_sandbox/plugins', { plugin_type: plugin_type }, headers) + expect(last_response.status).to eq(200) + expect(parsed_body).to eql_json(expected_json) + end + end +end diff --git a/spec/v3/services/insights_sandbox/run_query_spec.rb b/spec/v3/services/insights_sandbox/run_query_spec.rb new file mode 100644 index 0000000000..c150f23de4 --- /dev/null +++ b/spec/v3/services/insights_sandbox/run_query_spec.rb @@ -0,0 +1,45 @@ +describe Travis::API::V3::Services::InsightsSandbox::RunQuery, set_app: true, insights_spec_helper: true do + let(:parsed_body) { JSON.load(last_response.body) } + let(:insights_url) { 'http://insightsfake.travis-ci.com' } + let(:insights_auth_key) { 'secret' } + + before do + Travis.config.new_insights.insights_url = insights_url + Travis.config.new_insights.insights_auth_token = insights_auth_key + end + + context 'unauthenticated' do + it 'responds 403' do + post('/v3/insights_sandbox/run_query') + + expect(last_response.status).to eq(403) + end + end + + context 'authenticated' do + let(:user) { FactoryBot.create(:user) } + let(:token) { Travis::Api::App::AccessToken.create(user: user, app_id: 1) } + let(:headers) {{ 'HTTP_AUTHORIZATION' => "token #{token}" }} + let(:plugin_id) { '333' } + let(:query) { 'test' } + let(:expected_json) do + { + "@type"=>"insights_sandbox_query_result", + "negative_results"=>[false], + "positive_results"=>nil, + "success"=>true + } + end + + before do + stub_insights_request(:post, '/sandbox/run_query', auth_key: insights_auth_key, user_id: user.id) + .to_return(status: 201, body: JSON.dump(insights_sandbox_query_response)) + end + + it 'responds with list of subscriptions' do + post('/v3/insights_sandbox/run_query', { plugin_id: plugin_id, query: query }, headers) + expect(last_response.status).to eq(200) + expect(parsed_body).to eql_json(expected_json) + end + end +end diff --git a/spec/v3/services/insights_tags/search_tags_spec.rb b/spec/v3/services/insights_tags/search_tags_spec.rb new file mode 100644 index 0000000000..91525399ec --- /dev/null +++ b/spec/v3/services/insights_tags/search_tags_spec.rb @@ -0,0 +1,60 @@ +describe Travis::API::V3::Services::InsightsTags::SearchTags, set_app: true, insights_spec_helper: true do + let(:parsed_body) { JSON.load(last_response.body) } + let(:insights_url) { 'http://insightsfake.travis-ci.com' } + let(:insights_auth_key) { 'secret' } + let(:probe_id) { 1 } + + before do + Travis.config.new_insights.insights_url = insights_url + Travis.config.new_insights.insights_auth_token = insights_auth_key + end + + context 'unauthenticated' do + it 'responds 403' do + get('/v3/insights_tags') + + expect(last_response.status).to eq(403) + end + end + + context 'authenticated' do + let(:user) { FactoryBot.create(:user) } + let(:token) { Travis::Api::App::AccessToken.create(user: user, app_id: 1) } + let(:headers) {{ 'HTTP_AUTHORIZATION' => "token #{token}" }} + let(:expected_json) do + { + "@type"=>"tags", + "@href"=>"/v3/insights_tags", + "@representation"=>"standard", + "tags"=>[ + { + "@type"=>"insights_tag", + "@representation"=>"standard", + "name"=>"Tag1" + }, + { + "@type"=>"insights_tag", + "@representation"=>"standard", + "name"=>"Tag2" + }, + { + "@type"=>"insights_tag", + "@representation"=>"standard", + "name"=>"Tag3" + } + ] + } + end + + before do + stub_insights_request(:get, '/tags', auth_key: insights_auth_key, user_id: user.id) + .to_return(status: 201, body: JSON.dump(insights_tags_response)) + end + + it 'responds with authenticate result' do + get('/v3/insights_tags', {}, headers) + expect(last_response.status).to eq(200) + expect(parsed_body).to eql_json(expected_json) + end + end +end diff --git a/spec/v3/services/preferences/for_user_spec.rb b/spec/v3/services/preferences/for_user_spec.rb index c0b57f55e4..6d791de014 100644 --- a/spec/v3/services/preferences/for_user_spec.rb +++ b/spec/v3/services/preferences/for_user_spec.rb @@ -38,6 +38,30 @@ "@representation" => "standard", "name" => "private_insights_visibility", "value" => "private" + }, { + "@type" => "preference", + "@href" => "/v3/preference/insights_scan_notifications", + "@representation" => "standard", + "name" => "insights_scan_notifications", + "value" => true + }, { + "@type" => "preference", + "@href" => "/v3/preference/insights_time_zone", + "@representation" => "standard", + "name" => "insights_time_zone", + "value" => "" + }, { + "@type" => "preference", + "@href" => "/v3/preference/insights_date_format", + "@representation" => "standard", + "name" => "insights_date_format", + "value" => "DD/MM/YYYY" + }, { + "@type" => "preference", + "@href" => "/v3/preference/insights_time_format", + "@representation" => "standard", + "name" => "insights_time_format", + "value" => "HH:mm:ss" } ] ) @@ -49,6 +73,10 @@ user.preferences.update(:build_emails, false) user.preferences.update(:consume_oss_credits, false) user.preferences.update(:private_insights_visibility, 'public') + user.preferences.update(:insights_scan_notifications, false) + user.preferences.update(:insights_time_zone, '(GMT-12:00) Etc/GMT+12') + user.preferences.update(:insights_date_format, 'YYYY/MM/DD') + user.preferences.update(:insights_time_format, 'h:mm:ss A') get("/v3/preferences", {}, auth_headers) end @@ -78,6 +106,30 @@ "@representation" => "standard", "name" => "private_insights_visibility", "value" => "public" + }, { + "@type" => "preference", + "@href" => "/v3/preference/insights_scan_notifications", + "@representation" => "standard", + "name" => "insights_scan_notifications", + "value" => false + }, { + "@type" => "preference", + "@href" => "/v3/preference/insights_time_zone", + "@representation" => "standard", + "name" => "insights_time_zone", + "value" => "(GMT-12:00) Etc/GMT+12" + }, { + "@type" => "preference", + "@href" => "/v3/preference/insights_date_format", + "@representation" => "standard", + "name" => "insights_date_format", + "value" => "YYYY/MM/DD" + }, { + "@type" => "preference", + "@href" => "/v3/preference/insights_time_format", + "@representation" => "standard", + "name" => "insights_time_format", + "value" => "h:mm:ss A" } ] )