propel_authentication 0.1.1
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 +7 -0
- data/LICENSE +21 -0
- data/README.md +290 -0
- data/Rakefile +12 -0
- data/lib/generators/propel_auth/install_generator.rb +486 -0
- data/lib/generators/propel_auth/pack_generator.rb +277 -0
- data/lib/generators/propel_auth/templates/agency.rb +7 -0
- data/lib/generators/propel_auth/templates/agent.rb +7 -0
- data/lib/generators/propel_auth/templates/auth/base_passwords_controller.rb.tt +99 -0
- data/lib/generators/propel_auth/templates/auth/base_tokens_controller.rb.tt +90 -0
- data/lib/generators/propel_auth/templates/auth/passwords_controller.rb.tt +126 -0
- data/lib/generators/propel_auth/templates/auth_mailer.rb +180 -0
- data/lib/generators/propel_auth/templates/authenticatable.rb +38 -0
- data/lib/generators/propel_auth/templates/concerns/confirmable.rb +145 -0
- data/lib/generators/propel_auth/templates/concerns/lockable.rb +123 -0
- data/lib/generators/propel_auth/templates/concerns/propel_authentication.rb +44 -0
- data/lib/generators/propel_auth/templates/concerns/rack_session_disable.rb +19 -0
- data/lib/generators/propel_auth/templates/concerns/recoverable.rb +124 -0
- data/lib/generators/propel_auth/templates/config/environments/development_email.rb +43 -0
- data/lib/generators/propel_auth/templates/db/migrate/create_agencies.rb +20 -0
- data/lib/generators/propel_auth/templates/db/migrate/create_agents.rb +11 -0
- data/lib/generators/propel_auth/templates/db/migrate/create_invitations.rb +28 -0
- data/lib/generators/propel_auth/templates/db/migrate/create_organizations.rb +18 -0
- data/lib/generators/propel_auth/templates/db/migrate/create_users.rb +43 -0
- data/lib/generators/propel_auth/templates/db/seeds.rb +29 -0
- data/lib/generators/propel_auth/templates/invitation.rb +133 -0
- data/lib/generators/propel_auth/templates/lib/propel_auth.rb +84 -0
- data/lib/generators/propel_auth/templates/organization.rb +7 -0
- data/lib/generators/propel_auth/templates/propel_auth.rb +132 -0
- data/lib/generators/propel_auth/templates/services/auth_notification_service.rb +89 -0
- data/lib/generators/propel_auth/templates/test/concerns/confirmable_test.rb.tt +247 -0
- data/lib/generators/propel_auth/templates/test/concerns/lockable_test.rb.tt +282 -0
- data/lib/generators/propel_auth/templates/test/concerns/propel_authentication_test.rb.tt +75 -0
- data/lib/generators/propel_auth/templates/test/concerns/recoverable_test.rb.tt +327 -0
- data/lib/generators/propel_auth/templates/test/controllers/auth/lockable_integration_test.rb.tt +196 -0
- data/lib/generators/propel_auth/templates/test/controllers/auth/password_reset_integration_test.rb.tt +471 -0
- data/lib/generators/propel_auth/templates/test/controllers/auth/tokens_controller_test.rb.tt +265 -0
- data/lib/generators/propel_auth/templates/test/mailers/auth_mailer_test.rb.tt +216 -0
- data/lib/generators/propel_auth/templates/test/mailers/previews/auth_mailer_preview.rb +161 -0
- data/lib/generators/propel_auth/templates/tokens_controller.rb.tt +96 -0
- data/lib/generators/propel_auth/templates/user.rb +21 -0
- data/lib/generators/propel_auth/templates/user_test.rb.tt +81 -0
- data/lib/generators/propel_auth/templates/views/auth_mailer/account_unlock.html.erb +213 -0
- data/lib/generators/propel_auth/templates/views/auth_mailer/account_unlock.text.erb +56 -0
- data/lib/generators/propel_auth/templates/views/auth_mailer/email_confirmation.html.erb +213 -0
- data/lib/generators/propel_auth/templates/views/auth_mailer/email_confirmation.text.erb +32 -0
- data/lib/generators/propel_auth/templates/views/auth_mailer/password_reset.html.erb +166 -0
- data/lib/generators/propel_auth/templates/views/auth_mailer/password_reset.text.erb +32 -0
- data/lib/generators/propel_auth/templates/views/auth_mailer/user_invitation.html.erb +194 -0
- data/lib/generators/propel_auth/templates/views/auth_mailer/user_invitation.text.erb +51 -0
- data/lib/generators/propel_auth/test/dummy/Dockerfile +72 -0
- data/lib/generators/propel_auth/test/dummy/Gemfile +63 -0
- data/lib/generators/propel_auth/test/dummy/Gemfile.lock +394 -0
- data/lib/generators/propel_auth/test/dummy/README.md +24 -0
- data/lib/generators/propel_auth/test/dummy/Rakefile +6 -0
- data/lib/generators/propel_auth/test/dummy/app/assets/stylesheets/application.css +10 -0
- data/lib/generators/propel_auth/test/dummy/app/controllers/application_controller.rb +4 -0
- data/lib/generators/propel_auth/test/dummy/app/helpers/application_helper.rb +2 -0
- data/lib/generators/propel_auth/test/dummy/app/jobs/application_job.rb +7 -0
- data/lib/generators/propel_auth/test/dummy/app/mailers/application_mailer.rb +4 -0
- data/lib/generators/propel_auth/test/dummy/app/models/application_record.rb +3 -0
- data/lib/generators/propel_auth/test/dummy/app/views/layouts/application.html.erb +27 -0
- data/lib/generators/propel_auth/test/dummy/app/views/layouts/mailer.html.erb +13 -0
- data/lib/generators/propel_auth/test/dummy/app/views/layouts/mailer.text.erb +1 -0
- data/lib/generators/propel_auth/test/dummy/app/views/pwa/manifest.json.erb +22 -0
- data/lib/generators/propel_auth/test/dummy/app/views/pwa/service-worker.js +26 -0
- data/lib/generators/propel_auth/test/dummy/bin/brakeman +7 -0
- data/lib/generators/propel_auth/test/dummy/bin/dev +2 -0
- data/lib/generators/propel_auth/test/dummy/bin/docker-entrypoint +14 -0
- data/lib/generators/propel_auth/test/dummy/bin/rails +4 -0
- data/lib/generators/propel_auth/test/dummy/bin/rake +4 -0
- data/lib/generators/propel_auth/test/dummy/bin/rubocop +8 -0
- data/lib/generators/propel_auth/test/dummy/bin/setup +34 -0
- data/lib/generators/propel_auth/test/dummy/bin/thrust +5 -0
- data/lib/generators/propel_auth/test/dummy/config/application.rb +42 -0
- data/lib/generators/propel_auth/test/dummy/config/boot.rb +4 -0
- data/lib/generators/propel_auth/test/dummy/config/cable.yml +10 -0
- data/lib/generators/propel_auth/test/dummy/config/credentials.yml.enc +1 -0
- data/lib/generators/propel_auth/test/dummy/config/database.yml +41 -0
- data/lib/generators/propel_auth/test/dummy/config/environment.rb +5 -0
- data/lib/generators/propel_auth/test/dummy/config/environments/development.rb +72 -0
- data/lib/generators/propel_auth/test/dummy/config/environments/production.rb +89 -0
- data/lib/generators/propel_auth/test/dummy/config/environments/test.rb +53 -0
- data/lib/generators/propel_auth/test/dummy/config/initializers/assets.rb +10 -0
- data/lib/generators/propel_auth/test/dummy/config/initializers/content_security_policy.rb +25 -0
- data/lib/generators/propel_auth/test/dummy/config/initializers/filter_parameter_logging.rb +8 -0
- data/lib/generators/propel_auth/test/dummy/config/initializers/inflections.rb +16 -0
- data/lib/generators/propel_auth/test/dummy/config/locales/en.yml +31 -0
- data/lib/generators/propel_auth/test/dummy/config/master.key +1 -0
- data/lib/generators/propel_auth/test/dummy/config/puma.rb +41 -0
- data/lib/generators/propel_auth/test/dummy/config/routes.rb +2 -0
- data/lib/generators/propel_auth/test/dummy/config/storage.yml +34 -0
- data/lib/generators/propel_auth/test/dummy/config.ru +6 -0
- data/lib/generators/propel_auth/test/dummy/db/schema.rb +14 -0
- data/lib/generators/propel_auth/test/generators/authentication/controllers/tokens_controller_test.rb +230 -0
- data/lib/generators/propel_auth/test/generators/authentication/install_generator_test.rb +490 -0
- data/lib/generators/propel_auth/test/generators/authentication/uninstall_generator_test.rb +408 -0
- data/lib/generators/propel_auth/test/integration/generator_integration_test.rb +158 -0
- data/lib/generators/propel_auth/test/integration/multi_version_generator_test.rb +125 -0
- data/lib/generators/propel_auth/unpack_generator.rb +345 -0
- data/lib/propel_auth.rb +3 -0
- metadata +195 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 1cd8cca14e91a3fc54848cd5a245510df52d76255b79185462477311677724b8
|
4
|
+
data.tar.gz: 30ad644249b3619934c8b81287feef6b92cad1707a4f3d2627b128cc0e76f0a6
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: eff271364092358d28c82b91a4d757ee92f962b1acb56ded0a74cb5c5707446d64c0e89f47f4698b2051813979c455c29ddb8e298c71cbdfb0eed88718b253ea
|
7
|
+
data.tar.gz: 985be8cf0e9c27361fb622caeb1e36ac39a99fe2d317828d812fb8add592eb79fdac86ea66c4b5b4caf5a64cba1662eea4ff9df2f95b2f4fdb883c332aeedb92
|
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2025 Propel Auth Generator
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,290 @@
|
|
1
|
+
# PropelAuth
|
2
|
+
|
3
|
+
A comprehensive Rails generator that creates a complete JWT-based authentication system with agencies, agents, tokens, password resets, account locking, and email confirmation.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
PropelAuth is designed as a **self-extracting generator gem**. You install it temporarily, run the generators to extract the code into your application, then remove the gem dependency.
|
8
|
+
|
9
|
+
### Step 1: Add to Gemfile as a Path Gem
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
# In your Gemfile
|
13
|
+
gem 'propel_auth', path: 'propel_auth'
|
14
|
+
```
|
15
|
+
|
16
|
+
### Step 2: Bundle Install
|
17
|
+
|
18
|
+
```bash
|
19
|
+
bundle install
|
20
|
+
```
|
21
|
+
|
22
|
+
### Step 3: Unpack the Generator (Optional)
|
23
|
+
|
24
|
+
If you want to customize the generator templates:
|
25
|
+
|
26
|
+
```bash
|
27
|
+
rails generate propel_auth:unpack
|
28
|
+
```
|
29
|
+
|
30
|
+
This extracts the generator into `lib/generators/propel_auth/` for customization.
|
31
|
+
|
32
|
+
### Step 4: Install PropelAuth
|
33
|
+
|
34
|
+
```bash
|
35
|
+
rails generate propel_auth:install
|
36
|
+
```
|
37
|
+
|
38
|
+
This installs the complete authentication system including models, controllers, services, and mailers.
|
39
|
+
|
40
|
+
### Step 5: Remove Gem Dependency (Optional)
|
41
|
+
|
42
|
+
After installation, you can remove the gem from your Gemfile. All functionality remains in your application.
|
43
|
+
|
44
|
+
## Usage
|
45
|
+
|
46
|
+
### Generated Authentication System
|
47
|
+
|
48
|
+
The generator creates a complete authentication system with:
|
49
|
+
|
50
|
+
- **User model** - Primary user accounts with authentication
|
51
|
+
- **Organization model** - Multi-tenant organization structure
|
52
|
+
- **Agency model** - Intermediate organization management
|
53
|
+
- **Agent model** - User accounts with JWT authentication
|
54
|
+
- **Invitation model** - User invitation system
|
55
|
+
- **Authentication controllers** - Login, logout, token management
|
56
|
+
- **Password controllers** - Password reset functionality
|
57
|
+
- **Email confirmation** - Account verification system
|
58
|
+
- **Account locking** - Security protection against brute force
|
59
|
+
- **Auth mailer** - Email notifications for auth events
|
60
|
+
- **Auth service** - Centralized authentication logic
|
61
|
+
|
62
|
+
### Authentication Flow
|
63
|
+
|
64
|
+
```ruby
|
65
|
+
# Login
|
66
|
+
POST /auth/tokens
|
67
|
+
{
|
68
|
+
"email": "user@example.com",
|
69
|
+
"password": "password"
|
70
|
+
}
|
71
|
+
|
72
|
+
# Response
|
73
|
+
{
|
74
|
+
"data": {
|
75
|
+
"user": { ... },
|
76
|
+
"organization": { ... },
|
77
|
+
"token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9..."
|
78
|
+
}
|
79
|
+
}
|
80
|
+
|
81
|
+
# Access protected resources
|
82
|
+
GET /api/v1/protected_resource
|
83
|
+
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...
|
84
|
+
```
|
85
|
+
|
86
|
+
### Authentication Concerns
|
87
|
+
|
88
|
+
PropelAuth generates several reusable concerns:
|
89
|
+
|
90
|
+
```ruby
|
91
|
+
# In your models
|
92
|
+
class User < ApplicationRecord
|
93
|
+
include Authenticatable # JWT token generation and validation
|
94
|
+
include Lockable # Account locking after failed attempts
|
95
|
+
include Recoverable # Password reset functionality
|
96
|
+
include Confirmable # Email confirmation
|
97
|
+
|
98
|
+
# Your model customizations here
|
99
|
+
end
|
100
|
+
|
101
|
+
# In your controllers
|
102
|
+
class ApplicationController < ActionController::API
|
103
|
+
include PropelAuthentication # Authentication helpers
|
104
|
+
include RackSessionDisable # Disable Rails sessions for API
|
105
|
+
end
|
106
|
+
```
|
107
|
+
|
108
|
+
### Password Reset Flow
|
109
|
+
|
110
|
+
```ruby
|
111
|
+
# Request password reset
|
112
|
+
POST /auth/passwords
|
113
|
+
{ "email": "user@example.com" }
|
114
|
+
|
115
|
+
# Reset password with token
|
116
|
+
PATCH /auth/passwords
|
117
|
+
{
|
118
|
+
"token": "reset_token_from_email",
|
119
|
+
"password": "new_password",
|
120
|
+
"password_confirmation": "new_password"
|
121
|
+
}
|
122
|
+
```
|
123
|
+
|
124
|
+
### Account Features
|
125
|
+
|
126
|
+
- **Email confirmation** - Verify email addresses before activation
|
127
|
+
- **Account locking** - Automatic lockout after failed attempts
|
128
|
+
- **Password expiration** - Configurable password aging
|
129
|
+
- **JWT tokens** - Secure stateless authentication
|
130
|
+
- **Multi-tenancy** - Organization-based structure with agencies
|
131
|
+
|
132
|
+
## Features
|
133
|
+
|
134
|
+
### Complete Authentication System
|
135
|
+
- **JWT-based authentication** - Stateless, scalable token system
|
136
|
+
- **Multi-tenant architecture** - User/Organization/Agency/Agent model hierarchy
|
137
|
+
- **Email verification** - Confirm email addresses before activation
|
138
|
+
- **Password security** - Reset, expiration, and strength requirements
|
139
|
+
- **Account protection** - Automatic locking and unlock mechanisms
|
140
|
+
- **Invitation system** - User invitation workflow
|
141
|
+
|
142
|
+
### Production-Ready Security
|
143
|
+
- **BCrypt password hashing** - Industry standard password protection
|
144
|
+
- **JWT token validation** - Secure token-based authentication
|
145
|
+
- **Rate limiting ready** - Designed for rate limiting integration
|
146
|
+
- **Email notifications** - Automated security and account emails
|
147
|
+
- **Configurable policies** - Adjust security settings per requirements
|
148
|
+
|
149
|
+
### Rails Integration
|
150
|
+
- **Standard Rails patterns** - Follows Rails conventions throughout
|
151
|
+
- **ActiveRecord models** - Standard model associations and validations
|
152
|
+
- **ActionMailer integration** - Built-in email functionality
|
153
|
+
- **Controller concerns** - Reusable authentication logic
|
154
|
+
- **Environment configuration** - Different settings per environment
|
155
|
+
|
156
|
+
## Self-Extracting Architecture
|
157
|
+
|
158
|
+
PropelAuth follows a self-extracting pattern that provides:
|
159
|
+
|
160
|
+
- **No runtime dependencies** - all code lives in your application
|
161
|
+
- **Full control** - modify any component after installation
|
162
|
+
- **No black boxes** - transparent, readable Rails code
|
163
|
+
- **Easy maintenance** - standard Rails patterns throughout
|
164
|
+
|
165
|
+
After installation, you can:
|
166
|
+
- Remove the gem from your Gemfile
|
167
|
+
- Customize all generated code
|
168
|
+
- Maintain and extend functionality independently
|
169
|
+
- Integrate with existing authentication systems
|
170
|
+
|
171
|
+
## Configuration
|
172
|
+
|
173
|
+
Configure PropelAuth in `config/initializers/propel_auth.rb`:
|
174
|
+
|
175
|
+
```ruby
|
176
|
+
PropelAuth.configure do |config|
|
177
|
+
# JWT Configuration
|
178
|
+
config.jwt_secret = Rails.application.credentials.secret_key_base
|
179
|
+
config.jwt_expiration = 24.hours # 2.hours in production
|
180
|
+
config.jwt_algorithm = 'HS256'
|
181
|
+
|
182
|
+
# Password requirements
|
183
|
+
config.password_length = 8..128
|
184
|
+
|
185
|
+
# Account lockout settings
|
186
|
+
config.max_failed_attempts = 10
|
187
|
+
config.lockout_duration = 30.minutes
|
188
|
+
|
189
|
+
# Password reset settings
|
190
|
+
config.password_reset_expiration = 15.minutes
|
191
|
+
config.password_reset_rate_limit = 1.minute
|
192
|
+
|
193
|
+
# Email settings
|
194
|
+
config.frontend_url = 'http://localhost:3000' # For email links
|
195
|
+
config.email_from_address = "noreply@#{Rails.application.class.module_parent.name.downcase}.com"
|
196
|
+
config.enable_email_notifications = true
|
197
|
+
end
|
198
|
+
```
|
199
|
+
|
200
|
+
## Generated Files
|
201
|
+
|
202
|
+
After installation, PropelAuth creates:
|
203
|
+
|
204
|
+
### Models
|
205
|
+
- `app/models/user.rb` - Primary user model
|
206
|
+
- `app/models/organization.rb` - Organization/tenant model
|
207
|
+
- `app/models/agency.rb` - Agency management model
|
208
|
+
- `app/models/agent.rb` - Agent user accounts
|
209
|
+
- `app/models/invitation.rb` - User invitation system
|
210
|
+
- `app/models/concerns/authenticatable.rb` - JWT authentication logic
|
211
|
+
- `app/models/concerns/confirmable.rb` - Email confirmation
|
212
|
+
- `app/models/concerns/lockable.rb` - Account locking
|
213
|
+
- `app/models/concerns/recoverable.rb` - Password recovery
|
214
|
+
|
215
|
+
### Controllers
|
216
|
+
- `app/controllers/auth/tokens_controller.rb` - Login/logout
|
217
|
+
- `app/controllers/auth/passwords_controller.rb` - Password reset
|
218
|
+
- `app/controllers/concerns/propel_authentication.rb` - Authentication helpers
|
219
|
+
- `app/controllers/concerns/rack_session_disable.rb` - Session management
|
220
|
+
|
221
|
+
### Services
|
222
|
+
- `app/services/auth_notification_service.rb` - Email notifications
|
223
|
+
|
224
|
+
### Mailers
|
225
|
+
- `app/mailers/auth_mailer.rb` - Authentication emails
|
226
|
+
- `app/views/auth_mailer/` - Email templates for confirmations, resets, lockouts
|
227
|
+
|
228
|
+
### Migrations
|
229
|
+
- User, Organization, Agency, Agent, and Invitation table creation
|
230
|
+
- Authentication-related fields and indexes
|
231
|
+
|
232
|
+
### Tests
|
233
|
+
- Complete test coverage for all authentication functionality
|
234
|
+
- Model tests for validations and business logic
|
235
|
+
- Controller tests for authentication flows
|
236
|
+
- Integration tests for complete user journeys
|
237
|
+
|
238
|
+
### Configuration
|
239
|
+
- `config/initializers/propel_auth.rb` - PropelAuth configuration
|
240
|
+
- `lib/propel_auth.rb` - Runtime library (extracted from gem)
|
241
|
+
|
242
|
+
## API Versioning Support
|
243
|
+
|
244
|
+
PropelAuth supports API versioning for authentication routes:
|
245
|
+
|
246
|
+
```bash
|
247
|
+
# Install with custom API version
|
248
|
+
rails generate propel_auth:install --api-version=v2
|
249
|
+
|
250
|
+
# Creates routes like: /api/v2/auth/tokens
|
251
|
+
```
|
252
|
+
|
253
|
+
## Dependencies
|
254
|
+
|
255
|
+
- **Rails 7.0+** - Modern Rails framework support
|
256
|
+
- **BCrypt ~> 3.1.20** - Secure password hashing
|
257
|
+
- **JWT ~> 2.7** - JSON Web Token authentication
|
258
|
+
|
259
|
+
## Development
|
260
|
+
|
261
|
+
```bash
|
262
|
+
# Run generator tests
|
263
|
+
cd propel_auth
|
264
|
+
bundle exec rake test
|
265
|
+
|
266
|
+
# Test authentication flows
|
267
|
+
bundle exec ruby -Ilib:test test/generators/authentication/install_generator_test.rb
|
268
|
+
```
|
269
|
+
|
270
|
+
## Integration with PropelApi
|
271
|
+
|
272
|
+
PropelAuth integrates seamlessly with PropelApi for complete API authentication:
|
273
|
+
|
274
|
+
```ruby
|
275
|
+
# Generated API controllers automatically include authentication
|
276
|
+
class Api::V1::ApiController < ApplicationController
|
277
|
+
include PropelAuthentication
|
278
|
+
before_action :authenticate_user
|
279
|
+
|
280
|
+
# Your API methods here
|
281
|
+
end
|
282
|
+
```
|
283
|
+
|
284
|
+
## Contributing
|
285
|
+
|
286
|
+
Bug reports and pull requests are welcome on GitHub.
|
287
|
+
|
288
|
+
## License
|
289
|
+
|
290
|
+
The gem is available as open source under the [MIT License](https://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED