web47core 0.0.9 → 0.0.10

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: 623ae80309063bdc6c27dee1668a86ae4473da7db27a6ffedb9bd75df3b83d40
4
- data.tar.gz: e39e28438fb5247ddb2cc65c9dd3b5c8edb8a98d9079921b3dc07d511b587ecb
3
+ metadata.gz: 97cb8fc1a923a3c6a911a319404529ef67ad9de4d1f20d6c90b088f99d8e366a
4
+ data.tar.gz: 53ce4e9da8a4279b4bc4eb3ffb7a0f58b9ec1844c6f1f42adeed9d3e572f3f7e
5
5
  SHA512:
6
- metadata.gz: db0cd4d93d34398cf6e3a4739016db9fd63337e048917403ea9ec624ee5f516ecdb8a9ac278925f8f329dde34c3a42af16b856530ae976c5cc9534eca0999143
7
- data.tar.gz: b5304422a552e6ec81a9e188000533a8a4652e66d3e6e8096b81abaf45d5e4646cc5ed5b7591265c5639f56225e977ba26cb68351eda9e1c20743d70b81b3580
6
+ metadata.gz: e3598aefea3e3b1411e4e4c60c1096129ba90fc5d33ae2c0907762d223ce234f3a4c56e50d28b2dc218a82544a51e9003bc20e0bf4f68bff70d0e767667887ad
7
+ data.tar.gz: 773f67eac21317c9da0c286c1071383f864b42f4a1d36dcef624bf3968dedf40d96452f9a3eb252057fb805dd6ce66c4302746e72838a4fcd856d30c23e95563
@@ -1,10 +1,11 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- web47core (0.0.9)
4
+ web47core (0.0.10)
5
5
  activesupport (~> 5.0)
6
6
  aws-sdk-ec2 (> 1.140, <= 1.160)
7
7
  delayed_job_mongoid (~> 2.3)
8
+ email_format
8
9
  haml
9
10
  jwt
10
11
  liquid
@@ -13,6 +14,8 @@ PATH
13
14
  redis (~> 4.1)
14
15
  redis-rails (> 5, < 6)
15
16
  rest-client (>= 0, <= 2.1.0)
17
+ twilio-ruby (>= 3.0, <= 4.13)
18
+ tzinfo
16
19
 
17
20
  GEM
18
21
  remote: https://rubygems.org/
@@ -63,7 +66,7 @@ GEM
63
66
  ansi (1.5.0)
64
67
  arel (9.0.0)
65
68
  aws-eventstream (1.0.3)
66
- aws-partitions (1.288.0)
69
+ aws-partitions (1.289.0)
67
70
  aws-sdk-core (3.92.0)
68
71
  aws-eventstream (~> 1.0, >= 1.0.2)
69
72
  aws-partitions (~> 1, >= 1.239.0)
@@ -99,6 +102,10 @@ GEM
99
102
  docile (1.3.2)
100
103
  domain_name (0.5.20190701)
101
104
  unf (>= 0.0.5, < 1.0.0)
105
+ email_format (1.0.0)
106
+ activemodel
107
+ email_regex
108
+ email_regex (0.0.1)
102
109
  erubi (1.9.0)
103
110
  factory_bot (5.1.1)
104
111
  activesupport (>= 4.2.0)
@@ -119,7 +126,7 @@ GEM
119
126
  concurrent-ruby (~> 1.0)
120
127
  jmespath (1.4.0)
121
128
  json (2.3.0)
122
- jwt (2.2.1)
129
+ jwt (1.5.6)
123
130
  liquid (4.0.3)
124
131
  listen (3.2.1)
125
132
  rb-fsevent (~> 0.10, >= 0.10.3)
@@ -167,6 +174,7 @@ GEM
167
174
  mongoid-compatibility (0.5.1)
168
175
  activesupport
169
176
  mongoid (>= 2.0)
177
+ multi_json (1.14.1)
170
178
  netrc (0.11.0)
171
179
  nio4r (2.5.2)
172
180
  nokogiri (1.10.9)
@@ -252,6 +260,10 @@ GEM
252
260
  thor (1.0.1)
253
261
  thread_safe (0.3.6)
254
262
  tilt (2.0.10)
263
+ twilio-ruby (4.13.0)
264
+ builder (>= 2.1.2)
265
+ jwt (~> 1.0)
266
+ multi_json (>= 1.3.0)
255
267
  tzinfo (1.2.6)
256
268
  thread_safe (~> 0.1)
257
269
  unf (0.1.4)
@@ -284,7 +296,7 @@ DEPENDENCIES
284
296
  minitest-reporters
285
297
  mocha
286
298
  shoulda (= 3.6.0)
287
- shoulda-matchers (= 3.1.2)
299
+ shoulda-matchers
288
300
  simplecov (= 0.16.1)
289
301
  test-unit
290
302
  vcr
data/README.md CHANGED
@@ -1,6 +1,11 @@
1
1
  # web47core
2
2
  Core components used commonly among all web apps for both App47 and RedMonocle
3
3
 
4
+ ## We don't need no sticking badges
5
+
6
+ * [![Codacy Badge](https://api.codacy.com/project/badge/Grade/acc591f31c214849959f71e210e7edbd)](https://www.codacy.com?utm_source=github.com&amp;utm_medium=referral&amp;utm_content=App47/web47core&amp;utm_campaign=Badge_Grade)
7
+ * [![Codacy Badge](https://api.codacy.com/project/badge/Coverage/acc591f31c214849959f71e210e7edbd)](https://www.codacy.com?utm_source=github.com&utm_medium=referral&utm_content=App47/web47core&utm_campaign=Badge_Coverage)
8
+
4
9
  ## Requirements
5
10
 
6
11
  * Ruby 2.4.1
@@ -27,62 +32,62 @@ bundle install --path vendor
27
32
  ```
28
33
  The `--path vendor` simply puts all gem files in a `vendor` directory.
29
34
 
30
- # Development
35
+ ## Development
31
36
 
32
37
  Your `RubyMine` environment should be setup now, however to verify all is well, please run the test suite
33
38
  ```
34
39
  bundle exec rake test
35
40
  ```
36
41
 
37
- # Deployment
42
+ ## Deployment
38
43
  The `web47core` project is a gem that will be deployed via [Ruby Gems](https://rubygems.org). When an update is ready, the following steps should be followed
39
44
 
40
- 1. Build the gem `gem build web47core.gemspec`
41
- 1. Push the new gem to [Ruby Gems](https://rubygems.org) `gem push web47core-<<version>>.gem`
42
- 1. There may be a delay when using the gem file
45
+ 1. Build the gem `gem build web47core.gemspec`
46
+ 2. Push the new gem to [Ruby Gems](https://rubygems.org) `gem push web47core-version.gem`
47
+ 3. There may be a delay when using the gem file
43
48
 
44
- # Usage
45
- ## Importing the gem
49
+ ## Usage
50
+ ### Importing the gem
46
51
  To use the `app47core` gem in a project, first add the gem to your Gemfile in one of two ways
47
52
 
48
53
  Using the gem from [Ruby Gems](https://rubygems.org)
49
- ```
54
+ ```rbenv-gemsets
50
55
  gem 'web47core'
51
56
  ```
52
57
 
53
58
  If you need the gem immediately or need to pull from development branch, you can use the git repo
54
- ```
59
+ ```rbenv-gemsets
55
60
  gem 'web47core', git: 'git@github.com:App47/web47core.git', branch: :master
56
61
  ```
57
62
  or from the develop branch
58
- ```
63
+ ```rbenv-gemsets
59
64
  gem 'web47core', git: 'git@github.com:App47/web47core.git', branch: :develop
60
65
  ```
61
66
 
62
67
  _Please do not ship to production code using the git repo, as the production servers will not have keys to pull from the web47core repo_
63
68
 
64
- ## Remove the following files
65
- 1. `StandardModel` - Includes the common set of includes, Mongoid, Auditable, AutoClearCache, etc.
66
- 1. `CdnUrl` - Provide CDN URLs of your classes URLs when cdn_url is configured in system configuration
67
- 1. `AutoClearCache` - Clears your objects cache out of Rails.cache using the object's id
68
- 1. `Formable` - Consolidated into StandardModel, was used to provide common form operations for mongoid documents
69
- 1. `EmailNotification`
70
- 1. `EmailTemplate`
71
- 1. `Notification`
72
- 1. `NotificationTemplate`
73
- 1. `SlackNotification`
74
- 1. `SmsNotification`
75
- 1. `Template`
76
-
77
- ### Models
78
- #### Concerns
79
- 1. `StandardModel` - Includes the common set of includes, Mongoid, etc.
80
- 1. `CoreSystemConfiguration` - Base system configuration to be included in the app's SystemConfiguration Object
81
- 1. `CoreAccount` - Base account object that is related to notifications and the ilk.
82
- #### System Configuration
69
+ ### Remove the following files
70
+ 1. `StandardModel` - Includes the common set of includes, Mongoid, Auditable, AutoClearCache, etc.
71
+ 2. `CdnUrl` - Provide CDN URLs of your classes URLs when cdn_url is configured in system configuration
72
+ 3. `AutoClearCache` - Clears your objects cache out of Rails.cache using the object's id
73
+ 4. `Formable` - Consolidated into StandardModel, was used to provide common form operations for mongoid documents
74
+ 5. `EmailNotification`
75
+ 6. `EmailTemplate`
76
+ 7. `Notification`
77
+ 8. `NotificationTemplate`
78
+ 9. `SlackNotification`
79
+ 10. `SmsNotification`
80
+ 11. `Template`
81
+
82
+ #### Models
83
+ ##### Concerns
84
+ 1. `StandardModel` - Includes the common set of includes, Mongoid, etc.
85
+ 2. `CoreSystemConfiguration` - Base system configuration to be included in the app's SystemConfiguration Object
86
+ 3. `CoreAccount` - Base account object that is related to notifications and the ilk.
87
+ ##### System Configuration
83
88
  Define a `SystemConfiguration` class in your project and import the core concern.
84
89
 
85
- ```
90
+ ```ruby
86
91
  class SystemConfiguration
87
92
  include StandardModel
88
93
  include CoreSystemConfiguration
@@ -91,10 +96,10 @@ class SystemConfiguration
91
96
  field :google_sso_client_id, type: String
92
97
  end
93
98
  ```
94
- #### Account
99
+ ##### Account
95
100
  Define a `Account` class in your project and import the core concern.
96
101
 
97
- ```
102
+ ```ruby
98
103
  class Account
99
104
  include StandardModel
100
105
  include CoreAccount
@@ -103,4 +108,3 @@ class Account
103
108
  has_many :users
104
109
  end
105
110
  ```
106
-
@@ -0,0 +1,11 @@
1
+ en:
2
+ time:
3
+ formats:
4
+ long: '%Y-%m-%d %H:%M:%ss (%Z)'
5
+ medium: '%Y-%m-%d %H:%M (%Z)'
6
+ short: '%m/%d/%Y'
7
+ date:
8
+ formats:
9
+ long: '%B %d, %Y'
10
+ medium: '%b %d, %Y'
11
+ short: '%m/%d/%Y'
@@ -63,7 +63,7 @@ module App47Logger
63
63
 
64
64
  max_frame = -1 if ENV['RACK_ENV'].eql?('test')
65
65
  log_message(level, exception.message)
66
- exception.backtrace[0..max_frame].each { |frame| log_message(level, frame) } unless exception.backtrace.blank?
66
+ exception.backtrace[0..max_frame].each { |frame| log_message(level, frame) } if exception.backtrace.present?
67
67
  end
68
68
 
69
69
  #
@@ -117,6 +117,10 @@ module CoreSystemConfiguration
117
117
  def respond_to?(method_name, _include_private = false)
118
118
  SystemConfiguration.fields.include?(method_name)
119
119
  end
120
+
121
+ def respond_to_missing?(method_name, _include_private = false)
122
+ SystemConfiguration.fields.include?(method_name)
123
+ end
120
124
  # rubocop:enable Style/MethodMissingSuper
121
125
  end
122
126
 
@@ -208,7 +212,7 @@ module CoreSystemConfiguration
208
212
  config = SystemConfiguration.configuration
209
213
  path = if config.zendesk_configured? && user.present?
210
214
  time_now = Time.now.to_i
211
- jti = "#{time_now}/#{rand(36 ** 64).to_s(36)}"
215
+ jti = "#{time_now}/#{rand(36**64).to_s(36)}"
212
216
  payload = { jwt: JWT.encode({ iat: time_now, # Seconds since epoch, determine when this token is stale
213
217
  jti: jti, # Unique token identifier, helps prevent replay attacks
214
218
  name: user.name,
@@ -0,0 +1,84 @@
1
+ #
2
+ # Objects that emails can be sent too...
3
+ #
4
+ module EmailAble
5
+ extend ActiveSupport::Concern
6
+ include App47Logger
7
+
8
+ def self.included(base)
9
+ base.class_eval do
10
+ field :email, type: String
11
+ field :email_bounced_at, type: Time
12
+ field :email_bounce_reason, type: String
13
+ field :unconfirmed_email, type: String
14
+ field :email_enabled, type: Boolean, default: true
15
+ #
16
+ # Validations
17
+ #
18
+ validates :email, presence: true, email_format: { strict: true }
19
+ #
20
+ # Callbacks
21
+ #
22
+ before_validation :downcase_email
23
+ end
24
+ end
25
+
26
+ #
27
+ # Support legacy apps with old name
28
+ #
29
+ def email_bounce_date(date = nil)
30
+ self.email_bounced_at = date if date.present?
31
+ email_bounced_at
32
+ end
33
+
34
+ #
35
+ # Is this a valid email to send to?
36
+ #
37
+ def valid_email?
38
+ email_enabled? && !email_bounced?
39
+ end
40
+
41
+ #
42
+ # Has the email bounced?
43
+ #
44
+ def email_bounced?
45
+ email_bounced_at.present?
46
+ end
47
+
48
+ #
49
+ # Set the email to a bounced status with the given reason
50
+ #
51
+ def bounced(reason)
52
+ set email_bounced_at: Time.now.utc, email_bounce_reason: reason
53
+ end
54
+
55
+ #
56
+ # Reset the bounced email
57
+ #
58
+ def reset_bounce_status
59
+ return unless SystemConfiguration.mailgun_configured? && email_bounced?
60
+
61
+ reset_url = "https://api.mailgun.net/v3/#{SystemConfiguration.smtp_domain}/bounces/#{CGI.escape(email)}"
62
+ RestClient.delete(reset_url, user: 'api', password: SystemConfiguration.mailgun_api_key)
63
+ rescue RestClient::Exception => error
64
+ log_error "Unable to reset email bounce status: #{inspect}", error
65
+ ensure
66
+ set email_bounced_at: nil, email_bounce_reason: nil
67
+ end
68
+
69
+ #
70
+ # Return the gravatar URL based on email address
71
+ #
72
+ def gravatar_url(size = '32', default = 'mm')
73
+ "https://www.gravatar.com/avatar/#{Digest::MD5.hexdigest(email)}?s=#{size}&d=#{default}"
74
+ end
75
+
76
+ private
77
+
78
+ #
79
+ # Make sure emails are always downcased
80
+ #
81
+ def downcase_email
82
+ self.email = email.strip.downcase if email.present?
83
+ end
84
+ end
@@ -0,0 +1,100 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # Public: Add search and sort text to an object
5
+ #
6
+ module SearchAble
7
+ extend ActiveSupport::Concern
8
+
9
+ def self.included(base)
10
+ base.class_eval do
11
+ #
12
+ # Fields
13
+ #
14
+ field :search_text, type: String
15
+ field :sort_text, type: String
16
+ #
17
+ # Call backs
18
+ #
19
+ before_validation :update_search_and_sort_text
20
+ end
21
+ end
22
+
23
+ #
24
+ # Public: Add to class methods a way to search for records with matching
25
+ # search text.
26
+ #
27
+ # Examples
28
+ #
29
+ # Model.matching_search_text('some text')
30
+ # # => <Mongoid::critera>
31
+ #
32
+ module ClassMethods
33
+ def matching_search_text(search_text = nil)
34
+ (search_text.blank? ? all : where(search_text: /#{search_text.downcase}/)).order(sort_order)
35
+ end
36
+
37
+ def sort_order
38
+ new.sort_fields.collect { |field| [field, 1] }
39
+ end
40
+ end
41
+
42
+ #
43
+ # Internal: Update the search and sort text
44
+ #
45
+ # Call before validation to update, changes are persisted with the object.
46
+ #
47
+ def update_search_and_sort_text
48
+ return if destroyed?
49
+
50
+ update_text(search_fields, :search_text)
51
+ update_text(sort_fields, :sort_text)
52
+ end
53
+
54
+ #
55
+ # Internal: Update the search text
56
+ #
57
+ # Examples
58
+ #
59
+ # update_search_text
60
+ #
61
+ def update_text(fields, field_to_update)
62
+ items = fields.reject { |field| send(field.to_sym).blank? }.collect do |field|
63
+ value = send(field.to_sym)
64
+ if value.is_a? String
65
+ value.downcase
66
+ elsif value.is_a? Array
67
+ value.empty? ? nil : value.join(' ').downcase
68
+ end
69
+ end
70
+ send "#{field_to_update}=", items.compact.join(' ')
71
+ end
72
+
73
+ #
74
+ # Internal: Which fields to add to search text
75
+ #
76
+ # Examples
77
+ #
78
+ # search_fields
79
+ # # => ['name', 'email', 'code']
80
+ #
81
+ # Return which fields should be added to search
82
+ #
83
+ def search_fields
84
+ %w[name]
85
+ end
86
+
87
+ #
88
+ # Internal: Which fields to add to sort on
89
+ #
90
+ # Examples
91
+ #
92
+ # sort_fields
93
+ # # => ['name', 'email']
94
+ #
95
+ # Return which fields should be added to sort
96
+ #
97
+ def sort_fields
98
+ search_fields
99
+ end
100
+ end
@@ -101,7 +101,7 @@ module StandardModel
101
101
  super(remove_blank_secure_fields(params))
102
102
  end
103
103
 
104
- alias :update_attributes :update
104
+ alias update_attributes update
105
105
 
106
106
  #
107
107
  # Remove updates for secure fields that come across as blank to start with and get removed on update
@@ -110,7 +110,7 @@ module StandardModel
110
110
  super(remove_blank_secure_fields(params))
111
111
  end
112
112
 
113
- alias :update_attributes! :update!
113
+ alias update_attributes! update!
114
114
 
115
115
  #
116
116
  # List of secure fields, to add fields in concrete class, simply override this method