tramway-api 1.8.1.1 → 1.8.3

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: 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