wcc-data 0.1.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.
Files changed (52) hide show
  1. checksums.yaml +7 -0
  2. data/.env.example +3 -0
  3. data/.gitignore +18 -0
  4. data/.rspec +2 -0
  5. data/Gemfile +4 -0
  6. data/LICENSE.txt +22 -0
  7. data/README.md +29 -0
  8. data/Rakefile +36 -0
  9. data/circle.yml +6 -0
  10. data/lib/wcc/data.rb +26 -0
  11. data/lib/wcc/data/config.rb +45 -0
  12. data/lib/wcc/data/enumerated_type.rb +63 -0
  13. data/lib/wcc/data/faraday_client_app_token_auth.rb +64 -0
  14. data/lib/wcc/data/mapper.rb +16 -0
  15. data/lib/wcc/data/mapper/attributes.rb +54 -0
  16. data/lib/wcc/data/mapper/json_response.rb +20 -0
  17. data/lib/wcc/data/mapper/rest_configuration.rb +36 -0
  18. data/lib/wcc/data/mapper/rest_query.rb +28 -0
  19. data/lib/wcc/data/model.rb +11 -0
  20. data/lib/wcc/data/nucleus.rb +15 -0
  21. data/lib/wcc/data/nucleus/address.rb +17 -0
  22. data/lib/wcc/data/nucleus/base.rb +6 -0
  23. data/lib/wcc/data/nucleus/campus.rb +47 -0
  24. data/lib/wcc/data/nucleus/client_app_token.rb +30 -0
  25. data/lib/wcc/data/nucleus/contact.rb +33 -0
  26. data/lib/wcc/data/nucleus/gender.rb +26 -0
  27. data/lib/wcc/data/nucleus/group.rb +18 -0
  28. data/lib/wcc/data/nucleus/marital_status.rb +41 -0
  29. data/lib/wcc/data/nucleus/user.rb +49 -0
  30. data/lib/wcc/data/rack_client_app_token_auth.rb +77 -0
  31. data/lib/wcc/data/response.rb +29 -0
  32. data/lib/wcc/data/rest_endpoint.rb +33 -0
  33. data/lib/wcc/data/service.rb +55 -0
  34. data/lib/wcc/data/version.rb +5 -0
  35. data/spec/spec_helper.rb +22 -0
  36. data/spec/support/inheritable_class_attribute_examples.rb +16 -0
  37. data/spec/wcc/data/config_spec.rb +113 -0
  38. data/spec/wcc/data/enumerated_type_spec.rb +176 -0
  39. data/spec/wcc/data/faraday_client_app_token_auth_spec.rb +224 -0
  40. data/spec/wcc/data/mapper/attributes_spec.rb +94 -0
  41. data/spec/wcc/data/mapper/json_response_spec.rb +50 -0
  42. data/spec/wcc/data/mapper/rest_configuration_spec.rb +43 -0
  43. data/spec/wcc/data/mapper/rest_query_spec.rb +50 -0
  44. data/spec/wcc/data/model_spec.rb +33 -0
  45. data/spec/wcc/data/nucleus/campus_spec.rb +29 -0
  46. data/spec/wcc/data/rack_client_app_token_auth_spec.rb +219 -0
  47. data/spec/wcc/data/response_spec.rb +57 -0
  48. data/spec/wcc/data/rest_endpoint_spec.rb +71 -0
  49. data/spec/wcc/data/service_spec.rb +128 -0
  50. data/spec/wcc/data_spec.rb +25 -0
  51. data/wcc-data.gemspec +28 -0
  52. metadata +194 -0
@@ -0,0 +1,28 @@
1
+ module WCC::Data::Mapper
2
+
3
+ module RESTQuery
4
+
5
+ def find(id)
6
+ ensure_endpoint_defined
7
+ new_from_response(endpoint.show(id))
8
+ end
9
+
10
+ def list(params={})
11
+ ensure_endpoint_defined
12
+ new_from_response(endpoint.index(params: params))
13
+ end
14
+
15
+ def create(attributes={})
16
+ ensure_endpoint_defined
17
+ new_from_response(endpoint.create(attributes))
18
+ end
19
+
20
+ private
21
+
22
+ def ensure_endpoint_defined
23
+ raise EndpointUndefined unless defined?(endpoint) && endpoint
24
+ end
25
+
26
+ end
27
+
28
+ end
@@ -0,0 +1,11 @@
1
+ module WCC::Data
2
+
3
+ class Model
4
+ include Mapper::Attributes
5
+ extend Mapper::JSONResponse
6
+ extend Mapper::RESTConfiguration
7
+ extend Mapper::RESTQuery
8
+ end
9
+
10
+ end
11
+
@@ -0,0 +1,15 @@
1
+ module WCC::Data
2
+ module Nucleus
3
+ end
4
+ end
5
+
6
+ require_relative 'nucleus/base'
7
+
8
+ require_relative 'nucleus/address'
9
+ require_relative 'nucleus/campus'
10
+ require_relative 'nucleus/client_app_token'
11
+ require_relative 'nucleus/contact'
12
+ require_relative 'nucleus/gender'
13
+ require_relative 'nucleus/group'
14
+ require_relative 'nucleus/marital_status'
15
+ require_relative 'nucleus/user'
@@ -0,0 +1,17 @@
1
+ module WCC::Data::Nucleus
2
+
3
+ class Address < Base
4
+ set_endpoint :nucleus, "api/v1/users/"
5
+
6
+ attribute :user_id
7
+ attribute :street1, writer: true
8
+ attribute :street2, writer: true
9
+ attribute :city, writer: true
10
+ attribute :state, writer: true
11
+ attribute :zip, writer: true
12
+ attribute :latitude, writer: true
13
+ attribute :longitude, writer: true
14
+ end
15
+
16
+ end
17
+
@@ -0,0 +1,6 @@
1
+ module WCC::Data::Nucleus
2
+
3
+ class Base < WCC::Data::Model
4
+ end
5
+
6
+ end
@@ -0,0 +1,47 @@
1
+ module WCC::Data::Nucleus
2
+
3
+ class Campus < WCC::Data::EnumeratedType
4
+ attributes :id, :name, :key
5
+ attributes :street, :city, :state, :zip, :geo
6
+
7
+ def matches?(value)
8
+ [id, key].include?(value)
9
+ end
10
+
11
+ def self.db
12
+ [
13
+ {
14
+ id: 1,
15
+ name: 'Dallas',
16
+ key: :dallas,
17
+ street: '7540 LBJ Freeway',
18
+ city: 'Dallas',
19
+ state: 'TX',
20
+ zip: '75251',
21
+ geo: [32.922923, -96.7781638],
22
+ },
23
+ {
24
+ id: 2,
25
+ name: 'Fort Worth',
26
+ key: :ft_worth,
27
+ street: '3345 Winthrop Avenue',
28
+ city: 'Fort Worth',
29
+ state: 'TX',
30
+ zip: '76116',
31
+ geo: [32.7280064, -97.4146727],
32
+ },
33
+ {
34
+ id: 3,
35
+ name: 'Plano',
36
+ key: :plano,
37
+ street: '6400 K Avenue',
38
+ city: 'Plano',
39
+ state: 'TX',
40
+ zip: '75074',
41
+ geo: [33.060823, -96.688902],
42
+ },
43
+ ]
44
+ end
45
+ end
46
+
47
+ end
@@ -0,0 +1,30 @@
1
+ module WCC::Data::Nucleus
2
+
3
+ class ClientAppToken < Base
4
+ set_endpoint :nucleus, "api/v1/client_app_tokens/"
5
+
6
+ attribute :token
7
+ attribute :expires_at
8
+ attribute :expires_in
9
+ attribute :created_at
10
+ attribute :host_app
11
+ attribute :requesting_app
12
+
13
+ def host_app
14
+ App.new self[:host_app]
15
+ end
16
+
17
+ def requesting_app
18
+ App.new self[:requesting_app]
19
+ end
20
+
21
+ class App
22
+ include WCC::Data::Mapper::Attributes
23
+ attribute :id
24
+ attribute :uid
25
+ attribute :name
26
+ end
27
+ end
28
+
29
+ end
30
+
@@ -0,0 +1,33 @@
1
+ module WCC::Data::Nucleus
2
+
3
+ class Contact < Base
4
+ set_endpoint :nucleus, "api/v1/users/"
5
+
6
+ attribute :user_id
7
+ attribute :first_name, writer: true
8
+ attribute :last_name, writer: true
9
+ attribute :email, writer: true
10
+ attribute :phone, writer: true
11
+ attribute :birthday, writer: true
12
+ attribute :marital_status_id, writer: true
13
+ attribute :gender_id, writer: true
14
+
15
+ def marital_status
16
+ MaritalStatus[marital_status_id]
17
+ end
18
+
19
+ def marital_status=(marital_status)
20
+ self.marital_status_id = marital_status.id
21
+ end
22
+
23
+ def gender
24
+ Gender[gender_id]
25
+ end
26
+
27
+ def gender=(gender)
28
+ self.gender_id = gender.id
29
+ end
30
+ end
31
+
32
+ end
33
+
@@ -0,0 +1,26 @@
1
+ module WCC::Data::Nucleus
2
+
3
+ class Gender < WCC::Data::EnumeratedType
4
+ attributes :id, :name, :key
5
+
6
+ def matches?(value)
7
+ [id, key].include?(value)
8
+ end
9
+
10
+ def self.db
11
+ [
12
+ {
13
+ id: 1,
14
+ name: 'Male',
15
+ key: :male,
16
+ },
17
+ {
18
+ id: 2,
19
+ name: 'Female',
20
+ key: :female,
21
+ },
22
+ ]
23
+ end
24
+ end
25
+
26
+ end
@@ -0,0 +1,18 @@
1
+ module WCC::Data::Nucleus
2
+
3
+ class Group < Base
4
+ set_endpoint :nucleus, "api/v1/groups/"
5
+
6
+ attribute :id
7
+ attribute :name
8
+ attribute :member_count
9
+ attribute :created_at
10
+ attribute :updated_at
11
+
12
+ def users
13
+ User.list(group_id: id)
14
+ end
15
+ end
16
+
17
+ end
18
+
@@ -0,0 +1,41 @@
1
+ module WCC::Data::Nucleus
2
+
3
+ class MaritalStatus < WCC::Data::EnumeratedType
4
+ attributes :id, :name, :key
5
+
6
+ def matches?(value)
7
+ [id, key].include?(value)
8
+ end
9
+
10
+ def self.db
11
+ [
12
+ {
13
+ id: 1,
14
+ name: 'Single',
15
+ key: :single,
16
+ },
17
+ {
18
+ id: 2,
19
+ name: 'Married',
20
+ key: :married,
21
+ },
22
+ {
23
+ id: 3,
24
+ name: 'Widowed',
25
+ key: :widowed,
26
+ },
27
+ {
28
+ id: 4,
29
+ name: 'Divorced',
30
+ key: :divorced,
31
+ },
32
+ {
33
+ id: 5,
34
+ name: 'Separated',
35
+ key: :separated,
36
+ },
37
+ ]
38
+ end
39
+ end
40
+
41
+ end
@@ -0,0 +1,49 @@
1
+ module WCC::Data::Nucleus
2
+
3
+ class User < Base
4
+ set_endpoint :nucleus, "api/v1/users/"
5
+
6
+ attribute :id
7
+ attribute :first_name
8
+ attribute :last_name
9
+ attribute :email
10
+ attribute :access_level_id
11
+ attribute :arena_id, writer: true
12
+ attribute :created_at
13
+ attribute :updated_at
14
+ attribute :user_reviewed_at, writer: true
15
+ attribute :contact
16
+ attribute :address
17
+
18
+ SAVE_ATTRS = %i[arena_id user_reviewed_at]
19
+
20
+ def contact
21
+ @contact ||= Contact.new self[:contact].merge("user_id" => id)
22
+ end
23
+
24
+ def address
25
+ @address ||= Address.new self[:address].merge("user_id" => id)
26
+ end
27
+
28
+ def update_attributes(attrs={})
29
+ self.class.endpoint.update(id, user: attrs)
30
+ end
31
+
32
+ def save
33
+ update_attributes saveable_attributes
34
+ end
35
+
36
+ def saveable_attributes
37
+ attributes
38
+ .select { |key, _| SAVE_ATTRS.include?(key.to_sym) }
39
+ .merge(contact: contact.attributes)
40
+ .merge(address: address.attributes)
41
+ end
42
+
43
+ def self.search(string, options={})
44
+ list(options.merge(search: string))
45
+ end
46
+ end
47
+
48
+ end
49
+
@@ -0,0 +1,77 @@
1
+ module WCC::Data
2
+ class RackClientAppTokenAuth
3
+ class RedisCache
4
+ DEFAULT_CACHE_KEY = "org.watermark.wcc-api.client-app-token-cache-store"
5
+ DEFAULT_CACHE_LENGTH = 600
6
+
7
+ attr_reader :connection, :cache_key, :cache_length
8
+
9
+ def initialize(connection, cache_key: DEFAULT_CACHE_KEY, cache_length: DEFAULT_CACHE_LENGTH)
10
+ @connection = connection
11
+ @cache_key = cache_key
12
+ @cache_length = cache_length
13
+ end
14
+
15
+ def <<(token)
16
+ connection.call do |r|
17
+ r.set join_key(token), "1"
18
+ r.expire join_key(token), cache_length
19
+ end
20
+ end
21
+
22
+ def find(token)
23
+ connection.call do |r|
24
+ r.get join_key(token)
25
+ end
26
+ end
27
+
28
+ private
29
+
30
+ def join_key(suffix)
31
+ [cache_key, suffix].join(".")
32
+ end
33
+ end
34
+
35
+ attr_reader :app, :cache, :lookup_token
36
+
37
+ def initialize(app, cache: default_cache, lookup_token: method(:default_lookup_token))
38
+ @app = app
39
+ @cache = cache
40
+ @lookup_token = lookup_token
41
+ end
42
+
43
+ def find(token)
44
+ cached = cache.find(token)
45
+ return cached if cached
46
+
47
+ val = lookup_token.(token)
48
+
49
+ cache << token if val
50
+
51
+ val
52
+ end
53
+
54
+ def call(env)
55
+ _, token_string = env["HTTP_AUTHORIZATION"].split(/\s+/)
56
+ if find(token_string)
57
+ app.call(env)
58
+ else
59
+ [403, {}, '{"error":"Invalid Bearer Token"}']
60
+ end
61
+ end
62
+
63
+ private
64
+
65
+ def default_cache
66
+ RedisCache.new(Sidekiq.method(:redis))
67
+ end
68
+
69
+ def default_lookup_token(token)
70
+ WCC::Data::Nucleus::ClientAppToken.find(token)
71
+ rescue WCC::Data::Mapper::InvalidResponse, WCC::Data::Mapper::RecordNotFound
72
+ nil
73
+ end
74
+
75
+ end
76
+
77
+ end
@@ -0,0 +1,29 @@
1
+ require 'json'
2
+
3
+ module WCC::Data
4
+ class Response
5
+ attr_reader :raw
6
+
7
+ def initialize(raw)
8
+ @raw = raw
9
+ end
10
+
11
+ def json
12
+ JSON.parse(body)
13
+ rescue JSON::ParserError
14
+ end
15
+
16
+ def method_missing(method, *args, &block)
17
+ if raw.respond_to?(method)
18
+ raw.public_send(method, *args, &block)
19
+ else
20
+ super
21
+ end
22
+ end
23
+
24
+ def respond_to?(method)
25
+ super || raw.respond_to?(method)
26
+ end
27
+
28
+ end
29
+ end