entrance 0.4.2 → 0.4.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -4,7 +4,7 @@ require 'mongo_mapper'
4
4
  require 'entrance'
5
5
 
6
6
  MongoMapper.connection = Mongo::Connection.new('localhost')
7
- MongoMapper.database = 'entrance-example'
7
+ MongoMapper.database = 'entrance-omniauth-example'
8
8
 
9
9
  Entrance.configure do |config|
10
10
  config.remember_for = 1.month
@@ -18,5 +18,5 @@
18
18
  <input class="right btn btn-primary" tabindex="3" type="submit" value="Log in" />
19
19
 
20
20
  </form>
21
-
21
+
22
22
  <p>Don't have an account? <a href="<%= url('/signup') %>">Sign up</a>.</p>
@@ -0,0 +1,11 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'rack', '1.5.2'
4
+ gem 'sinatra'
5
+ gem 'sinatra-flash'
6
+ gem 'puma'
7
+ gem 'mongo_mapper'
8
+ gem 'bson_ext'
9
+ gem 'omniauth'
10
+ gem 'omniauth-twitter'
11
+ gem 'entrance', :path => './../../'
@@ -0,0 +1,13 @@
1
+ ## Example Sinatra App with Entrance
2
+
3
+ A quick example that shows how to use Entrance with a Sinatra modular app. Requires MongoDB.
4
+
5
+ To run:
6
+
7
+ git clone https://github.com/tomas/entrance
8
+ cd entrance/examples/sinatra-app
9
+ bundle install
10
+ # (start mongo, eg 'mongodb --dbpath=/var/lib/mongodb')
11
+ bundle exec puma
12
+
13
+ And ready-o. Then point your browser to localhost:9292 and sign up, then sign in using your credentials.
@@ -0,0 +1,33 @@
1
+ require 'rubygems'
2
+ require 'bundler/setup'
3
+ require 'mongo_mapper'
4
+ require 'entrance'
5
+
6
+ MongoMapper.connection = Mongo::Connection.new('localhost')
7
+ MongoMapper.database = 'entrance-example'
8
+
9
+ Entrance.configure do |config|
10
+ config.remember_for = 1.month
11
+ config.cookie_secure = false # for testing
12
+ end
13
+
14
+ class User
15
+ include MongoMapper::Document
16
+ include Entrance::Model
17
+
18
+ key :state, :default => 'active'
19
+
20
+ key :name
21
+ key :auth_provider, String
22
+ key :auth_uid, String
23
+
24
+ key :remember_token
25
+ key :remember_token_expires_at, Time
26
+
27
+ provides_entrance :local => false
28
+
29
+ def active?
30
+ state.to_sym == :active
31
+ end
32
+
33
+ end
@@ -0,0 +1,45 @@
1
+ %w(./app/models sinatra/base sinatra/flash).each { |lib| require lib }
2
+
3
+ require 'entrance/addons/omniauth'
4
+ require 'omniauth-twitter'
5
+
6
+ module Example
7
+
8
+ class Routes < Sinatra::Base
9
+
10
+ register Sinatra::Flash
11
+ register Entrance::OmniAuth
12
+
13
+ set :sessions, :secret => 'veryverysecretkey'
14
+ set :views, File.expand_path(File.dirname(__FILE__)) + '/views'
15
+
16
+ set :auth_test, true # only true for testing
17
+ set :auth_remember, true # enables 'remember me' for omniauth logins
18
+ set :auth_providers, {
19
+ :twitter => {
20
+ :key => 'foobar',
21
+ :secret => 'xoxoxoxox'
22
+ }
23
+ }
24
+
25
+ before do
26
+ login_required :except => ['/login']
27
+ end
28
+
29
+ get '/' do
30
+ erb :welcome
31
+ end
32
+
33
+ get '/login' do
34
+ erb :login
35
+ end
36
+
37
+ get '/logout' do
38
+ logout!
39
+ flash[:notice] = 'Logged out! See you soon.'
40
+ redirect to('/login')
41
+ end
42
+
43
+ end
44
+
45
+ end
@@ -0,0 +1,26 @@
1
+ <!doctype html>
2
+ <html xml:lang="en" lang="en">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
6
+
7
+ <title>Example Entrance App</title>
8
+ <meta name="viewport" content="width=device-width,initial-scale=1">
9
+ </head>
10
+
11
+ <body>
12
+
13
+ <div id="container" class="clearfix">
14
+
15
+ <% [:error, :notice, :success].each do |msg| %>
16
+ <% if flash && flash[msg] %>
17
+ <%= "<div class='alert alert-#{msg}'>#{flash[msg]}</div>" %>
18
+ <% end %>
19
+ <% end %>
20
+
21
+ <%= yield %>
22
+
23
+ </div>
24
+
25
+ </body>
26
+ </html>
@@ -0,0 +1,5 @@
1
+ <h2>Log in</h2>
2
+
3
+ <% Entrance::OmniAuth.providers.each do |name| %>
4
+ <a href="/auth/<%= name %>">Login with <%= name %></a>
5
+ <% end %>
@@ -0,0 +1,3 @@
1
+ <h1>Welcome <%= current_user.name %>!</h1>
2
+
3
+ <p>You're now logged in. Now it's time to <a href="<%= url('/logout') %>">log out</a>.</p>
@@ -0,0 +1,5 @@
1
+ require './app/routes'
2
+
3
+ map '/' do
4
+ run Example::Routes
5
+ end
@@ -5,13 +5,14 @@ require 'omniauth'
5
5
 
6
6
  require 'sinatra/base'
7
7
  require 'omniauth-twitter'
8
- require 'entrance/omniauth'
8
+ require 'entrance/addons/omniauth'
9
9
 
10
10
  class Hello < Sinatra::Base
11
11
  register Entrance::OmniAuth
12
12
 
13
- set :auth_test, false # only true for testing
14
- set :auth_providers {
13
+ set :auth_test, false # only true for testing
14
+ set :auth_remember, true # enables 'remember me' for omniauth logins
15
+ set :auth_providers, {
15
16
  :twitter => {
16
17
  :key => 'foobar'
17
18
  }
@@ -26,13 +27,17 @@ module Entrance
26
27
 
27
28
  class << self
28
29
 
30
+ def providers
31
+ @providers ||= []
32
+ end
33
+
29
34
  def registered(app)
30
35
 
31
36
  ::Entrance.model.class_eval do
32
37
 
33
38
  def via_omniauth?
34
- send(::Entrance.config.auth_provider_attr).present? \
35
- && send(::Entrance.config.auth_uid_attr).present?
39
+ send(::Entrance.fields.auth_provider).present? \
40
+ && send(::Entrance.fields.auth_uid).present?
36
41
  end
37
42
 
38
43
  def password_required?
@@ -53,6 +58,9 @@ module Entrance
53
58
  # puts "Initializing #{name} provider: #{options.inspect}"
54
59
  opts = options || {}
55
60
  provider(name, opts[:key], opts[:secret], opts[:extra] || {})
61
+
62
+ app.allow_paths.push("/auth/#{name}/callback")
63
+ ::Entrance::OmniAuth.providers.push(name.to_sym)
56
64
  end
57
65
  end
58
66
 
@@ -66,20 +74,22 @@ module Entrance
66
74
  user = ::Entrance::OmniAuth.auth_or_create(auth) or return return_401
67
75
 
68
76
  if ::Entrance::OmniAuth.valid_user?(user)
69
- login!(user)
77
+ login!(user, app.settings.auth_remember)
70
78
  flash[:success] = 'Welcome back!' if respond_to?(:flash)
71
79
  redirect_to_stored_or(to('/'))
72
80
  else
73
- redirect_with('/', :error, 'Unable to authenticate. Please try again.')
81
+ redirect_with(Entrance.config.access_denied_redirect_to, :error, 'Unable to authenticate. Please try again.')
74
82
  end
75
83
  end
76
84
 
77
85
  end # get, post
78
86
 
79
87
  app.get '/auth/failure' do
80
- redirect_with('/', :error, params[:message])
88
+ redirect_with(Entrance.config.access_denied_redirect_to, :error, params[:message])
81
89
  end
82
90
 
91
+ app.allow_paths.push("/auth/failure")
92
+
83
93
  end # registered
84
94
 
85
95
  def logger
@@ -87,7 +97,7 @@ module Entrance
87
97
  end
88
98
 
89
99
  def log(str)
90
- logger.info(str)
100
+ logger.info(str) rescue nil
91
101
  end
92
102
 
93
103
  def valid_user?(user)
@@ -99,25 +109,25 @@ module Entrance
99
109
 
100
110
  def can_authenticate_with?(service)
101
111
  return true if ::OmniAuth.config.test_mode and service.to_sym == :default
102
- settings.auth_providers.keys.map(&:to_sym).include?(service.to_sym)
112
+ ::Entrance::OmniAuth.providers.include?(service.to_sym)
103
113
  end
104
114
 
105
115
  def find_user_with_username(username)
106
116
  query = {}
107
- query[::Entrance.config.username_attr] = username # .to_s.downcase.strip
117
+ query[::Entrance.fields.username] = username # .to_s.downcase.strip
108
118
  ::Entrance.model.where(query).first
109
119
  end
110
120
 
111
121
  def find_user_with_provider_and_uid(provider, uid)
112
122
  query = {}
113
- query[::Entrance.config.auth_provider_attr] = provider
114
- query[::Entrance.config.auth_uid_attr] = uid
123
+ query[::Entrance.fields.auth_provider] = provider
124
+ query[::Entrance.fields.auth_uid] = uid
115
125
  ::Entrance.model.where(query).first
116
126
  end
117
127
 
118
128
  def set_auth_credentials(user, provider, uid)
119
- user[::Entrance.config.auth_provider_attr] = provider
120
- user[::Entrance.config.auth_uid_attr] = uid
129
+ user[::Entrance.fields.auth_provider] = provider
130
+ user[::Entrance.fields.auth_uid] = uid
121
131
  end
122
132
 
123
133
  def store_auth_credentials(user, provider, uid)
@@ -127,8 +137,8 @@ module Entrance
127
137
 
128
138
  def create_user(name, email, provider, uid)
129
139
  data = {}
130
- data[::Entrance.config.name_attr] = name
131
- data[::Entrance.config.username_attr] = email
140
+ data[::Entrance.fields.name] = name
141
+ data[::Entrance.fields.username] = email
132
142
  user = ::Entrance.model.new(data)
133
143
  set_auth_credentials(user, provider, uid)
134
144
 
@@ -4,8 +4,18 @@ module Entrance
4
4
 
5
5
  REMEMBER_ME_TOKEN = 'auth_token'.freeze
6
6
 
7
+ module ClassMethods
8
+
9
+ # lets us do app.skip_paths.push('/specific/path/we/want/unprotected')
10
+ def allow_paths
11
+ @allow_paths ||= []
12
+ end
13
+
14
+ end
15
+
7
16
  def self.included(base)
8
17
  base.send(:helper_method, :current_user, :logged_in?, :logged_out?) if base.respond_to?(:helper_method)
18
+ base.extend(ClassMethods)
9
19
  end
10
20
 
11
21
  def authenticate_and_login(username, password, remember_me = false)
@@ -29,7 +39,8 @@ module Entrance
29
39
  end
30
40
 
31
41
  def login_required(opts = {})
32
- return if opts[:except] and opts[:except].include?(request.path_info)
42
+ allowed = (opts[:except] || []) + self.class.allow_paths
43
+ return if allowed.any? and allowed.include?(request.path_info)
33
44
  logged_in? || access_denied
34
45
  end
35
46
 
@@ -26,43 +26,43 @@ module Entrance
26
26
  @auth_uid = 'auth_uid'
27
27
  end
28
28
 
29
- def validate!
30
- raise "Invalid model: #{Entrance.config.model}!" unless Kernel.const_defined?(Entrance.config.model)
29
+ def validate_field(attr)
30
+ field = send(attr)
31
+ unless fields.include?(field.to_sym)
32
+ raise "Couldn't find '#{field}' in the #{Entrance.model.name} model."
33
+ end
34
+ end
31
35
 
32
- fields = get_model_fields
36
+ def validate_option(what)
37
+ if field = send("#{what}_token")
38
+ until_field = send("#{what}_until")
33
39
 
34
- %w(username password).each do |attr|
35
- field = send(attr)
36
40
  unless fields.include?(field.to_sym)
37
- raise "Couldn't find '#{field}' in the #{Entrance.model.name} model."
41
+ raise "No #{field} field found. \
42
+ Set the fields.#{what}_token option to nil to disable the #{what} option."
38
43
  end
39
- end
40
-
41
- %w(remember reset).each do |what|
42
- if field = send("#{what}_token")
43
- until_field = send("#{what}_until")
44
-
45
- unless fields.include?(field.to_sym)
46
- raise "No #{field} field found. \
47
- Set the fields.#{what} option to nil to disable the #{what} option."
48
- end
49
44
 
50
- if until_field
51
- unless fields.include?(until_field.to_sym)
52
- raise "Couldn't find a #{until_field} field. Cannot continue."
53
- end
54
- else
55
- puts "Disabling expiration timestamp for the #{what} option. This is a VERY bad idea."
45
+ if until_field
46
+ unless fields.include?(until_field.to_sym)
47
+ raise "Couldn't find a #{until_field} field. Cannot continue."
56
48
  end
49
+ else
50
+ puts "Disabling expiration timestamp for the #{what} option. This is a VERY bad idea."
51
+ end
57
52
 
58
- Entrance.config.can?(what, true)
53
+ Entrance.config.can?(what, true)
59
54
 
60
- mod = what.to_sym == :remember ? Entrance::Model::RememberMethods : Entrance::Model::ResetMethods
61
- Entrance.model.send(:include, mod)
62
- end
55
+ mod = what.to_sym == :remember ? Entrance::Model::RememberMethods : Entrance::Model::ResetMethods
56
+ Entrance.model.send(:include, mod)
63
57
  end
64
58
  end
65
59
 
60
+ protected
61
+
62
+ def fields
63
+ @fields ||= get_model_fields
64
+ end
65
+
66
66
  def get_model_fields
67
67
  model = Entrance.model
68
68
  if model.respond_to?(:columns) # ActiveRecord::Base
@@ -7,8 +7,9 @@ module Entrance
7
7
 
8
8
  module ClassMethods
9
9
 
10
- def provides_entrance(&block)
10
+ def provides_entrance(options = {}, &block)
11
11
  Entrance.config.model = self.name
12
+ local = options.delete(:local) != false
12
13
 
13
14
  # if the target model class does not have a Model.where() method,
14
15
  # then login_by_session wont work, nor the ClassMethods below.
@@ -19,12 +20,20 @@ module Entrance
19
20
 
20
21
  fields = Entrance.fields
21
22
  yield fields if block_given?
22
- fields.validate!
23
23
 
24
- if self.respond_to?(:validates)
25
- validates :password, :presence => true, :length => 6..32, :if => :password_required?
26
- validates :password, :confirmation => true, :if => :password_required?
27
- validates :password_confirmation, :presence => true, :if => :password_required?
24
+ # username and remember token are used both for local and remote (omniauth)
25
+ fields.validate_field(:username)
26
+ fields.validate_option(:remember)
27
+
28
+ if local # allows password & reset
29
+ fields.validate_field(:password)
30
+ fields.validate_option(:reset)
31
+
32
+ if self.respond_to?(:validates)
33
+ validates :password, :presence => true, :length => 6..32, :if => :password_required?
34
+ validates :password, :confirmation => true, :if => :password_required?
35
+ validates :password_confirmation, :presence => true, :if => :password_required?
36
+ end
28
37
  end
29
38
  end
30
39
 
@@ -1,7 +1,7 @@
1
1
  module Entrance
2
2
  MAJOR = 0
3
3
  MINOR = 4
4
- PATCH = 2
4
+ PATCH = 3
5
5
 
6
6
  VERSION = [MAJOR, MINOR, PATCH].join('.')
7
7
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: entrance
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.2
4
+ version: 0.4.3
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2015-03-13 00:00:00.000000000 Z
12
+ date: 2015-03-19 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bcrypt
@@ -111,6 +111,14 @@ files:
111
111
  - examples/sinatra-app/app/views/signup.erb
112
112
  - examples/sinatra-app/app/views/welcome.erb
113
113
  - examples/sinatra-app/config.ru
114
+ - examples/sinatra-omniauth/Gemfile
115
+ - examples/sinatra-omniauth/README.md
116
+ - examples/sinatra-omniauth/app/models.rb
117
+ - examples/sinatra-omniauth/app/routes.rb
118
+ - examples/sinatra-omniauth/app/views/layout.erb
119
+ - examples/sinatra-omniauth/app/views/login.erb
120
+ - examples/sinatra-omniauth/app/views/welcome.erb
121
+ - examples/sinatra-omniauth/config.ru
114
122
  - lib/entrance.rb
115
123
  - lib/entrance/addons/omniauth.rb
116
124
  - lib/entrance/addons/sinatra.rb