app_rail-airtable 0.2.10 → 0.3.0

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: 3e57f8d279b01f1a7672be43fce5dda36da9df13bc3152399646f5be729d522c
4
- data.tar.gz: 7928368ae9d1b4edfd75c651af688be2aa0e7697f31fd5c87afb1a9e96e3945c
3
+ metadata.gz: 592d97e9fc6dbe4177847fdbfbc5c003620d179caee7887efb23f91d5f736ca7
4
+ data.tar.gz: 985e3ac9e23f4fe318c4944c2c3720a656faead5b5de3e3149fe58013aaa173c
5
5
  SHA512:
6
- metadata.gz: 5eef1c52f304ffe1b0050ff5a7278e47c825dce1e7e08a7af69550894070e23a465dc719fce7dddabfa06de9336f2b63d230685098d09a5c02711b17fe43394d
7
- data.tar.gz: e3629a453d333d78aac608f45ac04b303b27c636f4350fb0f5c2b42c739756a274faabd55a08278b0cc445a5777f62ae57431acea477dae20575ff1cfac53e59
6
+ metadata.gz: 80ae0eea7fbd168f1b469a5bfc9255940f0c62875d232427fd654d123e3b02aab822646cf6fa23313ca3fe7e653d0d73935927b8c6dff74dec8a01acf5edd431
7
+ data.tar.gz: 83e8736f2dc7dc42d276c45a83d8597c98d1f38faee8cf09e581f19256f22f64de81fa34a1acf9f290f9e4638a4bc00f14e25787d29bf2507d2bc3bbba44a13b
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- app_rail-airtable (0.2.10)
4
+ app_rail-airtable (0.3.0)
5
5
  activesupport
6
6
  airrecord
7
7
  bcrypt
data/README.md CHANGED
@@ -36,7 +36,18 @@ To provide support for routes, models can implement
36
36
  In order to support authentication you should create a class (normally `User`) and inherit from `AppRail::Airtable::AuthenticationRecord`. Your table needs `Email`, `Password Hash` and `Access Token` columns.
37
37
 
38
38
  ### Servers
39
- You should create a single server which extends `AppRail::Airtable::Sinatra`, then add routes with the `resources` macro to add `index`, `show` and `create` routes. You can also provide your own routes.
39
+ You should create a single server which extends `AppRail::Airtable::Sinatra`.
40
+
41
+ App Rail Airtable provides two helpers to generate routes
42
+
43
+ **resources(name, only:)**
44
+ Creates routes that map to a table. It delegates from the route to a model method
45
+ * `index` to `ar_list_item`
46
+ * `show` to `ar_stack`
47
+ * `create` to `self.create_as_json`
48
+
49
+ **authenticable_resources(name, , only:)**
50
+ Acts as `resources` but also takes a block of routes. Those nested routes will all call the `authenticate!` helper method before running. The `authenticate!` helper will call a lookup helper `find_authenticatable_resource(access_token:)` with the bearer token found in the `HTTP_AUTHORIZATION` header, which should be used to look up the correct object or return nil if none is found (resulting in a 401 response).
40
51
 
41
52
  ## License
42
53
 
@@ -23,9 +23,10 @@ module AppRail
23
23
  end
24
24
 
25
25
  def find_by_email_and_password(email, password)
26
- all(filter: "AND({Email} = \"#{email}\",{Password Hash} = \"#{password_hash(password)}\")").first
26
+ user = all(filter: "{Email} = \"#{email}\"").first
27
+ user.valid_password?(password) ? user : nil
27
28
  end
28
-
29
+
29
30
  def find_by_access_token(access_token)
30
31
  all(filter: "{Access Token} = \"#{access_token}\"").first
31
32
  end
@@ -38,6 +39,14 @@ module AppRail
38
39
  SecureRandom.hex
39
40
  end
40
41
  end
42
+
43
+ def valid_password?(password)
44
+ BCrypt::Password.new(password_hash) == password
45
+ end
46
+
47
+ def password_hash
48
+ self["Password Hash"]
49
+ end
41
50
 
