guestlist 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,48 @@
1
+ h1. Guestlist
2
+
3
+ Simple authentication using Github credentials.
4
+
5
+ h2. Installation
6
+
7
+ The installation is really simple, just throw this in your @Gemfile@:
8
+
9
+ bc. gem 'guestlist'
10
+
11
+ And run:
12
+
13
+ bc. bundle install
14
+
15
+ Or -- if you're using Rails 2.x -- put this in @config/environment.rb@:
16
+
17
+ bc. config.gem 'guestlist'
18
+
19
+ And run:
20
+
21
+ bc. rake gems:install
22
+
23
+ Include @Guestlist@ in your user model (mine is called @User@):
24
+
25
+ <pre><code>class User
26
+ # It works with ActiveRecord too. ;)
27
+ include MongoMapper::Document
28
+ include Guestlist
29
+
30
+ key :login, String
31
+ key :encrypted_token, String
32
+ end</code></pre>
33
+
34
+ Make sure you have both @login@ and @encrypted_token@ fields in your database if you're using ActiveRecord ("here's a migration":http://gist.github.com/369610), or add some <code>key</code>s to your "MongoMapper":mongomapper.com/ model like in the example above.
35
+
36
+ Believe it or not, you're all set. Let's try it (you can find your token on the "Github account page":https://github.com/account):
37
+
38
+ bc. User.authenticate 'github_login', 'github_token'
39
+
40
+ Guestlist will automatically create a new @User@ for you and return that, or false if you've entered a wrong login or token. The user's token is stored -- yes, encrypted -- , so next time you log in, it'll just authenticate you via the database.
41
+
42
+ h2. Contributing
43
+
44
+ Found any issues? Have a great idea? Want to help? Great! Create an issue "issue":http://github.com/jeffkreeftmeijer/guestlist/issues for it, or even better; "fork the project":http://github.com/jeffkreeftmeijer/guestlist/fork. Pull requests are always welcome. :)
45
+
46
+ h2. License
47
+
48
+ Copyright (c) 2009 Jeff Kreeftmeijer, released under the MIT license
@@ -0,0 +1,28 @@
1
+ require 'guestlist/github'
2
+
3
+ module Guestlist
4
+ module ClassMethods
5
+ def authenticate(login, token)
6
+ attributes = {:login => login, :encrypted_token => encrypt(token)}
7
+
8
+ if user = find_by_login(login)
9
+ return user if user.encrypted_token == attributes[:encrypted_token]
10
+ end
11
+
12
+ if Github.fetch(login, token)
13
+ user.update_attributes(attributes) if user
14
+ user || User.create!(attributes)
15
+ end
16
+ end
17
+
18
+ protected
19
+
20
+ def encrypt(string)
21
+ Digest::SHA1.hexdigest(string)
22
+ end
23
+ end
24
+
25
+ def self.included(base)
26
+ base.extend(ClassMethods)
27
+ end
28
+ end
@@ -0,0 +1,26 @@
1
+ require 'rubygems'
2
+ require 'httparty'
3
+
4
+ module Guestlist
5
+ class Github
6
+ class StatusError < StandardError; end
7
+
8
+ def self.fetch(login, token)
9
+ response = HTTParty.post(
10
+ "http://github.com/api/v2/json/user/show/#{login}",
11
+ {
12
+ :query => {
13
+ :login => login,
14
+ :token => token
15
+ }
16
+ }
17
+ )
18
+
19
+ case response.code
20
+ when 200; response
21
+ when 401; false
22
+ else; raise StatusError, response.code
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,65 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe Guestlist::Github do
4
+ describe '.fetch' do
5
+ before do
6
+ @ok = File.read(
7
+ File.expand_path(
8
+ File.dirname(__FILE__) + '/../stubs/github_200.xml'
9
+ )
10
+ )
11
+ end
12
+
13
+ it 'should call to Github via HTTParty' do
14
+ HTTParty.should_receive(:post).with(
15
+ 'http://github.com/api/v2/json/user/show/login',
16
+ :query => {
17
+ :login => 'login',
18
+ :token => 't0k3n'
19
+ }
20
+ ).and_return(
21
+ HTTParty::Response.new(
22
+ Crack::JSON.parse(@ok), @ok, 200, 'message'
23
+ )
24
+ )
25
+
26
+ Guestlist::Github.fetch('login', 't0k3n')
27
+ end
28
+
29
+ it 'should return a hash with user data' do
30
+ HTTParty.stub!(:post).and_return(
31
+ HTTParty::Response.new(
32
+ Crack::JSON.parse(@ok), @ok, 200, 'message'
33
+ )
34
+ )
35
+
36
+ result = Guestlist::Github.fetch('login', 't0k3n')
37
+ result.should be_instance_of Hash
38
+ result.length.should == 1
39
+ result['user']['name'].should == 'Bob'
40
+ result['user']['blog'].should == 'http://bobsblog.com'
41
+ end
42
+
43
+ it 'should return false when authentication fails' do
44
+ HTTParty.stub!(:post).and_return(
45
+ HTTParty::Response.new(
46
+ {}, '', 401, 'message'
47
+ )
48
+ )
49
+
50
+ Guestlist::Github.fetch('wronglogin', 't3k0n').should == false
51
+ end
52
+
53
+ it 'should raise an error when anything else happens' do
54
+ HTTParty.stub!(:post).and_return(
55
+ HTTParty::Response.new(
56
+ {}, '', 500, 'message'
57
+ )
58
+ )
59
+
60
+ lambda {
61
+ Guestlist::Github.fetch('login', 't0k3n')
62
+ }.should raise_error(Guestlist::Github::StatusError, 500)
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,114 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe Guestlist do
4
+ before do
5
+ @github_200 = Crack::JSON.parse(
6
+ File.read(
7
+ File.expand_path(
8
+ File.dirname(__FILE__) + '/stubs/github_200.xml'
9
+ )
10
+ )
11
+ )
12
+ end
13
+ describe '#authenticate' do
14
+ it 'should call find with the login' do
15
+ User.should_receive(:find_by_login).with('login')
16
+ User.authenticate('login', 'token')
17
+ end
18
+
19
+ describe 'when authenticating an existing user' do
20
+ describe 'with the correct token' do
21
+ it 'should return the user' do
22
+ User.authenticate('exists', 'token').should be_instance_of User
23
+ end
24
+
25
+ it 'should not try to fetch the user' do
26
+ Guestlist::Github.should_not_receive(:fetch)
27
+ User.authenticate('exists', 'token')
28
+ end
29
+
30
+ it 'should not create a new user' do
31
+ User.should_not_receive(:create!)
32
+ User.authenticate('exists', 'token')
33
+ end
34
+ end
35
+
36
+ describe 'with an incorrect token' do
37
+ it 'should not return the user' do
38
+ User.authenticate('exists', 'wrongtoken').should == nil
39
+ end
40
+
41
+ it 'should try to fetch the user' do
42
+ Guestlist::Github.should_receive(:fetch).with('exists', 'wrongtoken')
43
+ User.authenticate('exists', 'wrongtoken')
44
+ end
45
+
46
+ describe 'that seems to be correct after all' do
47
+ before do
48
+ Guestlist::Github.stub!(:fetch).and_return(@github_200)
49
+ end
50
+
51
+ it 'should return the user' do
52
+ User.authenticate('exists', 'newtoken').should be_instance_of User
53
+ end
54
+
55
+ it 'should not create a new user' do
56
+ User.should_not_receive(:create!)
57
+ User.authenticate('exists', 'newtoken')
58
+ end
59
+
60
+ it 'should update the user token' do
61
+ user = User.new
62
+ User.stub(:find_by_login).and_return(user)
63
+ user.should_receive(:update_attributes).with({
64
+ :login => 'exists',
65
+ :encrypted_token => Digest::SHA1.hexdigest('newtoken')
66
+ })
67
+ @user = User.authenticate('exists', 'newtoken')
68
+ end
69
+ end
70
+ end
71
+ end
72
+
73
+ describe 'when authenticating a user that does not exist yet' do
74
+ before do
75
+ User.stub(:find_by_login).and_return(nil)
76
+ Guestlist::Github.stub!(:fetch).and_return(@github_200)
77
+ end
78
+
79
+ it 'should try to fetch the user' do
80
+ Guestlist::Github.should_receive(:fetch).with('doesnt_exist_yet', 'token')
81
+ User.authenticate('doesnt_exist_yet', 'token')
82
+ end
83
+
84
+ it 'should create a new user' do
85
+ User.should_receive(:create!).with({
86
+ :login => 'doesnt_exist_yet',
87
+ :encrypted_token => Digest::SHA1.hexdigest('token')
88
+ })
89
+ User.authenticate('doesnt_exist_yet', 'token')
90
+ end
91
+ end
92
+
93
+ describe 'when authenticating a user that does not exist' do
94
+ before do
95
+ User.stub(:find_by_login).and_return(nil)
96
+ Guestlist::Github.stub!(:fetch).and_return(false)
97
+ end
98
+ it 'should return nil' do
99
+ User.should_receive(:find_by_login).and_return(nil)
100
+ User.authenticate('doesnt_exist', 'token').should == nil
101
+ end
102
+
103
+ it 'should try to fetch the user' do
104
+ Guestlist::Github.should_receive(:fetch).with('doesnt_exist', 'token')
105
+ User.authenticate('doesnt_exist', 'token')
106
+ end
107
+
108
+ it 'should not create a new user' do
109
+ User.should_not_receive(:create!)
110
+ User.authenticate('doesnt_exist', 'token')
111
+ end
112
+ end
113
+ end
114
+ end
@@ -0,0 +1,30 @@
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
2
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
3
+ require 'guestlist'
4
+ require 'spec'
5
+ require 'spec/autorun'
6
+
7
+ require 'crack'
8
+
9
+ Spec::Runner.configure do |config|
10
+ end
11
+
12
+ class User
13
+ include Guestlist
14
+
15
+ def self.find_by_login(*args)
16
+ return new
17
+ end
18
+
19
+ def self.create!(*args)
20
+ return new
21
+ end
22
+
23
+ def encrypted_token
24
+ Digest::SHA1.hexdigest('token')
25
+ end
26
+
27
+ def update_attributes(*args)
28
+ return true
29
+ end
30
+ end
@@ -0,0 +1,28 @@
1
+ {
2
+ "user": {
3
+ "plan": {
4
+ "name":"free",
5
+ "collaborators":0,
6
+ "space":307200,
7
+ "private_repos":0
8
+ },
9
+ "gravatar_id":"f03f4ce7b507aede346263d218228b6a",
10
+ "name":"Bob",
11
+ "company":"c0mp4ny",
12
+ "location":"l0c4ti0n",
13
+ "created_at":"2009/01/01 07:26:12 -0800",
14
+ "collaborators":0,
15
+ "disk_usage":21900,
16
+ "public_gist_count":24,
17
+ "public_repo_count":15,
18
+ "blog":"http://bobsblog.com",
19
+ "following_count":12,
20
+ "id":43621,
21
+ "private_gist_count":5,
22
+ "owned_private_repo_count":0,
23
+ "total_private_repo_count":0,
24
+ "followers_count":14,
25
+ "login":"login",
26
+ "email":"bob@email.com"
27
+ }
28
+ }
metadata ADDED
@@ -0,0 +1,80 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: guestlist
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Jeff Kreeftmeijer
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2010-04-18 00:00:00 +02:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: httparty
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 0.5.2
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: rspec
27
+ type: :development
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 1.3.0
34
+ version:
35
+ description: Simple authentication using Github credentials.
36
+ email: jeff@kreeftmeijer.nl
37
+ executables: []
38
+
39
+ extensions: []
40
+
41
+ extra_rdoc_files: []
42
+
43
+ files:
44
+ - lib/guestlist/github.rb
45
+ - lib/guestlist.rb
46
+ - spec/guestlist/github_spec.rb
47
+ - spec/guestlist_spec.rb
48
+ - spec/spec_helper.rb
49
+ - spec/stubs/github_200.xml
50
+ - README.textile
51
+ has_rdoc: true
52
+ homepage: http://github.com/jeffkreeftmeijer/guestlist
53
+ licenses: []
54
+
55
+ post_install_message:
56
+ rdoc_options: []
57
+
58
+ require_paths:
59
+ - lib
60
+ required_ruby_version: !ruby/object:Gem::Requirement
61
+ requirements:
62
+ - - ">="
63
+ - !ruby/object:Gem::Version
64
+ version: "0"
65
+ version:
66
+ required_rubygems_version: !ruby/object:Gem::Requirement
67
+ requirements:
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ version: "0"
71
+ version:
72
+ requirements: []
73
+
74
+ rubyforge_project:
75
+ rubygems_version: 1.3.5
76
+ signing_key:
77
+ specification_version: 3
78
+ summary: Simple authentication using Github credentials.
79
+ test_files: []
80
+