auther 4.1.0 → 5.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
}
|