42
51
  def oauth_session
43
52
  { access_token: self["Access Token"], scope: :user, refresh_token: "", token_type: :bearer, expires_in: 60000 }
@@ -6,7 +6,7 @@ module AppRail
6
6
  end
7
7
 
8
8
  def find_current_user
9
- authorization_header && bearer_token ? User.find_by_access_token(bearer_token) : nil
9
+ authorization_header && bearer_token ? find_authenticatable_resource(access_token: bearer_token) : nil
10
10
  end
11
11
 
12
12
  def bearer_token
@@ -24,6 +24,7 @@ end
24
24
  module AppRail
25
25
  module Airtable
26
26
  class Sinatra < Sinatra::Base
27
+ @@authenticated_route = false
27
28
 
28
29
  helpers do
29
30
  def request_body_as_json
@@ -35,36 +36,52 @@ module AppRail
35
36
  request_body_as_json.merge(params)
36
37
  end
37
38
  end
39
+
40
+ def self.authenticatable_resources(name, only: [:index, :show, :create])
41
+
42
+ # If authentication is used then include the correct helpers
43
+ # Allowing the routes to use `authenticate!` and `current_user`
44
+ helpers AppRail::Airtable::AuthenticationHelpers
45
+
46
+ resources(name, only: only)
47
+ @@authenticated_route = true
48
+ yield
49
+ @@authenticated_route = false
50
+ end
38
51
 
39
- def self.resources(name, only: [:index, :show, :create], authenticated: false)
52
+ def self.resources(name, only: [:index, :show, :create])
40
53
  only = [only] if only.is_a?(Symbol)
41
54
 
42
- index_route(name, authenticated) if only.include?(:index)
43
- show_route(name, authenticated) if only.include?(:show)
44
- create_route(name, authenticated) if only.include?(:create)
55
+ index_route(name, authenticated_route?) if only.include?(:index)
56
+ show_route(name, authenticated_route?) if only.include?(:show)
57
+ create_route(name, authenticated_route?) if only.include?(:create)
45
58
  end
46
59
 
47
- def self.index_route(name, authenticated)
60
+ def self.index_route(name, authenticated_route)
48
61
  get "/#{name.to_s}" do
49
- authenticate! if authenticated
50
- name.classify_constantize.index(user: authenticated ? current_user : nil).map(&:ar_list_item_as_json).to_json
62
+ authenticate! if authenticated_route
63
+ name.classify_constantize.index(user: authenticated_route ? current_user : nil).map(&:ar_list_item_as_json).to_json
51
64
  end
52
65
  end
53
66
 
54
- def self.show_route(name, authenticated)
67
+ def self.show_route(name, authenticated_route)
55
68
  get "/#{name.to_s}/:id" do
56
- authenticate! if authenticated
69
+ authenticate! if authenticated_route
57
70
  name.classify_constantize.find(params['id']).ar_stack_as_json.to_json
58
71
  end
59
72
  end
60
73
 
61
- def self.create_route(name, authenticated)
74
+ def self.create_route(name, authenticated_route)
62
75
  post "/#{name.to_s}" do
63
- authenticate! if authenticated
64
- as_json = name.classify_constantize.create_as_json(current_user: authenticated ? current_user : nil, params: params_and_body_as_json)
76
+ authenticate! if authenticated_route
77
+ as_json = name.classify_constantize.create_as_json(current_user: authenticated_route ? current_user : nil, params: params_and_body_as_json)
65
78
  [201, as_json.to_json]
66
79
  end
67
80
  end
81
+
82
+ def self.authenticated_route?
83
+ @@authenticated_route
84
+ end
68
85
  end
69
86
  end
70
87
  end
@@ -1,5 +1,5 @@
1
1
  module AppRail
2
2
  module Airtable
3
- VERSION = "0.2.10"
3
+ VERSION = "0.3.0"
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: app_rail-airtable
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.10
4
+ version: 0.3.0
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: 2021-10-06 00:00:00.000000000 Z
11
+ date: 2021-10-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport