app_rail-airtable 0.4.3 → 0.4.6

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: f789fb754083245cc062131945cb235ac19070edd2e3ae154e5a233b1533f76b
4
- data.tar.gz: '08a45094b4ba5b5882a8a1baed2acc39c3345adaa8d8557b8ae2daaa3a2bb96c'
3
+ metadata.gz: 3e4126f9d575a705e24ba998e9adb2ecd3dc95c567e13668a733b246fe9401fc
4
+ data.tar.gz: 58b0c53b463db9b7689c580b1fc5d7284c0d72ddf10e51f5eeeee1e63a65fc65
5
5
  SHA512:
6
- metadata.gz: e9bdf986a03d4ce2e00368f7a4ac5048a8b2271778647d1ea27adce3c8b8fa185854e339b2769ee0e0acfce5bfb6dc985cdafc3b4787a8f78fad2da5fdda1681
7
- data.tar.gz: 995431a75366484398c7d90e1e12a3950ac47c23ca6ebe78b9410320dd17224cf08d401df7f613f60b62dca8458103f506d5ebe3e6d5bb0aea0a60a726cce2dc
6
+ metadata.gz: f5969fbe95e911778f4b44104137c6ffe13163e55ea0a57aa13d6b03746ea4ef00daec15b6af9eb1a1c5d58fd2da5903e6cc2e90c71d7cd222dbacfa69b9f11f
7
+ data.tar.gz: b73be3571e4711e835b2a287a38132e8b38c071d433672de505ccce12c2e1658206fb35fdf4985dcc7ef6b32853cf69996e81589ac50fbfec431b6fed261cfe1
data/CHANGELOG.md CHANGED
@@ -1,3 +1,7 @@
1
+ # 0.4.6
2
+ * Add authenticatable_resource POST / DELETE `/<resource>/session` routes for sign in and sign out
3
+ * Simplify sign in methods & remove Authenticatable#create_session_as_json
4
+
1
5
  # 0.4.0
2
6
 
3
7
  ### Breaking changes
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- app_rail-airtable (0.4.3)
4
+ app_rail-airtable (0.4.6)
5
5
  activesupport
6
6
  airrecord
7
7
  app_rail-steps
@@ -14,16 +14,16 @@ PATH
14
14
  GEM
15
15
  remote: https://rubygems.org/
16
16
  specs:
17
- activesupport (7.0.2.3)
17
+ activesupport (7.0.2.4)
18
18
  concurrent-ruby (~> 1.0, >= 1.0.2)
19
19
  i18n (>= 1.6, < 2)
20
20
  minitest (>= 5.1)
21
21
  tzinfo (~> 2.0)
22
- airrecord (1.0.9)
23
- faraday (>= 0.10, < 3.0)
22
+ airrecord (1.0.10)
23
+ faraday (>= 1.0, < 3.0)
24
24
  faraday-net_http_persistent
25
25
  net-http-persistent
26
- app_rail-steps (0.2.0)
26
+ app_rail-steps (0.2.9)
27
27
  bcrypt (3.1.17)
28
28
  byebug (11.1.3)
29
29
  concurrent-ruby (1.1.10)
@@ -26,9 +26,9 @@ Gem::Specification.new do |spec|
26
26
  spec.executables << 'ara_generator'
27
27
 
28
28
  spec.require_paths = ['lib']
29
- spec.add_dependency 'app_rail-steps'
30
29
  spec.add_dependency 'activesupport'
31
30
  spec.add_dependency 'airrecord'
31
+ spec.add_dependency 'app_rail-steps'
32
32
  spec.add_dependency 'bcrypt'
33
33
  spec.add_dependency 'faraday', '~> 2.2'
34
34
  spec.add_dependency 'faraday-net_http_persistent', '~> 2.0' # workaround to make Faraday work after upgrading to 2.2.0
@@ -6,6 +6,8 @@ require 'securerandom'
6
6
  module AppRail
7
7
  module Airtable
8
8
  module Authenticatable
9
+ class AlreadyExistsError < StandardError; end
10
+
9
11
  include BCrypt
10
12
 
11
13
  def self.included(klass)
@@ -15,25 +17,22 @@ module AppRail
15
17
 
16
18
  module ClassMethods
17
19
  def create(email:, password:)
20
+ raise AlreadyExistsError if find_by_email(email)
21
+
18
22
  user = new('Email' => email, 'Password Hash' => password_hash(password), 'Access Token' => next_access_token)
19
23
  user.create
20
24
  user
21
25
  end
22
26
 
23
- def create_session_as_json(email:, password:)
24
- user = find_by_email_and_password(email, password)
25
- return nil unless user
26
-
27
- user['Access Token'] = next_access_token
28
- user.save
29
- user&.oauth_session
30
- end
31
-
32
27
  def find_by_email_and_password(email, password)
33
- user = all(filter: "{Email} = \"#{email}\"").first
28
+ user = find_by_email(email)
34
29
  user&.valid_password?(password) ? user : nil
35
30
  end
36
31
 
32
+ def find_by_email(email)
33
+ all(filter: "{Email} = \"#{email}\"").first
34
+ end
35
+
37
36
  def find_by_access_token(access_token)
38
37
  all(filter: "{Access Token} = \"#{access_token}\"").first
39
38
  end
@@ -66,7 +65,21 @@ module AppRail
66
65
  end
67
66
 
68
67
  def oauth_session
69
- { access_token: self['Access Token'], scope: :user, refresh_token: '', token_type: :bearer, expires_in: 60_000 }
68
+ ensure_access_token!
69
+
70
+ {
71
+ access_token: self['Access Token'],
72
+ scope: :user,
73
+ token_type: :bearer,
74
+ expires_in: 31_536_000 # 1 year
75
+ }
76
+ end
77
+
78
+ def ensure_access_token!
79
+ unless self['Access Token']
80
+ self['Access Token'] = User.next_access_token
81
+ save
82
+ end
70
83
  end
71
84
  end
72
85
  end
@@ -12,6 +12,10 @@ class Symbol
12
12
  ActiveSupport::Inflector.pluralize(self)
13
13
  end
14
14
 
15
+ def singularize
16
+ ActiveSupport::Inflector.singularize(self)
17
+ end
18
+
15
19
  def classify
16
20
  ActiveSupport::Inflector.classify(self)
17
21
  end
@@ -42,6 +46,8 @@ module AppRail
42
46
  # Allowing the routes to use `authenticate!` and `current_user`
43
47
  helpers AppRail::Airtable::AuthenticationHelpers
44
48
 
49
+ sign_in_route(name)
50
+ sign_out_route(name)
45
51
  resources(name, only: only)
46
52
 
47
53
  return unless block_given?
@@ -60,6 +66,26 @@ module AppRail
60
66
  update_route(name, authenticated_route?) if only.include?(:update)
61
67
  end
62
68
 
69
+ def self.sign_in_route(name)
70
+ post "/#{name}/session" do
71
+ resource = name.classify_constantize.authenticate_by_params(params)
72
+ halt 401 unless resource
73
+
74
+ resource.oauth_session.to_json
75
+ end
76
+ end
77
+
78
+ def self.sign_out_route(name)
79
+ delete "/#{name}/session" do
80
+ authenticate!
81
+ current_user.access_token = nil
82
+ current_user.save
83
+
84
+ # Assume that the client will reload and trigger a 401
85
+ [].to_json
86
+ end
87
+ end
88
+
63
89
  def self.index_route(name, authenticated_route)
64
90
  get "/#{name}" do
65
91
  authenticate! if authenticated_route
@@ -77,9 +103,13 @@ module AppRail
77
103
  def self.create_route(name, authenticated_route)
78
104
  post "/#{name}" do
79
105
  authenticate! if authenticated_route
80
- as_json = name.classify_constantize.create_as_json(current_user: authenticated_route ? current_user : nil,
81
- params: params_and_body_as_json)
82
- [201, as_json.to_json]
106
+ begin
107
+ as_json = name.classify_constantize.create_as_json(current_user: authenticated_route ? current_user : nil,
108
+ params: params_and_body_as_json)
109
+ [201, as_json.to_json]
110
+ rescue AppRail::Airtable::Authenticatable::AlreadyExistsError
111
+ [422, { error: "#{name.singularize} already exists" }.to_json]
112
+ end
83
113
  end
84
114
  end
85
115
 
@@ -2,6 +2,6 @@
2
2
 
3
3
  module AppRail
4
4
  module Airtable
5
- VERSION = '0.4.3'
5
+ VERSION = '0.4.6'
6
6
  end
7
7
  end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ ENV['RACK_ENV'] ||= 'development'
4
+
5
+ require 'dotenv/load' if ENV['RACK_ENV'] == 'development'
6
+
7
+ require 'bundler'
8
+ Bundler.require(:default, ENV['RACK_ENV'].to_sym)
@@ -1,13 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  $stdout.sync = true
4
-
5
- ENV['RACK_ENV'] ||= 'development'
6
- require 'dotenv/load' if ENV['RACK_ENV'] == 'development'
7
- require 'bundler'
8
- Bundler.require(:default, ENV['RACK_ENV'].to_sym)
9
-
10
- require 'dotenv/load' if ENV['RACK_ENV'] == 'development'
11
-
4
+ require './boot'
12
5
  require './lib/server'
13
6
  run Server
metadata CHANGED
@@ -1,17 +1,17 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: app_rail-airtable
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.3
4
+ version: 0.4.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matt Brooke-Smith
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-04-18 00:00:00.000000000 Z
11
+ date: 2022-05-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: app_rail-steps
14
+ name: activesupport
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - ">="
@@ -25,7 +25,7 @@ dependencies:
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
27
  - !ruby/object:Gem::Dependency
28
- name: activesupport
28
+ name: airrecord
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - ">="
@@ -39,7 +39,7 @@ dependencies:
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
41
  - !ruby/object:Gem::Dependency
42
- name: airrecord
42
+ name: app_rail-steps
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - ">="
@@ -187,6 +187,7 @@ files:
187
187
  - templates/project/.gitignore
188
188
  - templates/project/Gemfile
189
189
  - templates/project/app.json
190
+ - templates/project/boot.rb
190
191
  - templates/project/config.ru
191
192
  - templates/project/lib/server.rb.tt
192
193
  - templates/project/spec/server_spec.rb.tt