motor-admin 0.2.41 → 0.2.43

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a51c13e10df9707cb2130c580660133d07a543c55e97157ebe8660099ff602e6
4
- data.tar.gz: 81a887350a6fec48cae6fa7c0d74d1efaae29456685e7d2bb63d8347d6aab7e4
3
+ metadata.gz: 89d36e62222311f43cf9df24d7d090d72cb067e9cc713431ff2f7ce39ed8079c
4
+ data.tar.gz: 40f0520672effff61094e2518afcb216c6da4c2402749bac024648a5a8c491e9
5
5
  SHA512:
6
- metadata.gz: f9d5172d6d3014145c39f3640def2f7dbedf4b79dd0c2021562933d6da5caff0430f95334a30cb8c3fed6afa884753d1bd268cf28f8171fe9e03fc3d755d1049
7
- data.tar.gz: 8a56bce2407c3314d41ecb5d977e275da6b36fd40ac41468912ded8d02b386f3af27b4410e1be0e6c4b4c6b99736239326c663f4aadac4b9f5e30c5bcf30c2f3
6
+ metadata.gz: 89e962e2d87c0171a38961d1f1d0ede97021d5eb8bb0ba071b92d3c114a919d201f11dd25647793efd656823fc7b19c7e913c51a73b7e69b7f472f8772a59fa5
7
+ data.tar.gz: 38d3105d72a4aca9fa91f0096e92d7c4ef015e0544e877ceb7b844eac6617cbdc1c25a6df20772358b5a93b29b661985d6112719cfae9e62737499306b05c695
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Motor
4
+ class ApiConfigsController < ApiBaseController
5
+ wrap_parameters :data, except: %i[include fields]
6
+
7
+ before_action :find_or_initialize_api_config, only: :create
8
+ load_and_authorize_resource
9
+
10
+ def index
11
+ render json: { data: Motor::ApiQuery::BuildJson.call(@api_configs.active.order(:id), params, current_ability) }
12
+ end
13
+
14
+ def create
15
+ @api_config.save!
16
+
17
+ Motor::Configs::WriteToFile.call
18
+
19
+ render json: { data: Motor::ApiQuery::BuildJson.call(@api_config, params, current_ability) }
20
+ rescue ActiveRecord::RecordNotUnique
21
+ find_or_initialize_api_config
22
+
23
+ retry
24
+ end
25
+
26
+ def destroy
27
+ @api_config&.update!(deleted_at: Time.current)
28
+
29
+ Motor::Configs::WriteToFile.call
30
+
31
+ head :ok
32
+ end
33
+
34
+ private
35
+
36
+ def find_or_initialize_api_config
37
+ name, url, description, preferences, credentials =
38
+ api_config_params.values_at(:name, :url, :description, :preferences, :credentials)
39
+
40
+ @api_config =
41
+ Motor::ApiConfig.find_or_initialize_by(name: name).tap do |config|
42
+ config.url = url.delete_suffix('/')
43
+ config.description = description
44
+ config.preferences.merge!(preferences)
45
+ config.credentials.merge!(credentials)
46
+ config.deleted_at = nil
47
+ end
48
+ end
49
+
50
+ def api_config_params
51
+ params.require(:data).permit(:name, :url, :description, preferences: {}, credentials: {})
52
+ end
53
+ end
54
+ end
@@ -54,7 +54,8 @@ module Motor
54
54
  end
55
55
 
56
56
  def form_params
57
- params.require(:data).permit(:name, :description, :api_path, :http_method, preferences: {}, tags: [])
57
+ params.require(:data).permit(:name, :description, :api_path, :http_method,
58
+ :api_config_name, preferences: {}, tags: [])
58
59
  end
59
60
  end
60
61
  end
@@ -21,7 +21,11 @@ module Motor
21
21
  if Motor::Queries::Persistance.name_already_exists?(@query)
22
22
  render json: { errors: [{ source: 'name', detail: 'Name already exists' }] }, status: :unprocessable_entity
23
23
  else
24
- ApplicationRecord.transaction { @query.save! }
24
+ ApplicationRecord.transaction do
25
+ Motor::Queries::Persistance.assign_or_create_api_config!(@query)
26
+ @query.save!
27
+ end
28
+
25
29
  Motor::Configs::WriteToFile.call
26
30
 
