devise_session_limit 0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE +22 -0
- data/README.md +55 -0
- data/Rakefile +2 -0
- data/devise_session_limit.gemspec +17 -0
- data/lib/devise_session_limit.rb +1 -0
- data/lib/devise_session_limit/hooks/session_limit.rb +30 -0
- data/lib/devise_session_limit/models/session_limit.rb +26 -0
- data/lib/devise_session_limit/path_checker.rb +23 -0
- data/lib/devise_session_limit/version.rb +3 -0
- metadata +54 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 93afd6a31d5d33d4a2936096580ee0fb9906d938
|
4
|
+
data.tar.gz: 7323e3d825bce6c828d1cf60fd0281bdb3f8fdfc
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: fa71d82c30a187b6dc20210066b58071f86b452cfb8471ccb7ff0c5d5bfd52166a96806e7f2ee977273d87017b508015d5935522cefdd2be86d005e96a778c6b
|
7
|
+
data.tar.gz: afbf011dbd3151920faac2342586cce406686b213b397f643ad346771dcacdbf58693a014c271e93d5f1d3c4da865515c89c802ce800e927a7298ad93499f2b0
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2012 Adrien Jarthon
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
# DeviseSessionLimit
|
2
|
+
|
3
|
+
Devise plugin preventing a user from having multiple open sessions
|
4
|
+
|
5
|
+
Using code from [https://github.com/phatworx/devise_security_extension](devise_security_extension)
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
Add this line to your application's Gemfile:
|
10
|
+
|
11
|
+
gem 'devise_session_limit'
|
12
|
+
|
13
|
+
And then execute:
|
14
|
+
|
15
|
+
$ bundle
|
16
|
+
|
17
|
+
Or install it yourself as:
|
18
|
+
|
19
|
+
$ gem install devise_session_limit
|
20
|
+
|
21
|
+
## Usage
|
22
|
+
|
23
|
+
In your `User` model:
|
24
|
+
|
25
|
+
class User
|
26
|
+
|
27
|
+
# Additional field
|
28
|
+
field :unique_session_id, :type => String
|
29
|
+
|
30
|
+
# Additional devise module
|
31
|
+
devise ..., :session_limit
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
Add some translation key for the error message:
|
36
|
+
|
37
|
+
en:
|
38
|
+
devise:
|
39
|
+
failure:
|
40
|
+
session_limited: "You are already signed in from another place"
|
41
|
+
|
42
|
+
## Customize
|
43
|
+
|
44
|
+
You can customize the behaviour from the `User` model by overriding or chaining this two methods:
|
45
|
+
|
46
|
+
# Called at each sign in
|
47
|
+
def update_unique_session_id!(unique_session_id)
|
48
|
+
self.unique_session_id = unique_session_id
|
49
|
+
save(:validate => false)
|
50
|
+
end
|
51
|
+
|
52
|
+
# Called at each request, you can override to implement your own behaviour
|
53
|
+
def check_unique_session_id session_id
|
54
|
+
self.unique_session_id == session_id
|
55
|
+
end
|
data/Rakefile
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/devise_session_limit/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.authors = ["Adrien Jarthon"]
|
6
|
+
gem.email = ["adrien.jarthon@dimelo.com"]
|
7
|
+
gem.description = %q{Devise plugin preventing a user from having multiple open sessions}
|
8
|
+
gem.summary = %q{Devise plugin preventing a user from having multiple open sessions}
|
9
|
+
gem.homepage = "https://github.com/dimelo/devise_session_limit"
|
10
|
+
|
11
|
+
gem.files = `git ls-files`.split($\)
|
12
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
13
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
14
|
+
gem.name = "devise_session_limit"
|
15
|
+
gem.require_paths = ["lib"]
|
16
|
+
gem.version = DeviseSessionLimit::VERSION
|
17
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
Devise.add_module :session_limit, :model => 'devise_session_limit/models/session_limit'
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'devise_session_limit/path_checker' if not defined? Devise::PathChecker
|
2
|
+
|
3
|
+
# After each sign in, update unique_session_id.
|
4
|
+
# This is only triggered when the user is explicitly set (with set_user)
|
5
|
+
# and on authentication. Retrieving the user from session (:fetch) does
|
6
|
+
# not trigger it.
|
7
|
+
Warden::Manager.after_set_user :except => :fetch do |record, warden, options|
|
8
|
+
if record.respond_to?(:update_unique_session_id!) and warden.authenticated?(options[:scope])
|
9
|
+
unique_session_id = Devise.friendly_token
|
10
|
+
warden.session(options[:scope])['unique_session_id'] = unique_session_id
|
11
|
+
record.update_unique_session_id!(unique_session_id)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
# Each time a record is fetched from session we check if a new session from another
|
16
|
+
# browser was opened for the record or not, based on a unique session identifier.
|
17
|
+
# If so, the old account is logged out and redirected to the sign in page on the next request.
|
18
|
+
Warden::Manager.after_set_user :only => :fetch do |record, warden, options|
|
19
|
+
scope = options[:scope]
|
20
|
+
|
21
|
+
if record.respond_to?(:check_unique_session_id) and warden.authenticated?(scope)
|
22
|
+
unless record.check_unique_session_id(warden.session(scope)['unique_session_id'])
|
23
|
+
path_checker = Devise::PathChecker.new(warden.env, scope)
|
24
|
+
unless path_checker.signing_out?
|
25
|
+
warden.logout(scope)
|
26
|
+
throw :warden, :scope => scope, :message => :session_limited
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'devise_session_limit/hooks/session_limit'
|
2
|
+
|
3
|
+
module Devise
|
4
|
+
module Models
|
5
|
+
# Ensures that there is only one session usable per account at once.
|
6
|
+
# If someone logs in, and some other is logging in with the same credentials,
|
7
|
+
# the session from the first one is invalidated and not usable anymore.
|
8
|
+
# The first one is redirected to the sign page with a message, telling that
|
9
|
+
# someone used his credentials to sign in.
|
10
|
+
module SessionLimit
|
11
|
+
extend ActiveSupport::Concern
|
12
|
+
|
13
|
+
# Called at each sign in
|
14
|
+
def update_unique_session_id!(unique_session_id)
|
15
|
+
self.unique_session_id = unique_session_id
|
16
|
+
save(:validate => false)
|
17
|
+
end
|
18
|
+
|
19
|
+
# Called at each request, you can override to implement your own behaviour
|
20
|
+
def check_unique_session_id session_id
|
21
|
+
self.unique_session_id == session_id
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Devise
|
2
|
+
class PathChecker
|
3
|
+
include Rails.application.routes.url_helpers
|
4
|
+
|
5
|
+
def self.default_url_options(*args)
|
6
|
+
if defined?(ApplicationController)
|
7
|
+
ApplicationController.default_url_options(*args)
|
8
|
+
else
|
9
|
+
{}
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def initialize(env, scope)
|
14
|
+
@current_path = "/#{env["SCRIPT_NAME"]}/#{env["PATH_INFO"]}".squeeze("/")
|
15
|
+
@scope = scope
|
16
|
+
end
|
17
|
+
|
18
|
+
def signing_out?
|
19
|
+
route = "destroy_#{@scope}_session_path"
|
20
|
+
respond_to?(route) && @current_path == send(route)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
metadata
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: devise_session_limit
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: '0.2'
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Adrien Jarthon
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-10-31 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: Devise plugin preventing a user from having multiple open sessions
|
14
|
+
email:
|
15
|
+
- adrien.jarthon@dimelo.com
|
16
|
+
executables: []
|
17
|
+
extensions: []
|
18
|
+
extra_rdoc_files: []
|
19
|
+
files:
|
20
|
+
- ".gitignore"
|
21
|
+
- Gemfile
|
22
|
+
- LICENSE
|
23
|
+
- README.md
|
24
|
+
- Rakefile
|
25
|
+
- devise_session_limit.gemspec
|
26
|
+
- lib/devise_session_limit.rb
|
27
|
+
- lib/devise_session_limit/hooks/session_limit.rb
|
28
|
+
- lib/devise_session_limit/models/session_limit.rb
|
29
|
+
- lib/devise_session_limit/path_checker.rb
|
30
|
+
- lib/devise_session_limit/version.rb
|
31
|
+
homepage: https://github.com/dimelo/devise_session_limit
|
32
|
+
licenses: []
|
33
|
+
metadata: {}
|
34
|
+
post_install_message:
|
35
|
+
rdoc_options: []
|
36
|
+
require_paths:
|
37
|
+
- lib
|
38
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
39
|
+
requirements:
|
40
|
+
- - ">="
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: '0'
|
43
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
requirements: []
|
49
|
+
rubyforge_project:
|
50
|
+
rubygems_version: 2.4.2
|
51
|
+
signing_key:
|
52
|
+
specification_version: 4
|
53
|
+
summary: Devise plugin preventing a user from having multiple open sessions
|
54
|
+
test_files: []
|