app_rail-airtable 0.2.12 → 0.3.2

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: 3093a14dafa5e25f4cc4a7791bedfc00f1c2f5941f99c6a07060ea60e12e7ff8
4
- data.tar.gz: bd3ece807677d1ffa0d29f92b254fd484ad10b0ab7ca16312b31126c3d96bd1a
3
+ metadata.gz: 98fa16c4b212cd84ea0d9cd5caa37100c3f3bf9d97919cb1814d914d45fdf2c6
4
+ data.tar.gz: d16166e491328eaa897086cd43940e11b52e8345bfd8bef3bcb547537304e2cd
5
5
  SHA512:
6
- metadata.gz: 5e79328b4a2eca0a521541ebc8164b91374263fc3f6e6f91d2d847774a65baabfad66bec4b4672484a8eedb8da060f6c5fc19f909537d8076e18a75b31c94384
7
- data.tar.gz: a0eb587cb217d6c336d9cbe8fd52f72eb41dc24e582c58877ba72d5dd7ec2b034a0711ac782a00e29dcfdea944cb531e65f532b031e5fcf1de0c25827016e99a
6
+ metadata.gz: 2532b3183fba2e26b117e232a54d65120f9e08a874d46a1a08e6331bc11ee10de6a8460622d68c7bc46ec633090beb023d7de7b4a34dc2546c6013469b2157d6
7
+ data.tar.gz: ae372f1540f615fffd90045c6e2c6b4f1e4252278dcb256d4262d04a6356b50e1510676ed94f6d0358c4608f967caec00214fa6df4ebb6b9334f41846ec5a85d
data/.gitignore CHANGED
@@ -1,3 +1,7 @@
1
+ .DS_STORE
2
+ *.swp
3
+ *.rbc
4
+ *.sass-cache
1
5
  /.bundle/
2
6
  /.yardoc
3
7
  /_yardoc/
@@ -10,3 +14,6 @@
10
14
  # rspec failure tracking
11
15
  .rspec_status
12
16
  .byebug_history
17
+
18
+ # dotenv
19
+ .env
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- app_rail-airtable (0.2.12)
4
+ app_rail-airtable (0.3.2)
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
 
@@ -17,6 +17,7 @@ module AppRail
17
17
  def self.airtable_attr(*attributes)
18
18
  attributes.each do |attribute|
19
19
  define_method(attribute.to_s.snake_case) { self[attribute] }
20
+ define_method("#{attribute.to_s.snake_case}=") { |value| self[attribute] = value }
20
21
  end
21
22
  end
22
23
 
@@ -12,19 +12,21 @@ module AppRail
12
12
 
13
13
  module ClassMethods
14
14
  def create(email:, password:)
15
- user = User.new("Email" => email, "Password Hash" => password_hash(password), "Access Token" => access_token)
15
+ user = User.new("Email" => email, "Password Hash" => password_hash(password), "Access Token" => next_access_token)
16
16
  user.create
17
17
  user
18
18
  end
19
19
 
20
20
  def create_session_as_json(email:, password:)
21
21
  user = find_by_email_and_password(email, password)
22
+ user["Access Token"] = next_access_token
23
+ user.save
22
24
  user&.oauth_session
23
25
  end
24
26
 
25
27
  def find_by_email_and_password(email, password)
26
28
  user = all(filter: "{Email} = \"#{email}\"").first
27
- user.valid_password? ? user : nil
29
+ user.valid_password?(password) ? user : nil
28
30
  end
29
31
 
30
32
  def find_by_access_token(access_token)
@@ -35,7 +37,7 @@ module AppRail
35
37
  BCrypt::Password.create(password)
36
38
  end
37
39
 
38
- def access_token
40
+ def next_access_token
39
41
  SecureRandom.hex
40
42
  end
41
43
  end
@@ -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,54 @@ 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
+
48
+ return unless block_given?
49
+ @@authenticated_route = true
50
+ yield
51
+ @@authenticated_route = false
52
+ end
38
53
 
