auther 4.1.0 → 5.0.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
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/README.md +70 -43
- data/app/assets/stylesheets/auther/application.scss +3 -1
- data/app/assets/stylesheets/auther/auther.scss +98 -9
- data/app/controllers/auther/base_controller.rb +26 -21
- data/app/controllers/auther/session_controller.rb +10 -7
- data/app/models/auther/account.rb +2 -1
- data/app/presenters/auther/account.rb +10 -0
- data/app/views/auther/session/new.html.slim +19 -37
- data/app/views/layouts/auther/auth.html.slim +0 -2
- data/bin/rails +4 -7
- data/lib/auther/authenticator.rb +14 -18
- data/lib/auther/cipher.rb +2 -3
- data/lib/auther/engine.rb +3 -22
- data/lib/auther/gatekeeper.rb +18 -15
- data/lib/auther/identity.rb +3 -2
- data/lib/auther/keymaster.rb +5 -4
- data/lib/auther/null_logger.rb +6 -6
- data/lib/auther/settings.rb +14 -7
- data/lib/auther/tasks/rspec.rake +6 -0
- data/lib/auther/tasks/rubocop.rake +6 -0
- data/lib/generators/auther/install/install_generator.rb +1 -0
- data/vendor/assets/stylesheets/bitters/_base.scss +10 -0
- data/vendor/assets/stylesheets/bitters/_buttons.scss +35 -0
- data/vendor/assets/stylesheets/bitters/_forms.scss +90 -0
- data/vendor/assets/stylesheets/bitters/_grid-settings.scss +14 -0
- data/vendor/assets/stylesheets/bitters/_typography.scss +49 -0
- data/vendor/assets/stylesheets/bitters/_variables.scss +42 -0
- metadata +53 -20
- metadata.gz.sig +0 -0
- data/app/assets/javascripts/auther/application.js +0 -5
- data/app/assets/stylesheets/auther/foundation_and_overrides.scss +0 -1191
- data/app/helpers/auther/foundation_helper.rb +0 -9
@@ -2,6 +2,7 @@ require "active_model"
|
|
2
2
|
|
3
3
|
module Auther
|
4
4
|
module Presenter
|
5
|
+
# Adapter for presenting an account within a view.
|
5
6
|
class Account
|
6
7
|
include ActiveModel::Validations
|
7
8
|
|
@@ -14,6 +15,15 @@ module Auther
|
|
14
15
|
@login = options[:login]
|
15
16
|
@password = options[:password]
|
16
17
|
end
|
18
|
+
|
19
|
+
def error? key
|
20
|
+
errors.key? key
|
21
|
+
end
|
22
|
+
|
23
|
+
def error_message key
|
24
|
+
return "" unless error?(key)
|
25
|
+
"#{key.capitalize} #{errors.messages[key].first}"
|
26
|
+
end
|
17
27
|
end
|
18
28
|
end
|
19
29
|
end
|
@@ -1,43 +1,25 @@
|
|
1
1
|
- content_for(:title) { @title }
|
2
2
|
|
3
|
-
-
|
4
|
-
-
|
5
|
-
-
|
6
|
-
- name_error = error_keys.include?(:name)
|
3
|
+
.auther-page
|
4
|
+
.auther-content
|
5
|
+
h1.auther-title = "Authorization"
|
7
6
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
7
|
+
= form_for @account, as: :account, url: "/auther/session", html: {class: "auther-credentials"} do |form|
|
8
|
+
div class=%(auther-form-section #{"auther-error" if @account.error?(:login)})
|
9
|
+
= form.label :login, "Login:", class: "auther-form-label"
|
10
|
+
.auther-form-group
|
11
|
+
= form.text_field :login, class: "auther-form-input"
|
12
|
+
small.auther-error-message = @account.error_message(:login)
|
13
13
|
|
14
|
-
.
|
15
|
-
.
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
= content_tag :div, class: render_foundation_error(login_error, classes: %w(small-6 columns))
|
20
|
-
= form.text_field :login
|
21
|
-
= content_tag(:small, @account_presenter.errors.full_messages.first, class: "error") if login_error
|
22
|
-
.row
|
23
|
-
.small-8
|
24
|
-
.row
|
25
|
-
= content_tag :div, class: render_foundation_error(password_error, classes: %w(small-6 columns))
|
26
|
-
= form.label :password, "Password:", class: "inline right"
|
27
|
-
= content_tag :div, class: render_foundation_error(password_error, classes: %w(small-6 columns))
|
28
|
-
= form.password_field :password
|
29
|
-
= content_tag(:small, @account_presenter.errors.full_messages.first, class: "error") if password_error
|
14
|
+
div class=%(auther-form-section #{"auther-error" if @account.error?(:password)})
|
15
|
+
= form.label :password, "Password:", class: "auther-form-label"
|
16
|
+
.auther-form-group
|
17
|
+
= form.password_field :password, class: "auther-form-input"
|
18
|
+
small.auther-error-message = @account.error_message(:password)
|
30
19
|
|
31
|
-
.
|
32
|
-
.
|
33
|
-
|
34
|
-
|
35
|
-
= form.label :name, "Account:", class: "inline right"
|
36
|
-
.small-6.columns
|
37
|
-
= form.select :name, @account_options
|
20
|
+
.auther-form-section
|
21
|
+
= form.label :name, "Account:", class: "auther-form-select-label"
|
22
|
+
.auther-form-group
|
23
|
+
= form.select :name, @account_options, {}, class: "auther-form-select"
|
38
24
|
|
39
|
-
.
|
40
|
-
.small-8
|
41
|
-
.row
|
42
|
-
.small-6.right
|
43
|
-
= form.submit "Login", class: "button round expand"
|
25
|
+
= form.submit "Login", class: "auther-button"
|
data/bin/rails
CHANGED
@@ -1,8 +1,5 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
ENGINE_ROOT = File.expand_path("../..", __FILE__)
|
2
|
+
ENGINE_PATH = File.expand_path("../../lib/auther/engine", __FILE__)
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
require 'rails/all'
|
8
|
-
require 'rails/engine/commands'
|
4
|
+
require "rails/all"
|
5
|
+
require "rails/engine/commands"
|
data/lib/auther/authenticator.rb
CHANGED
@@ -1,9 +1,7 @@
|
|
1
1
|
module Auther
|
2
|
+
# Manages account authentication.
|
2
3
|
class Authenticator
|
3
|
-
|
4
|
-
attr_reader :logger
|
5
|
-
|
6
|
-
def initialize secret, account_model, account_presenter, logger = Auther::NullLogger.new(STDOUT)
|
4
|
+
def initialize secret, account_model, account_presenter, logger: Auther::NullLogger.new(STDOUT)
|
7
5
|
@cipher = Auther::Cipher.new secret
|
8
6
|
@account_model = account_model
|
9
7
|
@account_presenter = account_presenter
|
@@ -12,15 +10,15 @@ module Auther
|
|
12
10
|
|
13
11
|
def authenticated?
|
14
12
|
account_model.valid? &&
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
13
|
+
account_presenter.valid? &&
|
14
|
+
authentic_name? &&
|
15
|
+
authentic_login? &&
|
16
|
+
authentic_password?
|
19
17
|
end
|
20
18
|
|
21
19
|
private
|
22
20
|
|
23
|
-
attr_reader :cipher, :account_model, :account_presenter
|
21
|
+
attr_reader :cipher, :account_model, :account_presenter, :logger
|
24
22
|
|
25
23
|
def log_info message
|
26
24
|
id = "[#{Auther::Keymaster.namespace}]"
|
@@ -28,17 +26,15 @@ module Auther
|
|
28
26
|
end
|
29
27
|
|
30
28
|
def authentic? encrypted_value, value, error_name
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
account_presenter.errors.add error_name, "is invalid"
|
36
|
-
false
|
37
|
-
end
|
38
|
-
rescue ActiveSupport::MessageVerifier::InvalidSignature => error
|
39
|
-
log_info %(Authentication failed! Invalid credential(s) for "#{account_model.name}" account.)
|
29
|
+
if cipher.decrypt(encrypted_value) == value
|
30
|
+
true
|
31
|
+
else
|
32
|
+
account_presenter.errors.add error_name, "is invalid"
|
40
33
|
false
|
41
34
|
end
|
35
|
+
rescue ActiveSupport::MessageVerifier::InvalidSignature
|
36
|
+
log_info %(Authentication failed! Invalid credential(s) for "#{account_model.name}" account.)
|
37
|
+
false
|
42
38
|
end
|
43
39
|
|
44
40
|
def authentic_name?
|
data/lib/auther/cipher.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
module Auther
|
2
|
+
# Manages encryption/decryption.
|
2
3
|
class Cipher
|
3
4
|
def initialize secret
|
4
5
|
@encryptor = ActiveSupport::MessageEncryptor.new secret
|
@@ -14,8 +15,6 @@ module Auther
|
|
14
15
|
|
15
16
|
private
|
16
17
|
|
17
|
-
|
18
|
-
@encryptor
|
19
|
-
end
|
18
|
+
attr_reader :encryptor
|
20
19
|
end
|
21
20
|
end
|
data/lib/auther/engine.rb
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
module Auther
|
2
|
+
# The main engine.
|
2
3
|
class Engine < ::Rails::Engine
|
3
4
|
isolate_namespace Auther
|
4
5
|
|
5
|
-
# Set defaults. Can be overwritten in app config.
|
6
6
|
config.auther_settings = {}
|
7
|
+
config.action_view.field_error_proc = proc { |html_tag, _| html_tag.html_safe }
|
7
8
|
|
8
|
-
# Autoload presenters
|
9
9
|
config.to_prepare do
|
10
10
|
Dir.glob(Engine.root + "app/presenters/**/*.rb").each do |presenter|
|
11
11
|
require_dependency presenter
|
@@ -13,23 +13,8 @@ module Auther
|
|
13
13
|
end
|
14
14
|
|
15
15
|
initializer "auther.initialize" do |app|
|
16
|
-
|
17
|
-
|
18
|
-
# Add jQuery assets.
|
19
|
-
add_asset_paths asset_paths, "jquery-rails", "javascripts"
|
20
|
-
|
21
|
-
# Add Modernizr assets.
|
22
|
-
add_asset_paths asset_paths, "modernizr-rails", "javascripts"
|
23
|
-
|
24
|
-
# Add Zurb Foundation assets.
|
25
|
-
add_asset_paths asset_paths, "foundation-rails", "javascripts"
|
26
|
-
add_asset_paths asset_paths, "foundation-rails", "stylesheets"
|
27
|
-
|
28
|
-
# Configure log filter parameters.
|
16
|
+
app.config.app_middleware.use Gatekeeper, app.config.auther_settings
|
29
17
|
app.config.filter_parameters += [:login, :password]
|
30
|
-
|
31
|
-
# Initialize Gatekeeper middleware.
|
32
|
-
app.config.app_middleware.use Auther::Gatekeeper, app.config.auther_settings
|
33
18
|
end
|
34
19
|
|
35
20
|
private
|
@@ -37,9 +22,5 @@ module Auther
|
|
37
22
|
def full_gem_path name
|
38
23
|
Gem.loaded_specs[name].full_gem_path
|
39
24
|
end
|
40
|
-
|
41
|
-
def add_asset_paths paths, name, directory
|
42
|
-
paths << "#{full_gem_path name}/vendor/assets/#{directory}"
|
43
|
-
end
|
44
25
|
end
|
45
26
|
end
|
data/lib/auther/gatekeeper.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
module Auther
|
2
|
+
# Rack middleware that guards access to sensitive routes.
|
2
3
|
class Gatekeeper
|
3
4
|
attr_reader :application, :environment, :settings
|
4
5
|
|
@@ -70,7 +71,7 @@ module Auther
|
|
70
71
|
end
|
71
72
|
|
72
73
|
def clean_paths paths
|
73
|
-
paths.map { |path| path.chomp
|
74
|
+
paths.map { |path| path.chomp "/" }
|
74
75
|
end
|
75
76
|
|
76
77
|
def blacklisted_paths
|
@@ -82,23 +83,25 @@ module Auther
|
|
82
83
|
blacklisted_paths.select { |blacklisted_path| path.include? blacklisted_path }
|
83
84
|
end
|
84
85
|
|
85
|
-
def
|
86
|
+
def account_authenticated? account
|
86
87
|
keymaster = Auther::Keymaster.new account.fetch(:name)
|
87
88
|
cipher = Auther::Cipher.new settings.secret
|
88
89
|
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
90
|
+
session_login = cipher.decrypt session[keymaster.login_key]
|
91
|
+
session_password = cipher.decrypt session[keymaster.password_key]
|
92
|
+
account_login = cipher.decrypt account.fetch(:encrypted_login)
|
93
|
+
account_password = cipher.decrypt account.fetch(:encrypted_password)
|
94
|
+
|
95
|
+
session_login == account_login && session_password == account_password
|
96
|
+
end
|
97
|
+
|
98
|
+
def authenticated? account
|
99
|
+
authenticated = account_authenticated? account
|
100
|
+
log_authentication authenticated, account.fetch(:name)
|
101
|
+
authenticated
|
102
|
+
rescue ActiveSupport::MessageVerifier::InvalidSignature
|
103
|
+
log_info %(Authentication failed! Invalid credential(s) for "#{account.fetch :name}" account.)
|
104
|
+
false
|
102
105
|
end
|
103
106
|
|
104
107
|
def account_authorized? account, path
|
data/lib/auther/identity.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
module Auther
|
2
|
+
# Gem identity information.
|
2
3
|
module Identity
|
3
4
|
def self.name
|
4
5
|
"auther"
|
@@ -9,11 +10,11 @@ module Auther
|
|
9
10
|
end
|
10
11
|
|
11
12
|
def self.version
|
12
|
-
"
|
13
|
+
"5.0.0"
|
13
14
|
end
|
14
15
|
|
15
16
|
def self.label_version
|
16
|
-
|
17
|
+
"#{label} #{version}"
|
17
18
|
end
|
18
19
|
end
|
19
20
|
end
|
data/lib/auther/keymaster.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
module Auther
|
2
|
+
# Provides access to setting keys.
|
2
3
|
class Keymaster
|
3
4
|
attr_reader :account_name
|
4
5
|
|
@@ -7,13 +8,13 @@ module Auther
|
|
7
8
|
end
|
8
9
|
|
9
10
|
def self.redirect_url_key options = {}
|
10
|
-
[namespace, "redirect", "url"] * options.fetch(:delimiter,
|
11
|
+
[namespace, "redirect", "url"] * options.fetch(:delimiter, "_")
|
11
12
|
end
|
12
13
|
|
13
14
|
def self.get_account_name session = {}
|
14
15
|
matching_keys = session.keys.select { |key| key.to_s =~ /auther.+login/ }
|
15
|
-
key = matching_keys.first ||
|
16
|
-
key.gsub("#{namespace}_",
|
16
|
+
key = matching_keys.first || ""
|
17
|
+
key.gsub("#{namespace}_", "").gsub "_login", ""
|
17
18
|
end
|
18
19
|
|
19
20
|
def self.get_account_login session = {}
|
@@ -36,7 +37,7 @@ module Auther
|
|
36
37
|
private
|
37
38
|
|
38
39
|
def build_key key_name, options = {}
|
39
|
-
[self.class.namespace, account_name, key_name].compact * options.fetch(:delimiter,
|
40
|
+
[self.class.namespace, account_name, key_name].compact * options.fetch(:delimiter, "_")
|
40
41
|
end
|
41
42
|
end
|
42
43
|
end
|
data/lib/auther/null_logger.rb
CHANGED
@@ -1,22 +1,22 @@
|
|
1
1
|
module Auther
|
2
2
|
# The default logger which purposefully does nothing at all.
|
3
3
|
class NullLogger
|
4
|
-
def initialize
|
4
|
+
def initialize _
|
5
5
|
end
|
6
6
|
|
7
|
-
def info
|
7
|
+
def info _
|
8
8
|
end
|
9
9
|
|
10
|
-
def warn
|
10
|
+
def warn _
|
11
11
|
end
|
12
12
|
|
13
|
-
def error
|
13
|
+
def error _
|
14
14
|
end
|
15
15
|
|
16
|
-
def fatal
|
16
|
+
def fatal _
|
17
17
|
end
|
18
18
|
|
19
|
-
def debug
|
19
|
+
def debug _
|
20
20
|
end
|
21
21
|
end
|
22
22
|
end
|
data/lib/auther/settings.rb
CHANGED
@@ -1,14 +1,21 @@
|
|
1
1
|
module Auther
|
2
|
+
# Represents Auther settings.
|
2
3
|
class Settings
|
3
4
|
attr_reader :title, :label, :secret, :accounts, :auth_url, :logger
|
4
5
|
|
5
|
-
def initialize
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
6
|
+
def initialize title: "Authorization",
|
7
|
+
label: "Authorization",
|
8
|
+
secret: "",
|
9
|
+
accounts: [],
|
10
|
+
auth_url: "/login",
|
11
|
+
logger: Auther::NullLogger.new(STDOUT)
|
12
|
+
|
13
|
+
@title = title
|
14
|
+
@label = label
|
15
|
+
@secret = secret
|
16
|
+
@accounts = accounts
|
17
|
+
@auth_url = auth_url
|
18
|
+
@logger = logger
|
12
19
|
end
|
13
20
|
|
14
21
|
def find_account name
|
@@ -0,0 +1,35 @@
|
|
1
|
+
#{$all-buttons} {
|
2
|
+
appearance: none;
|
3
|
+
background-color: $action-color;
|
4
|
+
border: 0;
|
5
|
+
border-radius: $base-border-radius;
|
6
|
+
color: #fff;
|
7
|
+
cursor: pointer;
|
8
|
+
display: inline-block;
|
9
|
+
font-family: $base-font-family;
|
10
|
+
font-size: $base-font-size;
|
11
|
+
-webkit-font-smoothing: antialiased;
|
12
|
+
font-weight: 600;
|
13
|
+
line-height: 1;
|
14
|
+
padding: $small-spacing $base-spacing;
|
15
|
+
text-decoration: none;
|
16
|
+
transition: background-color $base-duration $base-timing;
|
17
|
+
user-select: none;
|
18
|
+
vertical-align: middle;
|
19
|
+
white-space: nowrap;
|
20
|
+
|
21
|
+
&:hover,
|
22
|
+
&:focus {
|
23
|
+
background-color: shade($action-color, 20%);
|
24
|
+
color: #fff;
|
25
|
+
}
|
26
|
+
|
27
|
+
&:disabled {
|
28
|
+
cursor: not-allowed;
|
29
|
+
opacity: 0.5;
|
30
|
+
|
31
|
+
&:hover {
|
32
|
+
background-color: $action-color;
|
33
|
+
}
|
34
|
+
}
|
35
|
+
}
|