sinatra-authentication-oran 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +33 -0
- data/History.txt +4 -0
- data/Manifest +26 -0
- data/Rakefile +43 -0
- data/TODO +53 -0
- data/UNLICENSE +24 -0
- data/example/database.yml +3 -0
- data/example/dm_extend_app.rb +26 -0
- data/example/dm_sinbook.rb +56 -0
- data/example/extend_views/edit.haml +42 -0
- data/example/extend_views/index.haml +31 -0
- data/example/extend_views/login.haml +21 -0
- data/example/extend_views/show.haml +9 -0
- data/example/extend_views/signup.haml +30 -0
- data/example/mm_app.rb +22 -0
- data/example/tc_app.rb +16 -0
- data/example/tc_sinbook.rb +62 -0
- data/lib/models/abstract_user.rb +95 -0
- data/lib/models/activerecord_user.rb +56 -0
- data/lib/models/ar_adapter.rb +66 -0
- data/lib/models/datamapper_user.rb +43 -0
- data/lib/models/dm_adapter.rb +61 -0
- data/lib/models/mm_adapter.rb +65 -0
- data/lib/models/mongoid_adapter.rb +67 -0
- data/lib/models/mongoid_user.rb +42 -0
- data/lib/models/mongomapper_user.rb +38 -0
- data/lib/models/rufus_tokyo_user.rb +206 -0
- data/lib/models/sequel_adapter.rb +68 -0
- data/lib/models/sequel_user.rb +53 -0
- data/lib/models/tc_adapter.rb +101 -0
- data/lib/sinatra-authentication-o.rb +305 -0
- data/lib/sinatra-authentication.rb +305 -0
- data/lib/sinatra-authentication/models.rb +5 -0
- data/lib/views/edit.haml +45 -0
- data/lib/views/edit.slim +46 -0
- data/lib/views/index.haml +29 -0
- data/lib/views/index.slim +30 -0
- data/lib/views/login.haml +24 -0
- data/lib/views/login.slim +25 -0
- data/lib/views/show.haml +9 -0
- data/lib/views/show.slim +10 -0
- data/lib/views/signup.haml +28 -0
- data/lib/views/signup.slim +33 -0
- data/readme.markdown +295 -0
- data/sinatra-authentication-oran.gemspec +137 -0
- data/spec/run_all_specs.rb +8 -0
- data/spec/unit/ar_model_spec.rb +3 -0
- data/spec/unit/dm_model_spec.rb +3 -0
- data/spec/unit/mm_model_spec.rb +3 -0
- data/spec/unit/mongoid_model_spec.rb +3 -0
- data/spec/unit/sequel_model_spec.rb +10 -0
- data/spec/unit/tc_model_spec.rb +3 -0
- data/spec/unit/user_specs.rb +119 -0
- data/test/activerecord_test.rb +5 -0
- data/test/datamapper_test.rb +5 -0
- data/test/lib/ar_app.rb +27 -0
- data/test/lib/dm_app.rb +20 -0
- data/test/lib/dm_extend_app.rb +27 -0
- data/test/lib/dm_sinbook.rb +54 -0
- data/test/lib/extend_views/edit.haml +46 -0
- data/test/lib/extend_views/index.haml +31 -0
- data/test/lib/extend_views/login.haml +21 -0
- data/test/lib/extend_views/show.haml +9 -0
- data/test/lib/extend_views/signup.haml +29 -0
- data/test/lib/helper.rb +16 -0
- data/test/lib/mm_app.rb +24 -0
- data/test/lib/mongoid_app.rb +28 -0
- data/test/lib/sequel_app.rb +21 -0
- data/test/lib/tc_app.rb +17 -0
- data/test/lib/tc_sinbook.rb +61 -0
- data/test/mongoid_test.rb +5 -0
- data/test/mongomapper_test.rb +40 -0
- data/test/route_tests.rb +29 -0
- data/test/rufus_tokyo_test.rb +5 -0
- data/test/sequel_test.rb +5 -0
- metadata +220 -0
data/example/tc_app.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'sinatra'
|
3
|
+
require 'haml'
|
4
|
+
require 'rufus/tokyo'
|
5
|
+
require 'sinatra-authentication'
|
6
|
+
|
7
|
+
use Rack::Session::Cookie, :secret => "heyhihello"
|
8
|
+
TcUserTable.cabinet_path = File.dirname(__FILE__)
|
9
|
+
|
10
|
+
set :environment, 'development'
|
11
|
+
set :public, 'public'
|
12
|
+
set :views, 'views'
|
13
|
+
|
14
|
+
get '/' do
|
15
|
+
haml "= render_login_logout", :layout => :layout
|
16
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'haml'
|
3
|
+
require 'sinbook'
|
4
|
+
require 'rufus/tokyo'
|
5
|
+
require 'sinatra'
|
6
|
+
require 'sinatra-authentication'
|
7
|
+
|
8
|
+
use Rack::Session::Cookie, :secret => "heyhihello"
|
9
|
+
TcUserTable.cabinet_path = File.dirname(__FILE__)
|
10
|
+
|
11
|
+
facebook do
|
12
|
+
api_key 'aa2db1b96cb7b57f0c5b1d4d3d8f0a22'
|
13
|
+
secret '21d94ee63969ae3b3f833689838ca00f'
|
14
|
+
app_id 48652736613
|
15
|
+
url 'peoplewithjetpacks.com:4568/'
|
16
|
+
callback 'peoplewithjetpacks.com:4568/'
|
17
|
+
end
|
18
|
+
|
19
|
+
set :port, 4568
|
20
|
+
|
21
|
+
get '/' do
|
22
|
+
haml :main
|
23
|
+
end
|
24
|
+
|
25
|
+
get '/test' do
|
26
|
+
login_required
|
27
|
+
'hihihi'
|
28
|
+
end
|
29
|
+
|
30
|
+
__END__
|
31
|
+
|
32
|
+
@@ layout
|
33
|
+
%html{:xmlns=>"http://www.w3.org/1999/xhtml", :'xmlns:fb'=>"http://www.facebook.com/2008/fbml"}
|
34
|
+
%head
|
35
|
+
%title Welcome to my Facebook Connect website!
|
36
|
+
%script{:type => 'text/javascript', :src => 'http://static.ak.connect.facebook.com/js/api_lib/v0.4/FeatureLoader.js.php/en_US'}
|
37
|
+
%script{:type => 'text/javascript', :src => 'http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js'}
|
38
|
+
:javascript
|
39
|
+
$(document).ready(function(){
|
40
|
+
/* test facebook crap works with ajax */
|
41
|
+
$('.sinatra-authentication-login').click(function(){
|
42
|
+
$.get($(this).attr('href'), {}, function(data){
|
43
|
+
$('#test_box').html(data);
|
44
|
+
});
|
45
|
+
return false;
|
46
|
+
});
|
47
|
+
});
|
48
|
+
%body
|
49
|
+
= render_login_logout
|
50
|
+
= yield
|
51
|
+
:javascript
|
52
|
+
FB.init("#{fb.api_key}", "/receiver")
|
53
|
+
#test_box
|
54
|
+
|
55
|
+
@@ main
|
56
|
+
- if fb[:user]
|
57
|
+
Hi,
|
58
|
+
%fb:profile-pic{:uid => fb[:user]}
|
59
|
+
%fb:name{:uid => fb[:user], :useyou => 'false', :firstnameonly => 'true'}
|
60
|
+
!
|
61
|
+
%br/
|
62
|
+
|
@@ -0,0 +1,95 @@
|
|
1
|
+
current_path = File.expand_path("..", __FILE__)
|
2
|
+
if Object.const_defined?("DataMapper")
|
3
|
+
#require 'dm-core'
|
4
|
+
require 'dm-timestamps'
|
5
|
+
require 'dm-validations'
|
6
|
+
require File.join(current_path, 'datamapper_user')
|
7
|
+
require File.join(current_path, 'dm_adapter')
|
8
|
+
elsif Object.const_defined?("Rufus") && Rufus.const_defined?("Tokyo")
|
9
|
+
require File.join(current_path, 'rufus_tokyo_user')
|
10
|
+
require File.join(current_path, 'tc_adapter')
|
11
|
+
elsif Object.const_defined?("MongoMapper")
|
12
|
+
require File.join(current_path, 'mongomapper_user')
|
13
|
+
require File.join(current_path, 'mm_adapter')
|
14
|
+
elsif Object.const_defined?("Sequel")
|
15
|
+
require File.join(current_path, 'sequel_user')
|
16
|
+
require File.join(current_path, 'sequel_adapter')
|
17
|
+
elsif Object.const_defined?("Mongoid")
|
18
|
+
require File.join(current_path, 'mongoid_user')
|
19
|
+
require File.join(current_path, 'mongoid_adapter')
|
20
|
+
end
|
21
|
+
|
22
|
+
class User
|
23
|
+
if Object.const_defined?("DataMapper")
|
24
|
+
include DmAdapter
|
25
|
+
elsif Object.const_defined?("Rufus")
|
26
|
+
include TcAdapter
|
27
|
+
elsif Object.const_defined?("MongoMapper")
|
28
|
+
include MmAdapter
|
29
|
+
elsif Object.const_defined?("Sequel")
|
30
|
+
include SequelAdapter
|
31
|
+
elsif Object.const_defined?("Mongoid")
|
32
|
+
include MongoidAdapter
|
33
|
+
elsif Object.const_defined?("ActiveRecord")
|
34
|
+
include ArAdapter
|
35
|
+
else
|
36
|
+
throw "you need to require either 'dm-core', 'mongo_mapper', 'sequel', 'mongoid', or 'rufus-tokyo' for sinatra-authentication to work"
|
37
|
+
end
|
38
|
+
|
39
|
+
def initialize(interfacing_class_instance)
|
40
|
+
@instance = interfacing_class_instance
|
41
|
+
end
|
42
|
+
|
43
|
+
def id
|
44
|
+
@instance.id
|
45
|
+
end
|
46
|
+
|
47
|
+
def self.authenticate(email, pass)
|
48
|
+
current_user = get(:email => email)
|
49
|
+
return nil if current_user.nil?
|
50
|
+
return current_user if User.encrypt(pass, current_user.salt) == current_user.hashed_password
|
51
|
+
nil
|
52
|
+
end
|
53
|
+
|
54
|
+
def db_instance
|
55
|
+
@instance
|
56
|
+
end
|
57
|
+
|
58
|
+
protected
|
59
|
+
|
60
|
+
def self.encrypt(pass, salt)
|
61
|
+
Digest::SHA1.hexdigest(pass+salt)
|
62
|
+
end
|
63
|
+
|
64
|
+
def self.random_string(len)
|
65
|
+
#generate a random password consisting of strings and digits
|
66
|
+
chars = ("a".."z").to_a + ("A".."Z").to_a + ("0".."9").to_a
|
67
|
+
newpass = ""
|
68
|
+
1.upto(len) { |i| newpass << chars[rand(chars.size-1)] }
|
69
|
+
return newpass
|
70
|
+
end
|
71
|
+
|
72
|
+
#def self.page_limit
|
73
|
+
# 20
|
74
|
+
#end
|
75
|
+
|
76
|
+
#def self.page_offset(page = 0)
|
77
|
+
# page.to_i * self.page_limit
|
78
|
+
#end
|
79
|
+
end
|
80
|
+
|
81
|
+
class Hash
|
82
|
+
def stringify
|
83
|
+
inject({}) do |options, (key, value)|
|
84
|
+
options[key.to_s] = value.to_s
|
85
|
+
options
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def stringify!
|
90
|
+
each do |key, value|
|
91
|
+
delete(key)
|
92
|
+
store(key.to_s, value.to_s)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
unless ActiveRecord::Base.connection.table_exists?("ar_users")
|
2
|
+
class CreateArUsers < ActiveRecord::Migration
|
3
|
+
def self.up
|
4
|
+
create_table :ar_users do |t|
|
5
|
+
t.string :email
|
6
|
+
t.string :hashed_password
|
7
|
+
t.string :salt
|
8
|
+
t.integer :permission_level
|
9
|
+
t.string :fb_uid
|
10
|
+
|
11
|
+
t.timestamps
|
12
|
+
end
|
13
|
+
|
14
|
+
add_index :ar_users, :email, :unique => true
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.down
|
18
|
+
remove_index :ar_users, :email
|
19
|
+
drop_table :ar_users
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
CreateArUsers.up
|
24
|
+
end
|
25
|
+
|
26
|
+
#require 'logger'
|
27
|
+
#ActiveRecord::Base.logger = Logger.new(STDOUT)
|
28
|
+
|
29
|
+
class ArUser < ActiveRecord::Base
|
30
|
+
|
31
|
+
attr_accessor :password, :password_confirmation
|
32
|
+
|
33
|
+
validates_format_of :email, :with => /(\A(\s*)\Z)|(\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z)/i
|
34
|
+
validates_uniqueness_of :email
|
35
|
+
validates_presence_of :password_confirmation, :unless => Proc.new { |t| t.hashed_password }
|
36
|
+
validates_presence_of :password, :unless => Proc.new { |t| t.hashed_password }
|
37
|
+
validates_confirmation_of :password
|
38
|
+
|
39
|
+
def password=(pass)
|
40
|
+
@password = pass
|
41
|
+
self.salt = User.random_string(10) if !self.salt
|
42
|
+
self.hashed_password = User.encrypt(@password, self.salt)
|
43
|
+
end
|
44
|
+
|
45
|
+
def admin?
|
46
|
+
self.permission_level == -1 || self.id == 1
|
47
|
+
end
|
48
|
+
|
49
|
+
def site_admin?
|
50
|
+
self.id == 1
|
51
|
+
end
|
52
|
+
|
53
|
+
def to_ary
|
54
|
+
self.attributes.values
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
module ArAdapter
|
2
|
+
def self.included(base)
|
3
|
+
base.extend ClassMethods
|
4
|
+
base.class_eval { include ArAdapter::InstanceMethods }
|
5
|
+
end
|
6
|
+
|
7
|
+
module ClassMethods
|
8
|
+
#pass all args to this
|
9
|
+
def all
|
10
|
+
result = ArUser.all(:order => ["created_at DESC"])
|
11
|
+
result.collect {|instance| self.new instance}
|
12
|
+
end
|
13
|
+
|
14
|
+
def get(hash)
|
15
|
+
if user = ArUser.where(hash).first
|
16
|
+
self.new user
|
17
|
+
else
|
18
|
+
nil
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def set(attributes)
|
23
|
+
user = ArUser.new attributes
|
24
|
+
user.save
|
25
|
+
self.new user
|
26
|
+
end
|
27
|
+
|
28
|
+
def set!(attributes)
|
29
|
+
user = ArUser.new attributes
|
30
|
+
user.save!
|
31
|
+
self.new user
|
32
|
+
end
|
33
|
+
|
34
|
+
def delete(pk)
|
35
|
+
user = ArUser.first(pk).first
|
36
|
+
user.destroy
|
37
|
+
user.destroyed?
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
module InstanceMethods
|
42
|
+
def valid
|
43
|
+
@instance.valid?
|
44
|
+
end
|
45
|
+
|
46
|
+
def errors
|
47
|
+
@instance.errors.collect do |k,v|
|
48
|
+
"#{k} #{v}"
|
49
|
+
end.join(', ')
|
50
|
+
end
|
51
|
+
|
52
|
+
def update(attributes)
|
53
|
+
@instance.update_attributes attributes
|
54
|
+
#self
|
55
|
+
end
|
56
|
+
|
57
|
+
def saved
|
58
|
+
@instance.valid?
|
59
|
+
end
|
60
|
+
|
61
|
+
def method_missing(meth, *args, &block)
|
62
|
+
#cool I just found out * on an array turns the array into a list of args for a function
|
63
|
+
@instance.send(meth, *args, &block)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
class DmUser
|
2
|
+
include DataMapper::Resource
|
3
|
+
|
4
|
+
property :id, Serial
|
5
|
+
property :email, String, :length => (5..40), :unique => true, :format => :email_address
|
6
|
+
property :hashed_password, String
|
7
|
+
property :salt, String
|
8
|
+
#Was DateTime should be DateTime?
|
9
|
+
property :created_at, Time
|
10
|
+
property :permission_level, Integer, :default => 1
|
11
|
+
if Sinatra.const_defined?('FacebookObject')
|
12
|
+
property :fb_uid, String
|
13
|
+
end
|
14
|
+
|
15
|
+
attr_accessor :password, :password_confirmation
|
16
|
+
#protected equievelant? :protected => true doesn't exist in dm 0.10.0
|
17
|
+
#protected :id, :salt
|
18
|
+
#doesn't behave correctly, I'm not even sure why I did this.
|
19
|
+
|
20
|
+
validates_presence_of :password_confirmation, :unless => Proc.new { |t| t.hashed_password }
|
21
|
+
validates_presence_of :password, :unless => Proc.new { |t| t.hashed_password }
|
22
|
+
validates_confirmation_of :password
|
23
|
+
|
24
|
+
def password=(pass)
|
25
|
+
@password = pass
|
26
|
+
self.salt = User.random_string(10) if !self.salt
|
27
|
+
self.hashed_password = User.encrypt(@password, self.salt)
|
28
|
+
end
|
29
|
+
|
30
|
+
def admin?
|
31
|
+
self.permission_level == -1 || self.id == 1
|
32
|
+
end
|
33
|
+
|
34
|
+
def site_admin?
|
35
|
+
self.id == 1
|
36
|
+
end
|
37
|
+
|
38
|
+
protected
|
39
|
+
|
40
|
+
def method_missing(m, *args)
|
41
|
+
return false
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
module DmAdapter
|
2
|
+
def self.included(base)
|
3
|
+
base.extend ClassMethods
|
4
|
+
base.class_eval { include DmAdapter::InstanceMethods }
|
5
|
+
end
|
6
|
+
|
7
|
+
module ClassMethods
|
8
|
+
#pass all args to this
|
9
|
+
def all
|
10
|
+
result = DmUser.all(:order => [:created_at.desc])
|
11
|
+
result.collect {|instance| self.new instance}
|
12
|
+
end
|
13
|
+
|
14
|
+
def get(hash)
|
15
|
+
if user = DmUser.first(hash)
|
16
|
+
self.new user
|
17
|
+
else
|
18
|
+
nil
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def set(attributes)
|
23
|
+
user = DmUser.new attributes
|
24
|
+
user.save
|
25
|
+
self.new user
|
26
|
+
end
|
27
|
+
|
28
|
+
def set!(attributes)
|
29
|
+
user = DmUser.new attributes
|
30
|
+
user.save!
|
31
|
+
self.new user
|
32
|
+
end
|
33
|
+
|
34
|
+
def delete(pk)
|
35
|
+
user = DmUser.first(:id => pk)
|
36
|
+
user.destroy
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
module InstanceMethods
|
41
|
+
def valid
|
42
|
+
@instance.valid?
|
43
|
+
end
|
44
|
+
|
45
|
+
def errors
|
46
|
+
@instance.errors.collect do |k,v|
|
47
|
+
"#{k} #{v}"
|
48
|
+
end.join(', ')
|
49
|
+
end
|
50
|
+
|
51
|
+
def update(attributes)
|
52
|
+
@instance.update attributes
|
53
|
+
#self
|
54
|
+
end
|
55
|
+
|
56
|
+
def method_missing(meth, *args, &block)
|
57
|
+
#cool I just found out * on an array turns the array into a list of args for a function
|
58
|
+
@instance.send(meth, *args, &block)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
module MmAdapter
|
2
|
+
def self.included(base)
|
3
|
+
base.extend ClassMethods
|
4
|
+
base.class_eval { include MmAdapter::InstanceMethods }
|
5
|
+
end
|
6
|
+
|
7
|
+
module ClassMethods
|
8
|
+
def all
|
9
|
+
result = MmUser.all(:order => 'created_at desc')
|
10
|
+
result.collect {|instance| self.new instance}
|
11
|
+
end
|
12
|
+
|
13
|
+
def get(hash)
|
14
|
+
if user = MmUser.first(hash)
|
15
|
+
self.new user
|
16
|
+
else
|
17
|
+
nil
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def set(attributes)
|
22
|
+
#puts attributes.inspect
|
23
|
+
user = MmUser.new attributes
|
24
|
+
user.id = nil unless user.save
|
25
|
+
self.new user
|
26
|
+
end
|
27
|
+
|
28
|
+
def set!(attributes)
|
29
|
+
user = MmUser.new attributes
|
30
|
+
user.save(:validate => false)
|
31
|
+
self.new user
|
32
|
+
end
|
33
|
+
|
34
|
+
def delete(pk)
|
35
|
+
user = MmUser.first(:id => pk)
|
36
|
+
#returns nil on success. Is this correct? Will it return something else on failure?
|
37
|
+
user.destroy
|
38
|
+
user.destroyed?
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
module InstanceMethods
|
43
|
+
def valid
|
44
|
+
@instance.valid?
|
45
|
+
end
|
46
|
+
|
47
|
+
def update(attributes)
|
48
|
+
@instance.update_attributes attributes
|
49
|
+
@instance.save
|
50
|
+
end
|
51
|
+
|
52
|
+
def saved
|
53
|
+
@instance.valid?
|
54
|
+
end
|
55
|
+
|
56
|
+
def errors
|
57
|
+
@instance.errors.full_messages.join(', ')
|
58
|
+
end
|
59
|
+
|
60
|
+
def method_missing(meth, *args, &block)
|
61
|
+
#cool I just found out * on an array turns the array into a list of args for a function
|
62
|
+
@instance.send(meth, *args, &block)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|