authie 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/db/migrate/20141012174250_create_authie_sessions.rb +17 -0
- data/lib/authie.rb +4 -0
- data/lib/authie/config.rb +24 -0
- data/lib/authie/controller_extension.rb +48 -0
- data/lib/authie/engine.rb +21 -0
- data/lib/authie/error.rb +4 -0
- data/lib/authie/session.rb +153 -0
- data/lib/authie/version.rb +3 -0
- metadata +53 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 5fae3a28b39351d3fd2d65cceb2fb3c27ae48fc8
|
4
|
+
data.tar.gz: f495eea593432bacdfb352cf81e22c06a4d51e43
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: b4ea09a545f6e32133e3c07fc79a8b2f925dd3ca796146fc1beff04e4863fd7acaa0cdc725a035087f2d6d0616ea18a29afaedaf937846bd7a1b5ff49b9431d7
|
7
|
+
data.tar.gz: 556e8ae46773fefcd25b11e9e3d0f30c8cd7b71dcc54986f28255ce57f7867e9d984d1237002a9bd7eb6e8b6467ffb846b77acb457dfa091eb3ce73f838f85d0
|
@@ -0,0 +1,17 @@
|
|
1
|
+
class CreateAuthieSessions < ActiveRecord::Migration
|
2
|
+
def change
|
3
|
+
create_table :authie_sessions do |t|
|
4
|
+
t.string :token, :browser_id
|
5
|
+
t.integer :user_id
|
6
|
+
t.boolean :active, :default => true
|
7
|
+
t.text :data
|
8
|
+
t.datetime :expires_at
|
9
|
+
t.datetime :login_at
|
10
|
+
t.string :login_ip
|
11
|
+
t.datetime :last_activity_at
|
12
|
+
t.string :last_activity_ip, :last_activity_path
|
13
|
+
t.string :user_agent
|
14
|
+
t.timestamps
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/lib/authie.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
module Authie
|
2
|
+
class Config
|
3
|
+
|
4
|
+
def session_inactivity_timeout
|
5
|
+
@session_inactivity_timeout || 12.hours
|
6
|
+
end
|
7
|
+
attr_writer :session_inactivity_timeout
|
8
|
+
|
9
|
+
def persistent_session_length
|
10
|
+
@persistent_session_length || 2.months
|
11
|
+
end
|
12
|
+
attr_writer :persistent_session_length
|
13
|
+
|
14
|
+
def user_model_class_name
|
15
|
+
@user_model_class_name || 'User'
|
16
|
+
end
|
17
|
+
attr_writer :user_model_class_name
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.config
|
22
|
+
@config ||= Config.new
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module Authie
|
2
|
+
module ControllerExtension
|
3
|
+
|
4
|
+
def self.included(base)
|
5
|
+
base.helper_method :logged_in?, :current_user, :auth_session
|
6
|
+
base.before_filter :set_browser_id
|
7
|
+
end
|
8
|
+
|
9
|
+
private
|
10
|
+
|
11
|
+
# Set a random browser ID for this browser.
|
12
|
+
# TODO: check that this is unique before setting it.
|
13
|
+
def set_browser_id
|
14
|
+
unless cookies[:browser_id]
|
15
|
+
cookies[:browser_id] = {:value => SecureRandom.uuid, :expires => 20.years.from_now}
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
# Return the currently logged in user object
|
20
|
+
def current_user
|
21
|
+
auth_session.user
|
22
|
+
end
|
23
|
+
|
24
|
+
# Set the currently logged in user
|
25
|
+
def current_user=(user)
|
26
|
+
if user.is_a?(Authie.config.user_model_class_name.constantize)
|
27
|
+
unless logged_in?
|
28
|
+
@auth_session = Session.start(self, :user => user)
|
29
|
+
end
|
30
|
+
@current_user = user
|
31
|
+
else
|
32
|
+
auth_session.destroy if logged_in?
|
33
|
+
@current_user = nil
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
# Is anyone currently logged in?
|
38
|
+
def logged_in?
|
39
|
+
auth_session.is_a?(Session)
|
40
|
+
end
|
41
|
+
|
42
|
+
# Return the currently logged in user session
|
43
|
+
def auth_session
|
44
|
+
@auth_session ||= Session.get_session(self)
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Authie
|
2
|
+
class Engine < ::Rails::Engine
|
3
|
+
|
4
|
+
initializer 'authie.initialize' do |app|
|
5
|
+
config.paths["db/migrate"].expanded.each do |expanded_path|
|
6
|
+
app.config.paths["db/migrate"] << expanded_path
|
7
|
+
end
|
8
|
+
|
9
|
+
ActiveSupport.on_load :active_record do
|
10
|
+
require 'authie/session'
|
11
|
+
end
|
12
|
+
|
13
|
+
ActiveSupport.on_load :action_controller do
|
14
|
+
require 'authie/controller_extension'
|
15
|
+
include Authie::ControllerExtension
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
data/lib/authie/error.rb
ADDED
@@ -0,0 +1,153 @@
|
|
1
|
+
module Authie
|
2
|
+
class Session < ActiveRecord::Base
|
3
|
+
|
4
|
+
# Define some errors which may be used
|
5
|
+
class InactiveSession < Error; end
|
6
|
+
class ExpiredSession < Error; end
|
7
|
+
class BrowserMismatch < Error; end
|
8
|
+
|
9
|
+
# Set table name
|
10
|
+
self.table_name = "authie_sessions"
|
11
|
+
|
12
|
+
# Relationships
|
13
|
+
belongs_to :user, :class_name => Authie.config.user_model_class_name, :foreign_key => 'user_id'
|
14
|
+
|
15
|
+
# Scopes
|
16
|
+
scope :active, -> { where(:active => true) }
|
17
|
+
scope :asc, -> { order(:last_activity_at => :desc) }
|
18
|
+
|
19
|
+
# Attributes
|
20
|
+
serialize :data, Hash
|
21
|
+
attr_accessor :controller
|
22
|
+
|
23
|
+
before_create do
|
24
|
+
self.token = SecureRandom.base64(32)
|
25
|
+
if controller
|
26
|
+
self.user_agent = controller.request.user_agent
|
27
|
+
set_cookie!
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
before_destroy do
|
32
|
+
cookies.delete(:user_session) if controller
|
33
|
+
end
|
34
|
+
|
35
|
+
# This method should be called each time a user performs an
|
36
|
+
# action while authenticated with this session.
|
37
|
+
def touch!
|
38
|
+
self.last_activity_at = Time.now
|
39
|
+
self.last_activity_ip = controller.request.ip
|
40
|
+
self.last_activity_path = controller.request.path
|
41
|
+
self.save!
|
42
|
+
end
|
43
|
+
|
44
|
+
# Sets the cookie on the associated controller.
|
45
|
+
def set_cookie!
|
46
|
+
cookies[:user_session] = {
|
47
|
+
:value => token,
|
48
|
+
:secure => controller.request.ssl?,
|
49
|
+
:httponly => true,
|
50
|
+
:expires => self.expires_at
|
51
|
+
}
|
52
|
+
end
|
53
|
+
|
54
|
+
# Check the security of the session to ensure it can be used.
|
55
|
+
def check_security!
|
56
|
+
if controller
|
57
|
+
if cookies[:browser_id] != self.browser_id
|
58
|
+
invalidate!
|
59
|
+
raise BrowserMismatch, "Browser ID mismatch"
|
60
|
+
end
|
61
|
+
|
62
|
+
unless self.active?
|
63
|
+
invalidate!
|
64
|
+
raise InactiveSession, "Session is no longer active"
|
65
|
+
end
|
66
|
+
|
67
|
+
if self.expires_at && self.expires_at < Time.now
|
68
|
+
invalidate!
|
69
|
+
raise ExpiredSession, "Persistent session has expired"
|
70
|
+
end
|
71
|
+
|
72
|
+
if self.expires_at.nil? && self.last_activity_at && self.last_activity_at < Authie.config.session_inactivity_timeout.ago
|
73
|
+
invalidate!
|
74
|
+
raise InactiveSession, "Non-persistent session has expired"
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
# Allow this session to persist rather than expiring at the end of the
|
80
|
+
# current browser session
|
81
|
+
def persist!
|
82
|
+
self.expires_at = Authie.config.persistent_session_length.from_now
|
83
|
+
self.save!
|
84
|
+
set_cookie!
|
85
|
+
end
|
86
|
+
|
87
|
+
# Is this a persistent session?
|
88
|
+
def persistent?
|
89
|
+
!!expires_at
|
90
|
+
end
|
91
|
+
|
92
|
+
# Mark this session as invalid
|
93
|
+
def invalidate!
|
94
|
+
self.active = false
|
95
|
+
self.save!
|
96
|
+
if controller
|
97
|
+
cookies.delete(:user_session)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
# Set some additional data in this session
|
102
|
+
def set(key, value)
|
103
|
+
self.data ||= {}
|
104
|
+
self.data[key.to_s] = value
|
105
|
+
self.save!
|
106
|
+
end
|
107
|
+
|
108
|
+
# Get some additional data from this session
|
109
|
+
def get(key)
|
110
|
+
(self.data ||= {})[key.to_s]
|
111
|
+
end
|
112
|
+
|
113
|
+
# Find a session from the database for the given controller instance.
|
114
|
+
# Returns a session object or :none if no session is found.
|
115
|
+
def self.get_session(controller)
|
116
|
+
cookies = controller.send(:cookies)
|
117
|
+
if cookies[:user_session] && session = self.active.where(:token => cookies[:user_session]).first
|
118
|
+
session.controller = controller
|
119
|
+
session
|
120
|
+
else
|
121
|
+
cookies.delete(:user_session)
|
122
|
+
:none
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
# Create a new session and return the newly created session object.
|
127
|
+
# Any other sessions for the browser will be invalidated.
|
128
|
+
def self.start(controller, params = {})
|
129
|
+
cookies = controller.send(:cookies)
|
130
|
+
self.where(:browser_id => cookies[:browser_id]).each(&:invalidate!)
|
131
|
+
session = self.new(params)
|
132
|
+
session.controller = controller
|
133
|
+
session.browser_id = cookies[:browser_id]
|
134
|
+
session.login_at = Time.now
|
135
|
+
session.login_ip = controller.request.ip
|
136
|
+
session.save
|
137
|
+
session
|
138
|
+
end
|
139
|
+
|
140
|
+
# Cleanup any old sessions.
|
141
|
+
def self.cleanup
|
142
|
+
self.active.where("expires_at IS NULL AND last_activity_at < ?", Authie.config.session_inactivity_timeout.ago).each(&:invalidate!)
|
143
|
+
end
|
144
|
+
|
145
|
+
private
|
146
|
+
|
147
|
+
# Return all cookies on the associated controller
|
148
|
+
def cookies
|
149
|
+
controller.send(:cookies)
|
150
|
+
end
|
151
|
+
|
152
|
+
end
|
153
|
+
end
|
metadata
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: authie
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Adam Cooke
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-10-12 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: A Rails library for storing user sessions in a backend database
|
14
|
+
email:
|
15
|
+
- me@adamcooke.io
|
16
|
+
executables: []
|
17
|
+
extensions: []
|
18
|
+
extra_rdoc_files: []
|
19
|
+
files:
|
20
|
+
- db/migrate/20141012174250_create_authie_sessions.rb
|
21
|
+
- lib/authie.rb
|
22
|
+
- lib/authie/config.rb
|
23
|
+
- lib/authie/controller_extension.rb
|
24
|
+
- lib/authie/engine.rb
|
25
|
+
- lib/authie/error.rb
|
26
|
+
- lib/authie/session.rb
|
27
|
+
- lib/authie/version.rb
|
28
|
+
homepage: https://github.com/adamcooke/authie
|
29
|
+
licenses:
|
30
|
+
- MIT
|
31
|
+
metadata: {}
|
32
|
+
post_install_message:
|
33
|
+
rdoc_options: []
|
34
|
+
require_paths:
|
35
|
+
- lib
|
36
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
42
|
+
requirements:
|
43
|
+
- - ">="
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
requirements: []
|
47
|
+
rubyforge_project:
|
48
|
+
rubygems_version: 2.2.2
|
49
|
+
signing_key:
|
50
|
+
specification_version: 4
|
51
|
+
summary: A Rails library for storing user sessions in a backend database
|
52
|
+
test_files: []
|
53
|
+
has_rdoc:
|