27
31
  render json: { data: Motor::ApiQuery::BuildJson.call(@query, params, current_ability) }
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Motor
4
+ class RunApiRequestsController < ApiBaseController
5
+ JWT_TTL = 2.hours
6
+
7
+ wrap_parameters :data
8
+
9
+ def show
10
+ respond_with_result
11
+ end
12
+
13
+ def create
14
+ respond_with_result
15
+ end
16
+
17
+ private
18
+
19
+ def respond_with_result
20
+ response = Motor::ApiConfigs.run(find_or_initialize_api_config,
21
+ method: request_params[:method],
22
+ path: request_params[:path],
23
+ body: request_params[:params],
24
+ params: request_params[:body],
25
+ headers: { 'Authorization' => "Bearer #{current_user_jwt}" })
26
+
27
+ self.response_body = response.body
28
+ self.status = response.code.to_i
29
+ end
30
+
31
+ def find_or_initialize_api_config
32
+ Motor::ApiConfig.find_by(name: request_params[:api_config_name]) ||
33
+ Motor::ApiConfig.new(url: request_params[:api_config_name])
34
+ end
35
+
36
+ def current_user_jwt
37
+ return '' unless defined?(JWT)
38
+ return '' unless current_user
39
+
40
+ payload = { uid: current_user.id, email: current_user.email, exp: JWT_TTL.from_now.to_i }
41
+
42
+ JWT.encode(payload, Rails.application.secrets.secret_key_base)
43
+ end
44
+
45
+ def request_params
46
+ params.require(:data).permit!
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Motor
4
+ class ApiConfig < ::Motor::ApplicationRecord
5
+ unless table_exists?
6
+ puts
7
+ puts ' => Run `rails g motor:upgrade && rake db:migrate` to perform data migration and enable the latest features'
8
+ puts
9
+ end
10
+
11
+ encrypts :credentials if defined?(::Motor::EncryptedConfig)
12
+
13
+ serialize :credentials, Motor::HashSerializer
14
+ serialize :preferences, Motor::HashSerializer
15
+
16
+ attribute :preferences, default: -> { HashWithIndifferentAccess.new }
17
+ attribute :credentials, default: -> { HashWithIndifferentAccess.new }
18
+
19
+ has_one :form, dependent: nil, foreign_key: :api_config_name, primary_key: :name, inverse_of: :api_config
20
+
21
+ scope :active, -> { where(deleted_at: nil) }
22
+
23
+ def headers
24
+ credentials.fetch(:headers, []).each_with_object({}) do |item, acc|
25
+ acc[item[:key]] = item[:value]
26
+ end
27
+ end
28
+ end
29
+ end
@@ -5,6 +5,7 @@ module Motor
5
5
  audited
6
6
 
7
7
  belongs_to :author, polymorphic: true, optional: true
8
+ belongs_to :api_config, foreign_key: :api_config_name, primary_key: :name, inverse_of: :form
8
9
 
9
10
  has_many :taggable_tags, as: :taggable, dependent: :destroy
10
11
  has_many :tags, through: :taggable_tags, class_name: 'Motor::Tag'
@@ -296,3 +296,6 @@ en:
296
296
  order_by: Order by
297
297
  ascending: Ascending
298
298
  descending: Descending
299
+ url: URL
300
+ expand: Expand
301
+ add_api: Add API
@@ -296,6 +296,9 @@ es:
296
296
  order_by: Ordenar por
297
297
  ascending: Ascendente
298
298
  descending: Descendente
299
+ url: URL
300
+ expand: Expandir
301
+ add_api: De API
299
302
  i:
300
303
  locale: es
301
304
  select:
@@ -292,6 +292,9 @@ pt:
292
292
  order_by: Encomendar por
293
293
  ascending: Ascendente
294
294
  descending: Decrescente
295
+ url: URL
296
+ expand: Expandir
297
+ add_api: De API
295
298
  i:
296
299
  locale: pt
297
300
  select:
data/config/routes.rb CHANGED
@@ -14,6 +14,8 @@ Motor::Admin.routes.draw do
14
14
  resources :resource_default_queries, only: %i[show], param: 'resource'
15
15
  resources :schema, only: %i[index show], param: 'resource'
16
16
  resources :dashboards, only: %i[index show create update destroy]
17
+ resource :run_api_request, only: %i[show create]
18
+ resources :api_configs, only: %i[index create destroy]
17
19
  resources :forms, only: %i[index show create update destroy]
18
20
  resources :alerts, only: %i[index show create update destroy]
19
21
  resources :icons, only: %i[index]
@@ -44,6 +44,7 @@ class <%= migration_class_name %> < ActiveRecord::Migration[<%= ActiveRecord::Mi
44
44
  t.column :author_id, :bigint
45
45
  t.column :author_type, :string
46
46
  t.column :deleted_at, :datetime
47
+ t.column :api_config_name, :string, null: false
47
48
 
48
49
  t.timestamps
49
50
 
@@ -138,6 +139,22 @@ class <%= migration_class_name %> < ActiveRecord::Migration[<%= ActiveRecord::Mi
138
139
  t.column :created_at, :datetime
139
140
  end
140
141
 
142
+ create_table :motor_api_configs do |t|
143
+ t.column :name, :string, null: false
144
+ t.column :url, :string, null: false
145
+ t.column :preferences, :text, null: false
146
+ t.column :credentials, :text, null: false
147
+ t.column :description, :text
148
+ t.column :deleted_at, :datetime
149
+
150
+ t.timestamps
151
+
152
+ t.index 'name',
153
+ name: 'motor_api_configs_name_unique_index',
154
+ unique: true,
155
+ where: 'deleted_at IS NULL'
156
+ end
157
+
141
158
  add_index :motor_audits, %i[auditable_type auditable_id version], name: 'motor_auditable_index'
142
159
  add_index :motor_audits, %i[associated_type associated_id], name: 'motor_auditable_associated_index'
143
160
  add_index :motor_audits, %i[user_id user_type], name: 'motor_auditable_user_index'
@@ -152,6 +169,10 @@ class <%= migration_class_name %> < ActiveRecord::Migration[<%= ActiveRecord::Mi
152
169
  name: '⭐ Star on GitHub',
153
170
  path: 'https://github.com/motor-admin/motor-admin-rails'
154
171
  }].to_json)
172
+
173
+ model.table_name = 'motor_api_configs'
174
+
175
+ model.create!(name: 'origin', path: '/')
155
176
  end
156
177
 
157
178
  def self.down
@@ -0,0 +1,80 @@
1
+ class <%= migration_class_name %> < ActiveRecord::Migration[<%= ActiveRecord::Migration.current_version %>]
2
+ class MotorApiConfig < ActiveRecord::Base
3
+ self.table_name = 'motor_api_configs'
4
+
5
+ encrypts :credentials if defined?(::Motor::EncryptedConfig)
6
+
7
+ serialize :credentials, Motor::HashSerializer
8
+ serialize :preferences, Motor::HashSerializer
9
+
10
+ attribute :preferences, default: -> { HashWithIndifferentAccess.new }
11
+ attribute :credentials, default: -> { HashWithIndifferentAccess.new }
12
+ end
13
+
14
+ class MotorForm < ActiveRecord::Base
15
+ self.table_name = 'motor_forms'
16
+ end
17
+
18
+ class MotorQuery < ActiveRecord::Base
19
+ self.table_name = 'motor_queries'
20
+
21
+ serialize :preferences, Motor::HashSerializer
22
+ end
23
+
24
+ def up
25
+ create_table :motor_api_configs do |t|
26
+ t.column :name, :string, null: false
27
+ t.column :url, :string, null: false
28
+ t.column :preferences, :text, null: false
29
+ t.column :credentials, :text, null: false
30
+ t.column :description, :text
31
+ t.column :deleted_at, :datetime
32
+
33
+ t.timestamps
34
+
35
+ t.index 'name',
36
+ name: 'motor_api_configs_name_unique_index',
37
+ unique: true,
38
+ where: 'deleted_at IS NULL'
39
+ end
40
+
41
+ add_column :motor_forms, :api_config_name, :string
42
+
43
+ MotorForm.all.each do |form|
44
+ if form.api_path.starts_with?('http')
45
+ url = form.api_path[%r{\Ahttps?://[^/]+}]
46
+
47
+ form.preferences[:default_values_api_path]&.delete(url)
48
+ form.update!(api_config_name: MotorApiConfig.find_or_create_by!(name: url, url: url).name,
49
+ api_path: form.api_path.delete(url))
50
+ else
51
+ form.update!(api_config_name: MotorApiConfig.find_or_create_by!(name: 'origin', url: '/').name)
52
+ end
53
+ end
54
+
55
+ MotorQuery.all.each do |query|
56
+ next if query.preferences['api_path'].blank?
57
+
58
+ if query.preferences['api_path'].starts_with?('http')
59
+ url = query.preferences['api_path'][%r{\Ahttps?://[^/]+}]
60
+
61
+ query.preferences['api_path'].delete(url)
62
+
63
+ query.preferences['api_config_name'] = MotorApiConfig.find_or_create_by!(name: url, url: url).name
64
+ else
65
+ query.preferences['api_config_name'] = MotorApiConfig.find_or_create_by!(name: 'origin', url: '/').name
66
+ end
67
+
68
+ query.save!
69
+ end
70
+
71
+ change_column_null :motor_forms, :api_config_name, false
72
+
73
+ MotorApiConfig.find_or_create_by!(name: 'origin', url: '/')
74
+ end
75
+
76
+ def down
77
+ remove_column :motor_forms, :api_config_name
78
+ drop_table :motor_api_configs
79
+ end
80
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails/generators'
4
+ require 'rails/generators/migration'
5
+ require 'active_record'
6
+ require 'rails/generators/active_record'
7
+ require 'generators/motor/migration'
8
+
9
+ module Motor
10
+ module Generators
11
+ class UpgradeGenerator < Rails::Generators::Base
12
+ include Rails::Generators::Migration
13
+ extend Motor::Generators::Migration
14
+
15
+ source_root File.expand_path('templates', __dir__)
16
+
17
+ def copy_migration
18
+ if Motor::ApiConfig.table_exists?
19
+ puts 'The latest Motor Admin features are already configured'
20
+ else
21
+ migration_template 'install_api_configs.rb', 'db/migrate/install_motor_api_configs.rb'
22
+
23
+ puts 'Run `rake db:migrate` to update DB schema'
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -53,7 +53,7 @@ module Motor
53
53
 
54
54
  type_map = connection_class.connection.send(:type_map)
55
55
 
56
- type_map.instance_variable_get('@mapping').map do |name, type|
56
+ type_map.instance_variable_get(:@mapping).map do |name, type|
57
57
  next unless name.is_a?(String)
58
58
 
59
59
  [type.call.class.to_s, name]
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Motor
4
+ module ApiConfigs
5
+ METHODS = %w[get post put delete].freeze
6
+
7
+ InvalidHttpMethod = Class.new(StandardError)
8
+
9
+ module_function
10
+
11
+ def run(api_config, method: nil, path: nil, body: nil, params: {}, headers: {})
12
+ method ||= 'get'
13
+
14
+ raise InvalidHttpMethod unless METHODS.include?(method.downcase)
15
+
16
+ Motor::NetHttpUtils.public_send(
17
+ method.downcase.to_sym,
18
+ api_config.url.to_s.sub(%r{/?\z}, '/') + path.delete_prefix('/'),
19
+ params,
20
+ headers.merge(api_config.headers),
21
+ body
22
+ )
23
+ end
24
+ end
25
+ end
@@ -5,6 +5,7 @@ module Motor
5
5
  module BuildConfigsHash
6
6
  module_function
7
7
 
8
+ # rubocop:disable Metrics/AbcSize
8
9
  def call
9
10
  cache_keys = LoadFromCache.load_cache_keys
10
11
 
@@ -16,9 +17,11 @@ module Motor
16
17
  queries: build_queries_hash(cache_keys[:queries]),
17
18
  dashboards: build_dashboards_hash(cache_keys[:dashboards]),
18
19
  forms: build_forms_hash(cache_keys[:forms]),
19
- alerts: build_alerts_hash(cache_keys[:alerts])
20
+ alerts: build_alerts_hash(cache_keys[:alerts]),
21
+ api_configs: build_api_configs_hash(cache_keys[:api_configs])
20
22
  )
21
23
  end
24
+ # rubocop:enable Metrics/AbcSize
22
25
 
23
26
  def build_queries_hash(cache_key = nil)
24
27
  Motor::Configs::LoadFromCache.load_queries(cache_key: cache_key).sort_by(&:id).map do |query|
@@ -43,11 +46,17 @@ module Motor
43
46
 
44
47
  def build_forms_hash(cache_key = nil)
45
48
  Motor::Configs::LoadFromCache.load_forms(cache_key: cache_key).sort_by(&:id).map do |form|
46
- form.slice(%i[id name http_method api_path description preferences])
49
+ form.slice(%i[id name http_method api_path description preferences api_config_name])
47
50
  .merge(tags: form.tags.map(&:name), updated_at: form.updated_at.to_time)
48
51
  end
49
52
  end
50
53
 
54
+ def build_api_configs_hash(cache_key = nil)
55
+ Motor::Configs::LoadFromCache.load_api_configs(cache_key: cache_key).sort_by(&:id).map do |config|
56
+ config.slice(%i[id name url preferences description]).merge(updated_at: config.updated_at.to_time)
57
+ end
58
+ end
59
+
51
60
  def build_configs_hash(cache_key = nil)
52
61
  Motor::Configs::LoadFromCache.load_configs(cache_key: cache_key).sort_by(&:key).map do |config|
53
62
  {
@@ -68,6 +68,12 @@ module Motor
68
68
  end
69
69
  end
70
70
 
71
+ def load_api_configs(cache_key: nil)
72
+ maybe_fetch_from_cache('forms', cache_key) do
73
+ Motor::ApiConfig.all.active.load
74
+ end
75
+ end
76
+
71
77
  def maybe_fetch_from_cache(type, cache_key)
72
78
  return yield unless cache_key
73
79
 
@@ -95,7 +101,8 @@ module Motor
95
101
  Motor::Dashboard.select("'dashboards', MAX(updated_at)").to_sql,
96
102
  Motor::Alert.select("'alerts', MAX(updated_at)").to_sql,
97
103
  Motor::Query.select("'queries', MAX(updated_at)").to_sql,
98
- Motor::Form.select("'forms', MAX(updated_at)").to_sql
104
+ Motor::Form.select("'forms', MAX(updated_at)").to_sql,
105
+ Motor::ApiConfig.select("'api_configs', MAX(updated_at)").to_sql
99
106
  ].join(' UNION ')
100
107
  end
101
108
  end
@@ -17,6 +17,7 @@ module Motor
17
17
  sync_forms(configs_hash)
18
18
  sync_configs(configs_hash)
19
19
  sync_resources(configs_hash)
20
+ sync_api_configs(configs_hash)
20
21
  end
21
22
  end
22
23
 
@@ -68,6 +69,28 @@ module Motor
68
69
  end
69
70
  end
70
71
 
72
+ def sync_api_configs(configs_hash)
73
+ return if configs_hash[:api_configs].blank?
74
+
75
+ configs_index = Motor::Configs::LoadFromCache.load_api_configs.index_by(&:name)
76
+
77
+ configs_hash[:api_configs].each do |attrs|
78
+ record = configs_index[attrs[:name]] || Motor::ApiConfig.new
79
+
80
+ next if record.updated_at && attrs[:updated_at] <= record.updated_at
81
+
82
+ record.update!(attrs.merge(deleted_at: nil))
83
+ end
84
+
85
+ archive_api_configs(configs_index, configs_hash[:api_configs])
86
+ end
87
+
88
+ def archive_api_configs(configs_index, api_configs)
89
+ configs_index.except(*api_configs.pluck('name')).each_value do |config|
90
+ config.update!(deleted_at: Time.current) if config.deleted_at.blank?
91
+ end
92
+ end
93
+
71
94
  def sync_resources(configs_hash)
72
95
  resources_index = Motor::Configs::LoadFromCache.load_resources.index_by(&:name)
73
96
 
@@ -38,6 +38,7 @@ module Motor
38
38
 
39
39
  ApplicationRecord.transaction do
40
40
  archive_with_existing_name(form) if force_replace
41
+ find_or_assign_api_config(form)
41
42
 
42
43
  form.save!
43
44
  end
@@ -50,12 +51,31 @@ module Motor
50
51
  end
51
52
 
52
53
  def assign_attributes(form, params)
53
- form.assign_attributes(params.slice(:name, :description, :api_path, :http_method, :preferences))
54
+ form.assign_attributes(params.slice(:name, :description, :api_path, :http_method, :preferences,
55
+ :api_config_name))
54
56
  form.updated_at = [params[:updated_at], Time.current].min if params[:updated_at].present?
55
57
 
58
+ find_or_assign_api_config(form)
59
+
56
60
  Motor::Tags.assign_tags(form, params[:tags])
57
61
  end
58
62
 
63
+ def find_or_assign_api_config(form)
64
+ return if form.api_config.present?
65
+
66
+ config = Motor::ApiConfig.find_by(url: [form.api_config_name, form.api_config_name.delete_suffix('/')])
67
+
68
+ if config
69
+ config.update!(deleted_at: nil)
70
+
71
+ form.api_config_name = config.name
72
+ else
73
+ form.api_config = Motor::ApiConfig.new(url: form.api_config_name.delete_suffix('/')).tap do |c|
74
+ c.name = c.url.sub(%r{\Ahttps?://}, '').delete_suffix('/')
75
+ end
76
+ end
77
+ end
78
+
59
79
  def archive_with_existing_name(form)
60
80
  Motor::Form.where(['name = ? AND id != ?', form.name, form.id])
61
81
  .update_all(deleted_at: Time.current)
@@ -4,7 +4,7 @@ module Motor
4
4
  module NetHttpUtils
5
5
  module_function
6
6
 
7
- def get(url, params = {}, headers = {})
7
+ def get(url, params = {}, headers = {}, _body = nil)
8
8
  request = build_request(Net::HTTP::Get, url, params, headers, nil)
9
9
 
10
10
  execute_request(request)
@@ -16,9 +16,21 @@ module Motor
16
16
  execute_request(request)
17
17
  end
18
18
 
19
+ def put(url, params = {}, headers = {}, body = '')
20
+ request = build_request(Net::HTTP::Put, url, params, headers, body)
21
+
22
+ execute_request(request)
23
+ end
24
+
25
+ def delete(url, params = {}, headers = {}, body = '')
26
+ request = build_request(Net::HTTP::Delete, url, params, headers, body)
27
+
28
+ execute_request(request)
29
+ end
30
+
19
31
  def build_request(method_class, url, params, headers, body)
20
32
  uri = URI(url)
21
- uri.query = params.to_query
33
+ uri.query = params.to_query if params.present?
22
34
 
23
35
  request = method_class.new(uri)
24
36
  request.body = body if body.present?
@@ -38,6 +38,7 @@ module Motor
38
38
 
39
39
  ApplicationRecord.transaction do
40
40
  archive_with_existing_name(query) if force_replace
41
+ assign_or_create_api_config!(query)
41
42
 
42
43
  query.save!
43
44
  end
@@ -61,6 +62,22 @@ module Motor
61
62
  .update_all(deleted_at: Time.current)
62
63
  end
63
64
 
65
+ def assign_or_create_api_config!(query)
66
+ api_config_name = query.preferences[:api_config_name]
67
+
68
+ return if api_config_name.blank?
69
+ return if Motor::ApiConfig.find_by(name: api_config_name)
70
+
71
+ config = Motor::ApiConfig.find_by(url: [api_config_name, api_config_name.delete_suffix('/')])
72
+
73
+ config&.update!(deleted_at: nil)
74
+
75
+ config ||= Motor::ApiConfig.create!(name: api_config_name.sub(%r{\Ahttps?://}, '').delete_suffix('/'),
76
+ url: api_config_name.delete_suffix('/'))
77
+
78
+ query.preferences[:api_config_name] = config.name
79
+ end
80
+
64
81
  def name_already_exists?(query)
65
82
  if query.new_record?
66
83
  Query.exists?(name: query.name, deleted_at: nil)
data/lib/motor/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Motor
4
- VERSION = '0.2.41'
4
+ VERSION = '0.2.43'
5
5
  end
data/lib/motor.rb CHANGED
@@ -61,6 +61,7 @@ require 'motor/configs'
61
61
  require 'motor/queries'
62
62
  require 'motor/dashboards'
63
63
  require 'motor/forms'
64
+ require 'motor/api_configs'
64
65
  require 'motor/alerts'
65
66
  require 'motor/resources'
66
67
  require 'motor/hash_serializer'
@@ -2601,9 +2601,9 @@
2601
2601
  "icons/zoom-out.svg.gz": "icons/zoom-out.svg.gz",
2602
2602
  "icons/zoom-question.svg": "icons/zoom-question.svg",
2603
2603
  "icons/zoom-question.svg.gz": "icons/zoom-question.svg.gz",
2604
- "main-f7a83db6d8381e2638a1.css.gz": "main-f7a83db6d8381e2638a1.css.gz",
2605
- "main-f7a83db6d8381e2638a1.js.LICENSE.txt": "main-f7a83db6d8381e2638a1.js.LICENSE.txt",
2606
- "main-f7a83db6d8381e2638a1.js.gz": "main-f7a83db6d8381e2638a1.js.gz",
2607
- "main.css": "main-f7a83db6d8381e2638a1.css",
2608
- "main.js": "main-f7a83db6d8381e2638a1.js"
2604
+ "main-90db17316da397cbfa9c.css.gz": "main-90db17316da397cbfa9c.css.gz",
2605
+ "main-90db17316da397cbfa9c.js.LICENSE.txt": "main-90db17316da397cbfa9c.js.LICENSE.txt",
2606
+ "main-90db17316da397cbfa9c.js.gz": "main-90db17316da397cbfa9c.js.gz",
2607
+ "main.css": "main-90db17316da397cbfa9c.css",
2608
+ "main.js": "main-90db17316da397cbfa9c.js"
2609
2609
  }
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: motor-admin
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.41
4
+ version: 0.2.43
5
5
  platform: ruby
6
6
  authors:
7
7
  - Pete Matsyburka
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-12-27 00:00:00.000000000 Z
11
+ date: 2021-12-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord-filter
@@ -114,6 +114,7 @@ files:
114
114
  - app/controllers/motor/active_storage_attachments_controller.rb
115
115
  - app/controllers/motor/alerts_controller.rb
116
116
  - app/controllers/motor/api_base_controller.rb
117
+ - app/controllers/motor/api_configs_controller.rb
117
118
  - app/controllers/motor/application_controller.rb
118
119
  - app/controllers/motor/assets_controller.rb
119
120
  - app/controllers/motor/audits_controller.rb
@@ -127,6 +128,7 @@ files:
127
128
  - app/controllers/motor/resource_default_queries_controller.rb
128
129
  - app/controllers/motor/resource_methods_controller.rb
129
130
  - app/controllers/motor/resources_controller.rb
131
+ - app/controllers/motor/run_api_requests_controller.rb
130
132
  - app/controllers/motor/run_queries_controller.rb
131
133
  - app/controllers/motor/schema_controller.rb
132
134
  - app/controllers/motor/send_alerts_controller.rb
@@ -139,6 +141,7 @@ files:
139
141
  - app/mailers/motor/application_mailer.rb
140
142
  - app/models/motor/alert.rb
141
143
  - app/models/motor/alert_lock.rb
144
+ - app/models/motor/api_config.rb
142
145
  - app/models/motor/application_record.rb
143
146
  - app/models/motor/audit.rb
144
147
  - app/models/motor/config.rb
@@ -158,6 +161,8 @@ files:
158
161
  - lib/generators/motor/install_generator.rb
159
162
  - lib/generators/motor/migration.rb
160
163
  - lib/generators/motor/templates/install.rb
164
+ - lib/generators/motor/templates/install_api_configs.rb
165
+ - lib/generators/motor/upgrade_generator.rb
161
166
  - lib/motor-admin.rb
162
167
  - lib/motor.rb
163
168
  - lib/motor/active_record_utils.rb
@@ -175,6 +180,7 @@ files:
175
180
  - lib/motor/alerts/persistance.rb
176
181
  - lib/motor/alerts/scheduled_alerts_cache.rb
177
182
  - lib/motor/alerts/scheduler.rb
183
+ - lib/motor/api_configs.rb
178
184
  - lib/motor/api_query.rb
179
185
  - lib/motor/api_query/apply_scope.rb
180
186
  - lib/motor/api_query/build_json.rb
@@ -1526,8 +1532,8 @@ files:
1526
1532
  - ui/dist/icons/zoom-money.svg.gz
1527
1533
  - ui/dist/icons/zoom-out.svg.gz
1528
1534
  - ui/dist/icons/zoom-question.svg.gz
1529
- - ui/dist/main-f7a83db6d8381e2638a1.css.gz
1530
- - ui/dist/main-f7a83db6d8381e2638a1.js.gz
1535
+ - ui/dist/main-90db17316da397cbfa9c.css.gz
1536
+ - ui/dist/main-90db17316da397cbfa9c.js.gz
1531
1537
  - ui/dist/manifest.json
1532
1538
  homepage:
1533
1539
  licenses: