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 +4 -4
- data/app/controllers/tramway/api/v1/application_controller.rb +99 -0
- data/app/controllers/tramway/api/v1/records_controller.rb +5 -47
- data/app/controllers/tramway/api/v1/users_controller.rb +1 -1
- data/lib/tramway/api.rb +48 -7
- data/lib/tramway/api/records_models.rb +40 -0
- data/lib/tramway/api/singleton_models.rb +31 -0
- data/lib/tramway/api/version.rb +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 56cacd097b745beaad7a04f1b31a63f645ffcb0ca3f2705be6c636765e04968a
|
4
|
+
data.tar.gz: 30b2598b412f3b87d48895254e1eef6ffd8b1c20299ea07b9bee766397aff8a5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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 :
|
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
|
-
|
11
|
-
|
12
|
-
render json:
|
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
|
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 :
|
6
|
+
before_action :authenticate, only: :show
|
7
7
|
include Tramway::ClassNameHelpers
|
8
8
|
|
9
9
|
def create
|
data/lib/tramway/api.rb
CHANGED
@@ -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
|
35
|
-
|
36
|
-
|
37
|
-
|
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
|
-
|
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
|
43
|
-
|
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
|
data/lib/tramway/api/version.rb
CHANGED
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.
|
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-
|
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: []
|