39
- def self.resources(name, only: [:index, :show, :create], authenticated: false)
54
+ def self.resources(name, only: [:index, :show, :create])
40
55
  only = [only] if only.is_a?(Symbol)
41
56
 
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)
57
+ index_route(name, authenticated_route?) if only.include?(:index)
58
+ show_route(name, authenticated_route?) if only.include?(:show)
59
+ create_route(name, authenticated_route?) if only.include?(:create)
45
60
  end
46
61
 
47
- def self.index_route(name, authenticated)
62
+ def self.index_route(name, authenticated_route)
48
63
  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
64
+ authenticate! if authenticated_route
65
+ name.classify_constantize.index(user: authenticated_route ? current_user : nil).map(&:ar_list_item_as_json).to_json
51
66
  end
52
67
  end
53
68
 
54
- def self.show_route(name, authenticated)
69
+ def self.show_route(name, authenticated_route)
55
70
  get "/#{name.to_s}/:id" do
56
- authenticate! if authenticated
71
+ authenticate! if authenticated_route
57
72
  name.classify_constantize.find(params['id']).ar_stack_as_json.to_json
58
73
  end
59
74
  end
60
75
 
61
- def self.create_route(name, authenticated)
76
+ def self.create_route(name, authenticated_route)
62
77
  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)
78
+ authenticate! if authenticated_route
79
+ as_json = name.classify_constantize.create_as_json(current_user: authenticated_route ? current_user : nil, params: params_and_body_as_json)
65
80
  [201, as_json.to_json]
66
81
  end
67
82
  end
83
+
84
+ def self.authenticated_route?
85
+ @@authenticated_route
86
+ end
68
87
  end
69
88
  end
70
89
  end
@@ -1,5 +1,5 @@
1
1
  module AppRail
2
2
  module Airtable
3
- VERSION = "0.2.12"
3
+ VERSION = "0.3.2"
4
4
  end
5
5
  end
@@ -2,7 +2,18 @@
2
2
  *.swp
3
3
  *.rbc
4
4
  *.sass-cache
5
- /pkg
6
- /coverage
7
- .yardoc
8
- /doc
5
+ /.bundle/
6
+ /.yardoc
7
+ /_yardoc/
8
+ /coverage/
9
+ /doc/
10
+ /pkg/
11
+ /spec/reports/
12
+ /tmp/
13
+
14
+ # rspec failure tracking
15
+ .rspec_status
16
+ .byebug_history
17
+
18
+ # dotenv
19
+ .env
@@ -7,9 +7,15 @@ ruby '2.7.4'
7
7
 
8
8
  gem 'app_rail-airtable'
9
9
 
10
- # dev
11
- gem 'dotenv'
10
+ group :development do
11
+ gem 'dotenv'
12
+ end
12
13
 
13
- # test
14
- gem "rspec"
15
- gem "rack-test"
14
+ group :test do
15
+ gem "rspec"
16
+ gem "rack-test"
17
+ end
18
+
19
+ group :development, :test do
20
+ gem 'byebug'
21
+ end
@@ -1,5 +1,11 @@
1
1
  $stdout.sync = true
2
2
 
3
- require 'dotenv/load'
3
+ ENV['RACK_ENV'] ||= 'development'
4
+ require 'dotenv/load' if ENV['RACK_ENV'] == 'development'
5
+ require 'bundler'
6
+ Bundler.require(:default, ENV['RACK_ENV'].to_sym)
7
+
8
+ require 'dotenv/load' if ENV['RACK_ENV'] == 'development'
9
+
4
10
  require './lib/server'
5
11
  run Server
@@ -23,7 +23,6 @@ require "rack/test"
23
23
  require "app_rail/airtable"
24
24
 
25
25
  require './lib/server'
26
- require './lib/item_recommender'
27
26
 
28
27
  RSpec.configure do |config|
29
28
  # rspec-expectations config goes here. You can use an alternate
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.12
4
+ version: 0.3.2
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-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport