tramway-api 1.7.1.2 → 1.8.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: da48436e048ba6df03c3764a6e528da5f427c1fbac6b61f38d518c716f19ec78
4
- data.tar.gz: b2ab9a5eb94df23ed37869e6908ae0c8fcf469816095e04fd9483fe986694247
3
+ metadata.gz: 56cacd097b745beaad7a04f1b31a63f645ffcb0ca3f2705be6c636765e04968a
4
+ data.tar.gz: 30b2598b412f3b87d48895254e1eef6ffd8b1c20299ea07b9bee766397aff8a5
5
5
  SHA512:
6
- metadata.gz: cc0856fcd9f84958606c305180ab4c719d3861e28e0f620e75630eac665e87c08f67021a953318380ba09d91876e2809a42d33a05dbf12fe3fb7cf11ce2267ff
7
- data.tar.gz: c551fdb3f5f9d42baf32de1f4e05e3ad12a2d8cbff675b5d4a6c521febcac17e0635f5cee7d2338c3fbbddb77d9936b8ef14060b7b4d7fd1c71febd4825a2337
6
+ metadata.gz: 42275c0a399c5f988e6cbf683a03b1eacbf3aae1da85a212ef06f48e936ed9e0a856ba89132d80e4c4f11e49a620f4cb8a7f2ee2402857ac24a4e5d2772f46c5
7
+ data.tar.gz: ae1465d070ee21a997310922cd43898617a617d5d74a727e4a37abd6717aca961ca833c547038703738227f2c9559e295dcd3c7bdcf191893b1957f95c962964
@@ -19,6 +19,105 @@ module Tramway
19
19
  end
20
20
  hash
21
21
  end
22
+
23
+ private
24
+
25
+ def record
26
+ @record = model_class.find_by! uuid: params[:id] if params[:id].present?
27
+ end
28
+
29
+ def records
30
+ collection = model_class.active.order(id: :desc).send params[:scope] || :all
31
+ collection = collection.full_text_search params[:search] if params[:search]
32
+ collection
33
+ end
34
+
35
+ def check_available_model_class
36
+ unless model_class
37
+ head(:unauthorized) && return unless current_user
38
+ head(:unprocessable_entity) && return
39
+ end
40
+ end
41
+
42
+ def check_available_model_action_for_record
43
+ action_is_available = check_action
44
+ action_is_available.tap do
45
+ if action_is_available.is_a?(Proc) && !action_is_available.call(record, current_user)
46
+ head(:unprocessable_entity) && return
47
+ end
48
+ end
49
+ end
50
+
51
+ def available_action_for_collection
52
+ action_is_available = check_action
53
+ return records if action_is_available == true
54
+
55
+ action_is_available.call records, current_user if action_is_available.is_a?(Proc)
56
+ end
57
+
58
+ def check_action
59
+ action_is_available = checking_roles.map do |role|
60
+ Tramway::Api.action_is_available(
61
+ action: action_name.to_sym,
62
+ project: (@application_engine || @application.name),
63
+ role: role,
64
+ model_name: params[:model],
65
+ current_user: current_user
66
+ )
67
+ end.compact.uniq - [false]
68
+
69
+ if action_is_available.count > 1
70
+ Tramway::Error.raise_error(:tramway, :api, :api, :v1, :records_controller, :available_action_for_collection, :duplicate_actions)
71
+ end
72
+
73
+ action_is_available = action_is_available.first
74
+
75
+ action_is_available.tap do
76
+ head(:unprocessable_entity) && return unless action_is_available
77
+ end
78
+ end
79
+
80
+ def authenticate_user_if_needed
81
+ action_is_open = Tramway::Api.action_is_available(
82
+ action: action_name.to_sym,
83
+ project: (@application_engine || @application.name),
84
+ model_name: params[:model]
85
+ )
86
+ head(:unauthorized) && return if !current_user && !action_is_open
87
+ end
88
+
89
+ def available_models_for_current_user
90
+ checking_roles.reduce([]) do |models, role|
91
+ models += ::Tramway::Api.available_models(role: role).map(&:to_s)
92
+ end
93
+ end
94
+
95
+ def checking_roles
96
+ [:open, current_user&.role].compact
97
+ end
98
+ protected
99
+
100
+ def model_class
101
+ if params[:model].to_s.in? available_models_for_current_user
102
+ begin
103
+ params[:model].constantize
104
+ rescue ActiveSupport::Concern::MultipleIncludedBlocks => e
105
+ raise "#{e}. Maybe #{params[:model]} model doesn't exists or there is naming conflicts with it"
106
+ end
107
+ end
108
+ end
109
+
110
+ def decorator_class(model_name = nil)
111
+ "#{model_name || model_class}Decorator".constantize
112
+ end
113
+
114
+ def form_class(model_name = nil)
115
+ "#{model_name || model_class}Form".constantize
116
+ end
117
+
118
+ def serializer_class(model_name = nil)
119
+ "#{model_name || model_class}Serializer".constantize
120
+ end
22
121
  end
23
122
  end
24
123
  end
@@ -3,13 +3,13 @@
3
3
  module Tramway::Api::V1
4
4
  class RecordsController < ::Tramway::Api::V1::ApplicationController
5
5
  before_action :check_available_model_class
6
- before_action :check_available_model_action
6
+ before_action :check_available_model_action_for_record, only: %i[show update destroy]
7
7
  before_action :authenticate_user_if_needed
8
8
 
9
9
  def index
10
- records = model_class.active.order(id: :desc).send params[:scope] || :all
11
- records = records.full_text_search params[:search] if params[:search]
12
- render json: records,
10
+ collection = available_action_for_collection
11
+
12
+ render json: collection,
13
13
  each_serializer: serializer_class,
14
14
  include: '*',
15
15
  status: :ok
@@ -29,7 +29,7 @@ module Tramway::Api::V1
29
29
  end
30
30
 
31
31
  def update
32
- record_form = form_class.new model_class.active.find_by! uuid: params[:id]
32
+ record_form = form_class.new record
33
33
  if record_form.submit snake_case params[:data][:attributes]
34
34
  render json: record_form.model,
35
35
  serializer: serializer_class,
@@ -41,7 +41,6 @@ module Tramway::Api::V1
41
41
  end
42
42
 
43
43
  def show
44
- record = model_class.active.find_by! uuid: params[:id]
45
44
  render json: record,
46
45
  serializer: serializer_class,
47
46
  include: '*',
@@ -49,52 +48,11 @@ module Tramway::Api::V1
49
48
  end
50
49
 
51
50
  def destroy
52
- record = model_class.active.find_by! uuid: params[:id]
53
51
  record.remove
54
52
  render json: record,
55
53
  serializer: serializer_class,
56
54
  include: '*',
57
55
  status: :no_content
58
56
  end
59
-
60
- private
61
-
62
- def check_available_model_class
63
- head(:unprocessable_entity) && return unless model_class
64
- end
65
-
66
- def check_available_model_action
67
- open_actions = Tramway::Api.available_models[model_class.to_s][:open]&.map(&:to_s) || []
68
- closed_actions = Tramway::Api.available_models[model_class.to_s][:closed]&.map(&:to_s) || []
69
- head(:unprocessable_entity) && return unless action_name.in? open_actions + closed_actions
70
- end
71
-
72
- def authenticate_user_if_needed
73
- if action_name.in?(Tramway::Api.available_models[model_class.to_s][:closed]&.map(&:to_s) || []) && !current_user
74
- head(:unauthorized) && return
75
- end
76
- end
77
-
78
- def model_class
79
- if params[:model].to_s.in? ::Tramway::Api.available_models.keys.map(&:to_s)
80
- begin
81
- params[:model].constantize
82
- rescue ActiveSupport::Concern::MultipleIncludedBlocks => e
83
- raise "#{e}. Maybe #{params[:model]} model doesn't exists or there is naming conflicts with it"
84
- end
85
- end
86
- end
87
-
88
- def decorator_class(model_name = nil)
89
- "#{model_name || model_class}Decorator".constantize
90
- end
91
-
92
- def form_class(model_name = nil)
93
- "#{model_name || model_class}Form".constantize
94
- end
95
-
96
- def serializer_class(model_name = nil)
97
- "#{model_name || model_class}Serializer".constantize
98
- end
99
57
  end
100
58
  end
@@ -3,7 +3,7 @@
3
3
  require 'tramway/helpers/class_name_helpers'
4
4
 
5
5
  class Tramway::Api::V1::UsersController < ::Tramway::Api::V1::ApplicationController
6
- before_action :authenticate_user, only: :show
6
+ before_action :authenticate, only: :show
7
7
  include Tramway::ClassNameHelpers
8
8
 
9
9
  def create
@@ -1,10 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'tramway/api/engine'
4
+ require 'tramway/api/records_models'
5
+ require 'tramway/api/singleton_models'
4
6
 
5
7
  module Tramway
6
8
  module Api
7
9
  class << self
10
+ include ::Tramway::Api::RecordsModels
11
+ include ::Tramway::Api::SingletonModels
12
+
8
13
  def auth_config
9
14
  @@auth_config ||= [{ user_model: ::Tramway::User::User, auth_attributes: :email }]
10
15
  end
@@ -31,16 +36,52 @@ module Tramway
31
36
  end
32
37
  end
33
38
 
34
- def set_available_models(**models)
35
- @@available_models ||= {}
36
- models = models.reduce({}) do |hash, pair|
37
- hash.merge! pair[0].to_s.camelize => pair[1]
39
+ def get_models_by_key(checked_models, project, role)
40
+ unless project.present?
41
+ error = Tramway::Error.new(
42
+ plugin: :admin,
43
+ method: :get_models_by_key,
44
+ message: "Looks like you have not create at lease one instance of #{Tramway::Core.application.model_class} model"
45
+ )
46
+ raise error.message
47
+ end
48
+ checked_models && checked_models != [] && checked_models[project][role]&.keys || []
49
+ end
50
+
51
+ def models_array(models_type:, role:)
52
+ instance_variable_get("@#{models_type}_models")&.map do |projects|
53
+ projects.last[role]&.keys
54
+ end&.flatten || []
55
+ end
56
+
57
+ def action_is_available(project:, role: :open, model_name:, action:, current_user: nil)
58
+ actions = select_actions(project: project, role: role, model_name: model_name)
59
+ if actions.present? && !actions.is_a?(Array)
60
+ raise "Looks like you did not used array type to define action permissions. Remember it should be this way: `#{model_name} => [ :#{action} ]` or `#{model_name} => [ { #{action}: lambda { |record, current_user| your_condition } } ]`"
38
61
  end
39
- @@available_models.merge! models
62
+
63
+ availability = actions&.select do |a|
64
+ if a.is_a? Symbol
65
+ a == action.to_sym
66
+ elsif a.is_a? Hash
67
+ a.keys.first.to_sym == action.to_sym
68
+ end
69
+ end&.first
70
+
71
+ return false unless availability.present?
72
+ return true if availability.is_a? Symbol
73
+
74
+ availability.values.first
40
75
  end
41
76
 
42
- def available_models
43
- @@available_models ||= {}
77
+ def select_actions(project:, role:, model_name:)
78
+ stringify_keys(@singleton_models&.dig(project, role))&.dig(model_name) || stringify_keys(@available_models&.dig(project, role))&.dig(model_name)
79
+ end
80
+
81
+ def stringify_keys(hash)
82
+ hash&.reduce({}) do |new_hash, pair|
83
+ new_hash.merge! pair[0].to_s => pair[1]
84
+ end
44
85
  end
45
86
  end
46
87
  end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tramway::Api::RecordsModels
4
+ def set_available_models(*models, project:, role: :open)
5
+ @available_models ||= {}
6
+ @available_models[project] ||= {}
7
+ @available_models[project][role] ||= {}
8
+ models.each do |model|
9
+ if model.class == Class
10
+ @available_models[project][role].merge! model => %i[index show update create destroy]
11
+ elsif model.class == Hash
12
+ @available_models[project][role].merge! model
13
+ end
14
+ end
15
+ @available_models = @available_models.with_indifferent_access
16
+ end
17
+
18
+ def available_models_for(project, role: :open)
19
+ models = get_models_by_key(@available_models, project, role)
20
+ if project_is_engine?(project)
21
+ models += engine_class(project).dependencies.map do |dependency|
22
+ if @available_models&.dig(dependency, role).present?
23
+ @available_models&.dig(dependency, role).keys
24
+ else
25
+ error = Tramway::Error.new(
26
+ plugin: :admin,
27
+ method: :available_models_for,
28
+ message: "There is no dependency `#{dependency}` for plugin: #{project}. Please, check file `tramway-#{project}/lib/tramway/#{project}/#{project}.rb`"
29
+ )
30
+ raise error
31
+ end
32
+ end.flatten.compact
33
+ end
34
+ models
35
+ end
36
+
37
+ def available_models(role:)
38
+ models_array models_type: :available, role: role
39
+ end
40
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tramway::Api::SingletonModels
4
+ def set_singleton_models(*models, project:, role: :open)
5
+ @singleton_models ||= {}
6
+ @singleton_models[project] ||= {}
7
+ @singleton_models[project][role] ||= {}
8
+ models.each do |model|
9
+ if model.class == Class
10
+ @singleton_models[project][role].merge! model => %i[index show update create destroy]
11
+ elsif model.class == Hash
12
+ @singleton_models[project][role].merge! model
13
+ end
14
+ end
15
+ @singleton_models = @singleton_models.with_indifferent_access
16
+ end
17
+
18
+ def singleton_models_for(project, role: :open)
19
+ models = get_models_by_key(@singleton_models, project, role)
20
+ if project_is_engine?(project)
21
+ models += engine_class(project).dependencies.map do |dependency|
22
+ @singleton_models&.dig(dependency, role)&.keys
23
+ end.flatten.compact
24
+ end
25
+ models
26
+ end
27
+
28
+ def singleton_models(role:)
29
+ models_array models_type: :singleton, role: role
30
+ end
31
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Tramway
4
4
  module Api
5
- VERSION = '1.7.1.2'
5
+ VERSION = '1.8.2'
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tramway-api
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.7.1.2
4
+ version: 1.8.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Pavel Kalashnikov
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-03-08 00:00:00.000000000 Z
11
+ date: 2020-04-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: active_model_serializers
@@ -81,6 +81,8 @@ files:
81
81
  - lib/tasks/tramway/api_tasks.rake
82
82
  - lib/tramway/api.rb
83
83
  - lib/tramway/api/engine.rb
84
+ - lib/tramway/api/records_models.rb
85
+ - lib/tramway/api/singleton_models.rb
84
86
  - lib/tramway/api/version.rb
85
87
  homepage: https://github.com/kalashnikovisme/tramway-dev
86
88
  licenses: []