passwd 0.2.0 → 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 +4 -4
- data/.gitignore +10 -17
- data/.travis.yml +3 -11
- data/Gemfile +3 -1
- data/LICENSE +21 -0
- data/README.md +39 -53
- data/Rakefile +6 -6
- data/bin/console +7 -0
- data/bin/setup +8 -0
- data/lib/generators/passwd/install/USAGE +5 -0
- data/lib/generators/passwd/install/install_generator.rb +10 -0
- data/lib/generators/passwd/install/templates/passwd.rb +27 -0
- data/lib/passwd.rb +33 -15
- data/lib/passwd/config.rb +29 -0
- data/lib/passwd/errors.rb +2 -7
- data/lib/passwd/rails/action_controller_ext.rb +77 -0
- data/lib/passwd/rails/active_record_ext.rb +37 -0
- data/lib/passwd/railtie.rb +5 -6
- data/lib/passwd/version.rb +2 -2
- data/passwd.gemspec +13 -14
- metadata +22 -156
- data/.coveralls.yml +0 -1
- data/CHANGELOG.md +0 -35
- data/LICENSE.txt +0 -23
- data/example/.gitignore +0 -16
- data/example/Gemfile +0 -25
- data/example/README.rdoc +0 -28
- data/example/Rakefile +0 -6
- data/example/app/assets/images/.keep +0 -0
- data/example/app/assets/javascripts/application.js +0 -16
- data/example/app/assets/stylesheets/application.css +0 -16
- data/example/app/controllers/application_controller.rb +0 -10
- data/example/app/controllers/concerns/.keep +0 -0
- data/example/app/controllers/profiles_controller.rb +0 -28
- data/example/app/controllers/root_controller.rb +0 -5
- data/example/app/controllers/sessions_controller.rb +0 -29
- data/example/app/helpers/application_helper.rb +0 -2
- data/example/app/mailers/.keep +0 -0
- data/example/app/models/.keep +0 -0
- data/example/app/models/concerns/.keep +0 -0
- data/example/app/models/user.rb +0 -4
- data/example/app/views/layouts/application.html.erb +0 -15
- data/example/app/views/profiles/edit.html.erb +0 -14
- data/example/app/views/profiles/show.html.erb +0 -12
- data/example/app/views/root/index.html.erb +0 -5
- data/example/app/views/sessions/new.html.erb +0 -6
- data/example/bin/bundle +0 -3
- data/example/bin/rails +0 -4
- data/example/bin/rake +0 -4
- data/example/config.ru +0 -4
- data/example/config/application.rb +0 -40
- data/example/config/boot.rb +0 -4
- data/example/config/database.yml +0 -26
- data/example/config/environment.rb +0 -5
- data/example/config/environments/development.rb +0 -37
- data/example/config/environments/production.rb +0 -78
- data/example/config/environments/test.rb +0 -39
- data/example/config/initializers/assets.rb +0 -8
- data/example/config/initializers/backtrace_silencers.rb +0 -7
- data/example/config/initializers/cookies_serializer.rb +0 -3
- data/example/config/initializers/filter_parameter_logging.rb +0 -4
- data/example/config/initializers/inflections.rb +0 -16
- data/example/config/initializers/mime_types.rb +0 -4
- data/example/config/initializers/passwd.rb +0 -41
- data/example/config/initializers/session_store.rb +0 -3
- data/example/config/initializers/wrap_parameters.rb +0 -14
- data/example/config/locales/en.yml +0 -23
- data/example/config/routes.rb +0 -16
- data/example/config/secrets.yml +0 -22
- data/example/db/migrate/20141122165914_create_users.rb +0 -13
- data/example/db/schema.rb +0 -25
- data/example/db/seeds.rb +0 -7
- data/example/lib/assets/.keep +0 -0
- data/example/lib/tasks/.keep +0 -0
- data/example/lib/tasks/user.rake +0 -12
- data/example/log/.keep +0 -0
- data/example/public/404.html +0 -67
- data/example/public/422.html +0 -67
- data/example/public/500.html +0 -66
- data/example/public/favicon.ico +0 -0
- data/example/public/robots.txt +0 -5
- data/example/vendor/assets/javascripts/.keep +0 -0
- data/example/vendor/assets/stylesheets/.keep +0 -0
- data/lib/generators/passwd/config_generator.rb +0 -13
- data/lib/generators/passwd/templates/passwd_config.rb +0 -41
- data/lib/passwd/action_controller_ext.rb +0 -48
- data/lib/passwd/active_record_ext.rb +0 -65
- data/lib/passwd/base.rb +0 -31
- data/lib/passwd/configuration.rb +0 -82
- data/lib/passwd/password.rb +0 -89
- data/lib/passwd/policy.rb +0 -28
- data/lib/passwd/salt.rb +0 -50
- data/spec/passwd/.keep +0 -0
- data/spec/passwd/active_record_ext_spec.rb +0 -80
- data/spec/passwd/base_spec.rb +0 -60
- data/spec/passwd/configuration_spec.rb +0 -50
- data/spec/passwd/password_spec.rb +0 -156
- data/spec/spec_helper.rb +0 -34
- data/spec/support/data_util.rb +0 -11
- data/spec/support/paths.rb +0 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4315761117ee941709bb71c7eb31757f2a5b7ec2
|
4
|
+
data.tar.gz: ad9db1a83f918d12d53a6ac15f4d3cb39e8f3c9b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d8025a6e85f67eacdf856281b17ceef650fb354e48fbafe1a4c06c979a7d2e1bf98ed1e4d812d3429b141945f1f7cbb0bcd7652b1ca65a288ba0583ba7ad971c
|
7
|
+
data.tar.gz: 780295751daffe7ebda019356f62aac1f56fe5a388b09281d8a8889654feb5d97d2f527c0de3c85f8344e1e41351887068202493d1cb5994022bfda4ebe83a71
|
data/.gitignore
CHANGED
@@ -1,17 +1,10 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
lib/bundler/man
|
12
|
-
pkg
|
13
|
-
rdoc
|
14
|
-
spec/reports
|
15
|
-
test/tmp
|
16
|
-
test/version_tmp
|
17
|
-
tmp
|
1
|
+
/.bundle/
|
2
|
+
/.yardoc
|
3
|
+
/_yardoc/
|
4
|
+
/coverage/
|
5
|
+
/doc/
|
6
|
+
/pkg/
|
7
|
+
/spec/reports/
|
8
|
+
/tmp/
|
9
|
+
|
10
|
+
/Gemfile.lock
|
data/.travis.yml
CHANGED
@@ -1,13 +1,5 @@
|
|
1
|
+
sudo: false
|
1
2
|
language: ruby
|
2
3
|
rvm:
|
3
|
-
- 2.
|
4
|
-
|
5
|
-
branches:
|
6
|
-
only:
|
7
|
-
- master
|
8
|
-
gemfile:
|
9
|
-
- Gemfile
|
10
|
-
script: bundle exec rake spec
|
11
|
-
notifications:
|
12
|
-
mails:
|
13
|
-
- i2bskn@gmail.com
|
4
|
+
- 2.5.1
|
5
|
+
before_install: gem install bundler -v 1.16.2
|
data/Gemfile
CHANGED
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2013-2018 Ken Iiboshi
|
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
CHANGED
@@ -1,11 +1,8 @@
|
|
1
1
|
# Passwd
|
2
2
|
|
3
3
|
[](http://badge.fury.io/rb/passwd)
|
4
|
-
[](https://travis-ci.org/i2bskn/passwd)
|
5
|
-
[](https://coveralls.io/r/i2bskn/passwd?branch=master)
|
6
|
-
[](https://codeclimate.com/github/i2bskn/passwd)
|
7
4
|
|
8
|
-
|
5
|
+
Passwd is provide hashed password creation and authentication.
|
9
6
|
|
10
7
|
## Installation
|
11
8
|
|
@@ -17,10 +14,31 @@ gem "passwd"
|
|
17
14
|
|
18
15
|
And then execute:
|
19
16
|
|
20
|
-
|
17
|
+
```
|
18
|
+
$ bundle install
|
19
|
+
```
|
20
|
+
|
21
|
+
Create config file(Only Rails) with:
|
22
|
+
|
23
|
+
```
|
24
|
+
$ bundle exec rails generate passwd:install
|
25
|
+
```
|
26
|
+
|
27
|
+
The following file will be created.
|
28
|
+
See [config](https://github.com/i2bskn/passwd/blob/master/lib/generators/passwd/install/templates/passwd.rb) if not Rails.
|
29
|
+
|
30
|
+
- `config/initializers/passwd.rb`
|
21
31
|
|
22
32
|
## Usage
|
23
33
|
|
34
|
+
### Ruby
|
35
|
+
|
36
|
+
```ruby
|
37
|
+
passwd = Passwd.current
|
38
|
+
passwd.random(10) # Create random password of 10 characters.
|
39
|
+
passwd.hashed_password("secret", "salt") # Create hashed password with stretching.
|
40
|
+
```
|
41
|
+
|
24
42
|
### ActiveRecord with Rails
|
25
43
|
|
26
44
|
Add authentication to your `User` model.
|
@@ -57,39 +75,20 @@ Returns nil if authentication fails or doesn't exists user.
|
|
57
75
|
Instance method is not required `id`.
|
58
76
|
|
59
77
|
```ruby
|
60
|
-
user = User.authenticate(params[:email], params[:password]) #
|
61
|
-
user.authenticate(params[:password])
|
78
|
+
user = User.authenticate(params[:email], params[:password]) # Returns user object or nil.
|
79
|
+
user.authenticate(params[:password]) # Returns true if authentication succeeded.
|
62
80
|
```
|
63
81
|
|
64
82
|
`set_password` method will be set random password.
|
65
83
|
To specify password as an argument if you want to specify a password.
|
66
84
|
|
67
85
|
```ruby
|
68
|
-
current_user.set_password("secret") #
|
69
|
-
current_user.passwd.plain # => new password
|
86
|
+
current_user.set_password("secret") # Set random password if not specified a argument.
|
70
87
|
current_user.save
|
71
88
|
|
72
89
|
new_user = User.new
|
73
|
-
|
74
|
-
UserMailer.register(new_user,
|
75
|
-
```
|
76
|
-
|
77
|
-
`update_password` method will be set new password if the authentication successful.
|
78
|
-
But `update_password` method doesn't call `save` method.
|
79
|
-
|
80
|
-
```ruby
|
81
|
-
# update_password(OLD_PASSWORD, NEW_PASSWORD[, POLICY_CHECK=false])
|
82
|
-
current_user.update_password(old_pass, new_pass, true)
|
83
|
-
current_user.save
|
84
|
-
```
|
85
|
-
|
86
|
-
#### Policy check
|
87
|
-
|
88
|
-
Default policy is 8 more characters and require lower case and require number.
|
89
|
-
Can be changed in configuration file.
|
90
|
-
|
91
|
-
```ruby
|
92
|
-
Passwd.policy_check("secret") # => true or false
|
90
|
+
random_plain_password = new_user.set_password
|
91
|
+
UserMailer.register(new_user, random_plain_password).deliver!
|
93
92
|
```
|
94
93
|
|
95
94
|
### ActionController
|
@@ -123,8 +122,8 @@ class SessionsController < ApplicationController
|
|
123
122
|
|
124
123
|
if @user
|
125
124
|
# Save user_id to session
|
126
|
-
signin
|
127
|
-
|
125
|
+
signin(@user)
|
126
|
+
redirect_to_referer_or some_path, notice: "Signin was successful. Hello #{current_user.name}"
|
128
127
|
else # Authentication fails
|
129
128
|
render action: :new
|
130
129
|
end
|
@@ -133,38 +132,25 @@ class SessionsController < ApplicationController
|
|
133
132
|
# DELETE /signout
|
134
133
|
def destroy
|
135
134
|
# Clear session (Only user_id)
|
136
|
-
signout
|
137
|
-
redirect_to
|
135
|
+
signout
|
136
|
+
redirect_to some_path
|
138
137
|
end
|
139
138
|
end
|
140
139
|
```
|
141
140
|
|
142
|
-
`current_user` method available
|
141
|
+
`current_user` and `signin?` method available in controllers and views.
|
143
142
|
|
144
143
|
```ruby
|
145
|
-
# app/controllers/greet_controller.rb
|
146
144
|
def greet
|
147
|
-
|
145
|
+
name = signin? ? current_user.name : "Guest"
|
146
|
+
render text: "Hello #{name}!!"
|
148
147
|
end
|
149
|
-
|
150
|
-
# app/views/greet/greet.html.erb
|
151
|
-
<p>Hello <%= current_user.name %>!!<p>
|
152
|
-
```
|
153
|
-
|
154
|
-
### Generate configuration file
|
155
|
-
|
156
|
-
Run generator of Rails.
|
157
|
-
Configuration file created to `config/initializers/passwd.rb`.
|
158
|
-
|
159
|
-
```
|
160
|
-
$ bundle exec rails generate passwd:config
|
161
148
|
```
|
162
149
|
|
163
150
|
## Contributing
|
164
151
|
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
4. Push to the branch (`git push origin my-new-feature`)
|
169
|
-
5. Create a new Pull Request
|
152
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/i2bskn/passwd.
|
153
|
+
|
154
|
+
## License
|
170
155
|
|
156
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/Rakefile
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
require "bundler/gem_tasks"
|
2
|
-
require "
|
2
|
+
require "rake/testtask"
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
t.
|
4
|
+
Rake::TestTask.new(:test) do |t|
|
5
|
+
t.libs << "test"
|
6
|
+
t.libs << "lib"
|
7
|
+
t.test_files = FileList["test/**/*_test.rb"]
|
7
8
|
end
|
8
9
|
|
9
|
-
task :default => :
|
10
|
-
|
10
|
+
task :default => :test
|
data/bin/console
ADDED
data/bin/setup
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
module Passwd::Generators
|
2
|
+
class InstallGenerator < Rails::Generators::Base
|
3
|
+
source_root File.expand_path("templates", __dir__)
|
4
|
+
|
5
|
+
desc "Create Passwd config file"
|
6
|
+
def create_config_file
|
7
|
+
copy_file "passwd.rb", "config/initializers/passwd.rb"
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
Passwd.current.config.tap do |config|
|
2
|
+
# Hashing algorithm
|
3
|
+
# Supported algorithm is :md5, :rmd160, :sha1, :sha256, :sha384 and :sha512
|
4
|
+
# config.algorithm = :sha512
|
5
|
+
|
6
|
+
# Number of hashed by stretching
|
7
|
+
# Not stretching if specified nil or 0.
|
8
|
+
# config.stretching = 100
|
9
|
+
|
10
|
+
# Random generate password length
|
11
|
+
# config.length = 10
|
12
|
+
|
13
|
+
# Array of characters used for random password generation
|
14
|
+
# config.characters = [("a".."z"), ("A".."Z"), ("0".."9")].map(&:to_a).flatten
|
15
|
+
end
|
16
|
+
|
17
|
+
# Session key for authentication
|
18
|
+
# Rails.application.config.passwd.session_key = :user_id
|
19
|
+
|
20
|
+
# Authentication Model Class
|
21
|
+
# Rails.application.config.passwd.auth_class = :User
|
22
|
+
|
23
|
+
# Redirect path when not signin
|
24
|
+
# Rails.application.config.passwd.signin_path = :signin_path
|
25
|
+
|
26
|
+
# Salt generation logic
|
27
|
+
# Rails.application.config.passwd.random_salt = proc { SecureRandom.uuid }
|
data/lib/passwd.rb
CHANGED
@@ -1,25 +1,43 @@
|
|
1
|
-
require "digest
|
2
|
-
require "
|
1
|
+
require "digest"
|
2
|
+
require "securerandom"
|
3
3
|
|
4
4
|
require "passwd/version"
|
5
5
|
require "passwd/errors"
|
6
|
-
require "passwd/
|
7
|
-
require "passwd/configuration"
|
8
|
-
require "passwd/base"
|
9
|
-
require "passwd/salt"
|
10
|
-
require "passwd/password"
|
6
|
+
require "passwd/config"
|
11
7
|
require "passwd/railtie" if defined?(Rails)
|
12
8
|
|
13
|
-
|
14
|
-
|
15
|
-
|
9
|
+
class Passwd
|
10
|
+
class << self
|
11
|
+
def current
|
12
|
+
@current ||= new
|
13
|
+
end
|
16
14
|
|
17
|
-
|
18
|
-
|
15
|
+
def current=(passwd)
|
16
|
+
@current = passwd
|
17
|
+
end
|
19
18
|
end
|
20
19
|
|
21
|
-
def
|
22
|
-
|
20
|
+
def initialize(conf = nil)
|
21
|
+
@config = conf
|
22
|
+
end
|
23
|
+
|
24
|
+
def hashed_password(plain, salt)
|
25
|
+
config.stretching.to_i.times.with_object([digest_class.hexdigest([plain, salt].join)]) { |_, pass|
|
26
|
+
pass[0] = digest_class.hexdigest(pass[0])
|
27
|
+
}.first
|
28
|
+
end
|
29
|
+
|
30
|
+
def random(n = nil)
|
31
|
+
Array.new(n || config.length) { config.characters[rand(config.characters.size)] }.join
|
23
32
|
end
|
24
|
-
end
|
25
33
|
|
34
|
+
def config
|
35
|
+
@config ||= Config.new
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def digest_class
|
41
|
+
Digest.const_get(config.algorithm.upcase)
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
class Passwd
|
2
|
+
class Config
|
3
|
+
VALID_OPTIONS = [
|
4
|
+
:algorithm,
|
5
|
+
:stretching,
|
6
|
+
:length,
|
7
|
+
:characters,
|
8
|
+
].freeze
|
9
|
+
|
10
|
+
attr_accessor *VALID_OPTIONS
|
11
|
+
|
12
|
+
def initialize(options = {})
|
13
|
+
reset
|
14
|
+
merge(options)
|
15
|
+
end
|
16
|
+
|
17
|
+
def merge(options)
|
18
|
+
options.keys.each { |key| send("#{key}=", options[key]) }
|
19
|
+
self
|
20
|
+
end
|
21
|
+
|
22
|
+
def reset
|
23
|
+
@algorithm = :sha512
|
24
|
+
@stretching = 100
|
25
|
+
@length = 10
|
26
|
+
@characters = [("a".."z"), ("A".."Z"), ("0".."9")].map(&:to_a).flatten
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
data/lib/passwd/errors.rb
CHANGED
@@ -1,8 +1,3 @@
|
|
1
|
-
|
2
|
-
class
|
3
|
-
class UnauthorizedAccess < PasswdError; end
|
4
|
-
class PolicyNotMatch < PasswdError; end
|
5
|
-
class AuthenticationFails < PasswdError; end
|
6
|
-
class ConfigError < PasswdError; end
|
1
|
+
class Passwd
|
2
|
+
class UnauthorizedAccess < StandardError; end
|
7
3
|
end
|
8
|
-
|
@@ -0,0 +1,77 @@
|
|
1
|
+
module Passwd::Rails
|
2
|
+
module ActionControllerExt
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
included do
|
6
|
+
helper_method :current_user, :signin?
|
7
|
+
end
|
8
|
+
|
9
|
+
private
|
10
|
+
|
11
|
+
def current_user
|
12
|
+
return @current_user if instance_variable_defined?(:@current_user)
|
13
|
+
|
14
|
+
@current_user = _auth_class.find_by(id: session[_auth_key])
|
15
|
+
end
|
16
|
+
|
17
|
+
def signin?
|
18
|
+
current_user.present?
|
19
|
+
end
|
20
|
+
|
21
|
+
def signin(user)
|
22
|
+
if user.present?
|
23
|
+
@current_user = user
|
24
|
+
session[_auth_key] = user&.id
|
25
|
+
end
|
26
|
+
|
27
|
+
user.present?
|
28
|
+
end
|
29
|
+
|
30
|
+
def signout
|
31
|
+
session[_auth_key] = nil
|
32
|
+
@current_user = nil
|
33
|
+
end
|
34
|
+
|
35
|
+
def redirect_to_referer_or(path, options = {})
|
36
|
+
redirect_to session[:referer].presence || path, **options
|
37
|
+
end
|
38
|
+
|
39
|
+
def require_signin
|
40
|
+
unless signin?
|
41
|
+
path = _signin_path
|
42
|
+
raise UnauthorizedAccess unless path
|
43
|
+
session[:referer] = request.fullpath
|
44
|
+
redirect_to path
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def passwd_auth_class
|
49
|
+
nil
|
50
|
+
end
|
51
|
+
|
52
|
+
def passwd_auth_key
|
53
|
+
nil
|
54
|
+
end
|
55
|
+
|
56
|
+
def passwd_signin_path
|
57
|
+
nil
|
58
|
+
end
|
59
|
+
|
60
|
+
def _auth_class
|
61
|
+
(Rails.application.config.passwd.auth_class || passwd_auth_class || :User).to_s.constantize
|
62
|
+
end
|
63
|
+
|
64
|
+
def _auth_key
|
65
|
+
Rails.application.config.passwd.session_key || passwd_auth_key || :user_id
|
66
|
+
end
|
67
|
+
|
68
|
+
def _signin_path
|
69
|
+
name = Rails.application.config.passwd.signin_path || passwd_signin_path || :signin_path
|
70
|
+
_url_helpers.respond_to?(name) ? _url_helpers.public_send(name) : nil
|
71
|
+
end
|
72
|
+
|
73
|
+
def _url_helpers
|
74
|
+
Rails.application.routes.url_helpers
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|