tramway-api 1.8.1.1 → 1.8.3

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: 4d1e2133a961aaba201c222f211ca45a609f559b89d44622c345e802f29f67a6
4
- data.tar.gz: f8856dba0c3e478af5436cdf93df7a77cfb4b876fed6ce1c3a41c9f7da710674
3
+ metadata.gz: 151b3c808fba04666fdb2cccbd5368d45c86c6539878c52e1c9fa93905a3eb85
4
+ data.tar.gz: 8eeaf9cde77e40c5f170c3c1d242c88025003d10176947e943ae59dd10520b25
5
5
  SHA512:
6
- metadata.gz: 8143cc790cebc76de7dcd2746204bc8503a4a74ed9b4eefb3068e65cc456b6920a775d0cc107acd01c9dd651cd4c87a6394cf6cf807ca37626a13bd2b60adc08
7
- data.tar.gz: 45b9ec7765178d2d26869ec69bfc315b4c714fd5632aa1d86e537ea793617aac85a59dd3f08ea11f3139d5b008ebf49772888557c13859bd7a0975d68a8cd21e
6
+ metadata.gz: 989b0c66ec542b84a55f803f676b0778b78ccd012ced6579ae858c0aaa31f0d345f9ff4ea737a64e393735a37ffa6285fe153ceb862b0b1dc692a4f1f2999ee3
7
+ data.tar.gz: ac301bb8e6fc9a7dc5e8ae7a2100703977cc7d9d58a4f2c384bdb02130ed30b02b214b1c682874b4b32fdce38f33017faadfa89352b8cb4081fad439305c3d23
data/README.md CHANGED
@@ -44,6 +44,7 @@ coming soon...
44
44
  gem 'state_machine', github: 'seuros/state_machine'
45
45
  gem 'knock'
46
46
  gem 'audited'
47
+ gem 'ransack'
47
48
  ```
48
49
 
49
50
  ## Usage
@@ -64,10 +65,24 @@ gem 'knock'
64
65
 
65
66
  Run `bundle install`
66
67
 
68
+ ### Initialize @application object
69
+
70
+ [How-to](https://github.com/Purple-Magic/tramway-core/blob/develop/README.md#every-tramway-application-need-initialized-application-object-or-if-you-create-tramway-plugin-it-should-be-application_engine-object)
71
+
72
+ *config/routes.rb*
73
+
74
+ ```ruby
75
+ Rails.application.routes.draw do
76
+ # ...
77
+ mount Tramway::Api::Engine, at: '/api'
78
+ # ...
79
+ end
80
+ ```
81
+
67
82
  Then generate User (you use another name, it's just an example) model
68
83
 
69
84
  ```
70
- rails g model user email:text password_digest:text username:text state:text uid:text
85
+ rails g model user email:text password_digest:text username:text state:text uuid:uuid
71
86
  ```
72
87
 
73
88
  Enable extension in your database:
@@ -100,11 +115,26 @@ class User < Tramway::Core::ApplicationRecord
100
115
  end
101
116
  ```
102
117
 
103
- Create file `config/initializers/tramway.rb`
118
+ #### Create file `config/initializers/tramway.rb`
119
+ #### If you need JWT authentication add this line to the `config/initializers/tramway.rb`
104
120
 
105
121
  ```ruby
106
122
  ::Tramway::Api.auth_config = { user_model: User, auth_attributes: %i[email username] }
107
- ::Tramway::Api.set_available_models user: { open: %i[create], closed: %i[update] }
123
+ ```
124
+
125
+ #### Configurate available models. Tramway will create end points according to this config
126
+
127
+ ```
128
+ ::Tramway::Api.set_available_models({
129
+ User => [
130
+ {
131
+ show: lambda do |record, current_user|
132
+ record.id == current_user.id # shows only current_user profile
133
+ end
134
+ }
135
+ ],
136
+ project: :your_project_name
137
+ })
108
138
  ```
109
139
 
110
140
  Run `rails g tramway:core:install`
@@ -316,7 +346,7 @@ Create serializer
316
346
  *app/serializers/user_serializer.rb*
317
347
 
318
348
  ```ruby
319
- class UserSerializer < Tramway::Core::ApplicationSerializer
349
+ class UserSerializer < Tramway::Api::V1::ApplicationSerializer
320
350
  attributes :username, :email
321
351
  end
322
352
  ```
@@ -353,9 +383,39 @@ Docs coming soon
353
383
 
354
384
  ### Show
355
385
 
356
- Production ready
386
+ #### Description
357
387
 
358
- Docs coming soon
388
+ It returns just one record, if it is not deleted.
389
+
390
+ #### Using
391
+
392
+ ##### Allow method show in tramway initializer for `YourModel`
393
+
394
+ *config/initializers/tramway.rb*
395
+
396
+ ```ruby
397
+ ::Tramway::Api.set_available_models({ YourModel => [ :show ] }, project: :your_project_name })
398
+ ```
399
+
400
+ ##### Create serializer
401
+
402
+ *app/serializers/user_serializer.rb*
403
+
404
+ ```ruby
405
+ class UserSerializer < Tramway::Core::ApplicationSerializer
406
+ attributes :username, :email
407
+ end
408
+ ```
409
+
410
+ ##### Run your server on the localhost `rails s`
411
+ ##### Made this query to test new API method (for example: you can create file `bin/test_tramway.rb` with this lines):
412
+
413
+ ```ruby
414
+ require 'net/http'
415
+
416
+ YourModel.create! attribute_1: 'some value', attribute_2: 'some_value'
417
+ Net::HTTP.get('localhost:3000', "/api/v1/records/#{YourModel.last.id}?model=YourModel")
418
+ ```
359
419
 
360
420
  ### Destroy
361
421
 
@@ -58,7 +58,9 @@ module Tramway
58
58
 
59
59
  def current_user
60
60
  Tramway::Api.user_based_models.map do |user_based_model|
61
- send("current_#{user_based_model.name.underscore}")
61
+ unless user_based_model == User
62
+ send("current_#{user_based_model.name.underscore}")
63
+ end
62
64
  end.compact.first
63
65
  end
64
66
  end
@@ -15,10 +15,110 @@ module Tramway
15
15
  def snake_case(params)
16
16
  hash = {}
17
17
  params.each do |attribute, value|
18
- hash.merge! attribute.to_s.gsub('-', '_') => value
18
+ key = UUID.validate(attribute) ? attribute : attribute.to_s.gsub('-', '_')
19
+ hash.merge! key => value
19
20
  end
20
21
  hash
21
22
  end
23
+
24
+ private
25
+
26
+ def record
27
+ id_method = Tramway::Api.id_method_of(model: model_class) || :uuid
28
+ @record = model_class.find_by! id_method => params[:id] if params[:id].present?
29
+ end
30
+
31
+ def records
32
+ collection = model_class.active.order(id: :desc).send params[:scope] || :all
33
+ collection = collection.full_text_search params[:search] if params[:search]
34
+ collection
35
+ end
36
+
37
+ def check_available_model_class
38
+ unless model_class
39
+ head(:unauthorized) && return unless current_user
40
+ head(:unprocessable_entity) && return
41
+ end
42
+ end
43
+
44
+ def check_available_model_action_for_record
45
+ action_is_available = check_action
46
+ action_is_available.tap do
47
+ if action_is_available.is_a?(Proc) && !action_is_available.call(record, current_user)
48
+ head(:unprocessable_entity) && return
49
+ end
50
+ end
51
+ end
52
+
53
+ def available_action_for_collection
54
+ action_is_available = check_action
55
+ return records if action_is_available == true
56
+
57
+ action_is_available.call records, current_user if action_is_available.is_a?(Proc)
58
+ end
59
+
60
+ def check_action
61
+ action_is_available = checking_roles.map do |role|
62
+ Tramway::Api.action_is_available(
63
+ action: action_name.to_sym,
64
+ project: (@application_engine || @application.name),
65
+ role: role,
66
+ model_name: params[:model],
67
+ current_user: current_user
68
+ )
69
+ end.compact.uniq - [false]
70
+
71
+ if action_is_available.count > 1
72
+ Tramway::Error.raise_error(:tramway, :api, :api, :v1, :records_controller, :available_action_for_collection, :duplicate_actions)
73
+ end
74
+
75
+ action_is_available = action_is_available.first
76
+
77
+ action_is_available.tap do
78
+ head(:unprocessable_entity) && return unless action_is_available
79
+ end
80
+ end
81
+
82
+ def authenticate_user_if_needed
83
+ action_is_open = Tramway::Api.action_is_available(
84
+ action: action_name.to_sym,
85
+ project: (@application_engine || @application.name),
86
+ model_name: params[:model]
87
+ )
88
+ head(:unauthorized) && return if !current_user && !action_is_open
89
+ end
90
+
91
+ def available_models_for_current_user
92
+ checking_roles.reduce([]) do |models, role|
93
+ models += ::Tramway::Api.available_models(role: role).map(&:to_s)
94
+ end
95
+ end
96
+
97
+ def checking_roles
98
+ [:open, current_user&.role].compact
99
+ end
100
+
101
+ protected
102
+
103
+ def model_class
104
+ begin
105
+ params[:model].constantize
106
+ rescue ActiveSupport::Concern::MultipleIncludedBlocks => e
107
+ raise "#{e}. Maybe #{params[:model]} model doesn't exists or there is naming conflicts with it"
108
+ end
109
+ end
110
+
111
+ def decorator_class(model_name = nil)
112
+ "#{model_name || model_class}Decorator".constantize
113
+ end
114
+
115
+ def form_class(model_name = nil)
116
+ "#{model_name || model_class}Form".constantize
117
+ end
118
+
119
+ def serializer_class(model_name = nil)
120
+ "#{model_name || model_class}Serializer".constantize
121
+ end
22
122
  end
23
123
  end
24
124
  end
@@ -3,7 +3,7 @@
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_for_record, only: [ :show, :update, :destroy ]
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
@@ -54,102 +54,5 @@ module Tramway::Api::V1
54
54
  include: '*',
55
55
  status: :no_content
56
56
  end
57
-
58
- private
59
-
60
- def record
61
- if params[:id].present?
62
- @record = model_class.find_by! uuid: params[:id]
63
- end
64
- end
65
-
66
- def records
67
- collection = model_class.active.order(id: :desc).send params[:scope] || :all
68
- collection = collection.full_text_search params[:search] if params[:search]
69
- collection
70
- end
71
-
72
- def check_available_model_class
73
- unless model_class
74
- head(:unauthorized) && return unless current_user
75
- head(:unprocessable_entity) && return
76
- end
77
- end
78
-
79
- def check_available_model_action_for_record
80
- action_is_available = check_action
81
- action_is_available.tap do
82
- head(:unprocessable_entity) && return if action_is_available.is_a?(Proc) && !action_is_available.call(record, current_user)
83
- end
84
- end
85
-
86
- def available_action_for_collection
87
- action_is_available = check_action
88
- return records if action_is_available == true
89
- action_is_available.call records, current_user if action_is_available.is_a?(Proc)
90
- end
91
-
92
- def check_action
93
- action_is_available = checking_roles.map do |role|
94
- Tramway::Api.action_is_available(
95
- action: action_name.to_sym,
96
- project: (@application_engine || @application.name),
97
- role: role,
98
- model_name: params[:model],
99
- current_user: current_user
100
- )
101
- end.compact.uniq - [false]
102
-
103
- if action_is_available.count > 1
104
- Tramway::Error.raise_error(:tramway, :api, :api, :v1, :records_controller, :available_action_for_collection, :duplicate_actions)
105
- end
106
-
107
- action_is_available = action_is_available.first
108
-
109
- action_is_available.tap do
110
- head(:unprocessable_entity) && return unless action_is_available
111
- end
112
- end
113
-
114
- def authenticate_user_if_needed
115
- action_is_open = Tramway::Api.action_is_available(
116
- action: action_name.to_sym,
117
- project: (@application_engine || @application.name),
118
- model_name: params[:model]
119
- )
120
- head(:unauthorized) && return if !current_user && !action_is_open
121
- end
122
-
123
- def model_class
124
- if params[:model].to_s.in? available_models_for_current_user
125
- begin
126
- params[:model].constantize
127
- rescue ActiveSupport::Concern::MultipleIncludedBlocks => e
128
- raise "#{e}. Maybe #{params[:model]} model doesn't exists or there is naming conflicts with it"
129
- end
130
- end
131
- end
132
-
133
- def available_models_for_current_user
134
- checking_roles.reduce([]) do |models, role|
135
- models += ::Tramway::Api.available_models(role: role).map(&:to_s)
136
- end
137
- end
138
-
139
- def checking_roles
140
- [ :open, current_user&.role ].compact
141
- end
142
-
143
- def decorator_class(model_name = nil)
144
- "#{model_name || model_class}Decorator".constantize
145
- end
146
-
147
- def form_class(model_name = nil)
148
- "#{model_name || model_class}Form".constantize
149
- end
150
-
151
- def serializer_class(model_name = nil)
152
- "#{model_name || model_class}Serializer".constantize
153
- end
154
57
  end
155
58
  end
@@ -6,7 +6,8 @@ class Tramway::Api::V1::ApplicationSerializer < ActiveModel::Serializer
6
6
  attribute :id
7
7
 
8
8
  def id
9
- object.uuid
9
+ id_method = Tramway::Api.id_method_of(model: object.class) || :uuid
10
+ object.send(id_method)
10
11
  end
11
12
 
12
13
  def created_at
@@ -27,12 +27,8 @@ class Tramway::Api::V1::ErrorSerializer < ActiveModel::Serializer
27
27
  end
28
28
 
29
29
  object.model&.attributes&.each do |attribute_key, attribute_value|
30
- if attribute_value.is_a?(Reform::Form)
31
- error_messages.merge!(error_messages(attribute_value, path + [attribute_key]))
32
- elsif attribute_value.is_a?(Array)
30
+ if attribute_value.is_a?(Array)
33
31
  attribute_value.each_with_index do |array_attribute_value, array_attribute_key|
34
- next unless array_attribute_value.is_a?(Reform::Form)
35
-
36
32
  error_messages.merge!(
37
33
  error_messages(
38
34
  array_attribute_value,
@@ -56,7 +56,10 @@ module Tramway
56
56
 
57
57
  def action_is_available(project:, role: :open, model_name:, action:, current_user: nil)
58
58
  actions = select_actions(project: project, role: role, model_name: model_name)
59
- 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 } } ]`" if actions.present? && !actions.is_a?(Array)
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 } } ]`"
61
+ end
62
+
60
63
  availability = actions&.select do |a|
61
64
  if a.is_a? Symbol
62
65
  a == action.to_sym
@@ -80,6 +83,17 @@ module Tramway
80
83
  new_hash.merge! pair[0].to_s => pair[1]
81
84
  end
82
85
  end
86
+
87
+ def id_methods_of(options = {})
88
+ @@id_methods ||= {}
89
+ @@id_methods.merge!(options.reduce({}) do |hash, pair|
90
+ hash.merge! pair[0].to_s => pair[1]
91
+ end)
92
+ end
93
+
94
+ def id_method_of(model:)
95
+ @@id_methods[model.to_s]
96
+ end
83
97
  end
84
98
  end
85
99
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Tramway
4
4
  module Api
5
- VERSION = '1.8.1.1'
5
+ VERSION = '1.8.3'
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.8.1.1
4
+ version: 1.8.3
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-26 00:00:00.000000000 Z
11
+ date: 2020-06-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: active_model_serializers