aurora 0.0.1 → 0.1.10

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,13 @@
1
+ class CreateUsers < Sequel::Migration
2
+ def up
3
+ create_table :users do
4
+ primary_key :id
5
+ varchar :username, :size => 16, :unique => true, :null => false
6
+ varchar :password, :size => 32, :null => false
7
+ text :permissions, :null => false
8
+ end
9
+ end
10
+ def down
11
+ execute 'DROP TABLE users'
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ class CreateTokens < Sequel::Migration
2
+ def up
3
+ create_table :tokens do
4
+ primary_key :id
5
+ varchar :username, :size => 16, :null => false
6
+ varchar :token, :size => 32, :null => false
7
+ datetime :expires_at, :null => false
8
+ end
9
+ end
10
+ def down
11
+ execute 'DROP TABLE tokens'
12
+ end
13
+ end
@@ -1,26 +1,274 @@
1
- $:.unshift File.dirname(__FILE__)
2
-
1
+ #!/usr/bin/env ruby
3
2
  #--
4
- # Created by Matt Todd on 2007-11-10.
5
- # Copyright (c) 2007 The HUB, Clayton State University. All rights reserved.
3
+ # Created by Matt Todd on 2008-01-11.
4
+ # Copyright (c) 2008. All rights reserved.
6
5
  #++
7
6
 
7
+ $:.unshift File.dirname(File.join('..', __FILE__))
8
+ $:.unshift File.dirname(__FILE__)
9
+
8
10
  #--
9
- # Dependencies
11
+ # dependencies
10
12
  #++
11
13
 
12
- require 'rubygems'
13
- require 'logger'
14
- require 'uri'
15
- require 'json'
16
- require 'digest/md5'
17
- require 'mongrel'
14
+ %w(rubygems aurora halcyon/server sequel digest/md5).each {|dep|require dep}
18
15
 
19
16
  #--
20
- # Module
17
+ # module
21
18
  #++
22
19
 
23
- require 'server/base'
24
- require 'server/server'
25
- require 'server/handler'
26
- require 'server/token'
20
+ module Aurora
21
+
22
+ # = Aurora Server
23
+ #
24
+ # The Aurora Server handles user authentication requests, token creation and
25
+ # management, and permissions querying and verification.
26
+ #
27
+ # == Usage
28
+ #
29
+ # class Aurora::Server
30
+ # def authenticate(username, password)
31
+ # username == 'test' && password == 'secret'
32
+ # end
33
+ # end
34
+ #
35
+ # This will define an authentication processor for verifying users'
36
+ # authenticity. This method is only defaulted to when token authentication
37
+ # is not able to be used (such as for creating sessions), so its use should
38
+ # be minimized by token authentication.
39
+ class Server < Halcyon::Server::Base
40
+
41
+ def self.version
42
+ VERSION.join('.')
43
+ end
44
+
45
+ route do |r|
46
+ # authentication routes
47
+ r.match('/user/auth/:username').to(:module => 'user', :action => 'auth')
48
+ r.match('/token/auth/:token').to(:module => 'token', :action => 'auth')
49
+
50
+ # user routes
51
+ r.match('/user/show/:username').to(:module => 'user', :action => 'show')
52
+
53
+ # token routes
54
+ r.match('/token/destroy/:token').to(:module => 'token', :action => 'destroy')
55
+
56
+ # permission routes
57
+ r.match('/user/:username/:app/permissions').to(:module => 'user', :action => 'permisisons')
58
+ r.match('/user/:username/:app/permit/:permission').to(:module => 'user', :action => 'permit')
59
+
60
+ # generic
61
+ r.match('/:module/:action/:id').to()
62
+ r.match('/:module/:action').to()
63
+ r.match('/:action/:id').to()
64
+ r.match('/:action').to()
65
+
66
+ # failover
67
+ {:action => 'unauthorized'}
68
+ end
69
+
70
+ # Makes sure the Database server connection is created, tables migrated,
71
+ # and other tasks.
72
+ def startup
73
+ # TODO: setup startup tasks
74
+
75
+ # connect to database
76
+ host = credentials = ''
77
+ host = "#{@config[:db][:host]}/" unless @config[:db][:host].nil?
78
+ credentials = "#{@config[:db][:username]}:#{@config[:db][:password]}@" unless @config[:db][:username].nil?
79
+ @db = Sequel("#{@config[:db][:adapter]}://#{credentials}#{host}#{@config[:db][:database]}")
80
+ @logger.info 'Connected to Database.'
81
+
82
+ # run migrations if version is outdated
83
+ current_version = Sequel::Migrator.get_current_migration_version(@db)
84
+ latest_version = Sequel::Migrator.apply(@db, File.join(File.dirname(__FILE__),'migrations'))
85
+ @logger.info 'Migrations loaded!' if current_version < latest_version
86
+
87
+ # clean expired sessions/tokens
88
+ expire_tokens
89
+ @logger.info 'Expired sessions/tokens removed.'
90
+ end
91
+
92
+ # = User Module
93
+ #
94
+ # User actions, including authentication, permissions testing and
95
+ # management, and data querying.
96
+ user do
97
+
98
+ #--
99
+ # Authentication
100
+ #++
101
+
102
+ # Calls the supplied authentication method. Creates a token on success,
103
+ # returning that token, and raises Unauthorized on failure.
104
+ def auth
105
+ username, password = params[:username], @req.POST['password']
106
+ if authenticate(username, password)
107
+ # authenticated
108
+
109
+ # generate token and expiration date
110
+ token = Digest::MD5.hexdigest("#{username}:#{password}:#{Time.now.to_s}")
111
+ expiration = generate_expiration
112
+
113
+ # save to the DB
114
+ @db[:tokens].filter(:username => username).delete # removes previous tokens
115
+ @db[:tokens] << {:username => username, :token => token, :expires_at => expiration}
116
+
117
+ # create the user if not already in the DB
118
+ if @db[:users].filter(:username => username).empty?
119
+ # retrieve the new user permissions
120
+ permissions = initialize_permissions(username)
121
+
122
+ # create a new user
123
+ @db[:users] << {:username => username, :password => Digest::MD5.hexdigest(password), :permissions => permissions.to_json}
124
+ @logger.info "#{username} cached."
125
+ else
126
+ # or just cache the password so the user's profile is up-to-date
127
+ # if the authentication source is not available
128
+ @db[:users].filter(:username => username).update(:password => Digest::MD5.hexdigest(password))
129
+ @logger.debug "#{username} updated."
130
+ end
131
+
132
+ # return success with token for client
133
+ ok(token)
134
+ else
135
+ # failed authentication
136
+ raise Exceptions::Unauthorized.new
137
+ end
138
+ end
139
+
140
+ #--
141
+ # General
142
+ #++
143
+
144
+ # Show user data.
145
+ def show
146
+ # TODO: consider removing as potentially unsafe
147
+ end
148
+
149
+ #--
150
+ # Permissions
151
+ #++
152
+
153
+ # Request the full permissions of a given user
154
+ def permissions
155
+ # TODO: consider removing as potentially unsafe
156
+ # (in the event a malicious user wants to model a super user with a real
157
+ # super user's permissions)
158
+ end
159
+
160
+ # Handles action branching depending on the method for permission setting
161
+ # or getting. Defers to +permit?+ and +permit!+.
162
+ def permit
163
+ case method
164
+ when :get
165
+ permit?
166
+ when :post
167
+ permit!
168
+ end
169
+ end
170
+
171
+ # Does the user have permission?
172
+ def permit?
173
+ username, app, permission = params[:username], params[:app], params[:permission]
174
+
175
+ # pull the permissions for the user
176
+ perms = JSON.parse(@db[:users][:username => username][:permissions])
177
+
178
+ # test the permissions
179
+ unless perms[app].nil?
180
+ ok(perms[app][permission])
181
+ else
182
+ # no permissions were found for the given app
183
+ ok(false)
184
+ end
185
+ end
186
+
187
+ # Give permissions to user
188
+ def permit!
189
+ username, app, permission, value = params[:username], params[:app], params[:permission], post[:value]
190
+
191
+ # pull the permissions for the user
192
+ perms = JSON.parse(@db[:users][:username => username][:permissions])
193
+
194
+ # test the permissions
195
+ unless perms[app].nil?
196
+ if perms[app][permission] == value
197
+ ok(true)
198
+ else
199
+ raise Exceptions::Unauthorized.new
200
+ end
201
+ else
202
+ # no permissions were found for the given app
203
+ raise Exceptions::Unauthorized.new
204
+ end
205
+ end
206
+
207
+ end
208
+
209
+ # = Token Module
210
+ #
211
+ # Token actions, including authentication and destroying tokens. Tokens
212
+ # represent authenticated sessions allowing for faster repeated
213
+ # authentication requests in a short period of time (such as each page load
214
+ # in a larger web application).
215
+ token do
216
+
217
+ # Authenticates the token.
218
+ def auth
219
+ # expire_tokens # TODO: investigate how much of a performance hit checking (and deleting) is
220
+ unless @db[:tokens].filter('token = ? AND expires_at > ?', params[:token], Time.now).empty?
221
+ # authenticated
222
+
223
+ # update the expiration date if close to expiring
224
+ unless @db[:tokens].filter('token = ? AND expires_at <= ?', params[:token], generate_expiration(15)).empty?
225
+ @db[:tokens].filter(:token => params[:token]).update(:expires_at => generate_expiration)
226
+ end
227
+
228
+ # return success and token for client
229
+ ok(params[:token])
230
+ else
231
+ # failed authentication
232
+ raise Exceptions::Unauthorized.new
233
+ end
234
+ end
235
+
236
+ def destroy
237
+ @db[:tokens].filter(:token => params[:token]).delete
238
+ ok
239
+ end
240
+
241
+ end
242
+
243
+ # The default unauthorized action which raises an Unauthorized exception
244
+ def unauthorized(params={})
245
+ raise Exceptions::Unauthorized.new
246
+ end
247
+
248
+ #--
249
+ # Utility methods
250
+ #++
251
+
252
+ # Removes expired tokens.
253
+ def expire_tokens
254
+ @db[:tokens].filter('expires_at < ?',Time.now).delete
255
+ end
256
+
257
+ # Sets up a given user's permissions. Overwrite this method to specify more
258
+ # specific or dynamic default permissions, for instance connecting to LDAP
259
+ # to determine department and granting permissions that way.
260
+ def initialize_permissions(username)
261
+ # by default, no permissions are setup
262
+ # the returned value is JSON-ized
263
+ {}
264
+ end
265
+
266
+ # Generates a new time to expire from the minutes given, defaulting to the
267
+ # number of minutes given as a token lifetime in the configuration file.
268
+ def generate_expiration(lifetime=@config[:tokens][:lifetime])
269
+ (Time.now + (lifetime.to_i*60))
270
+ end
271
+
272
+ end
273
+
274
+ end
@@ -0,0 +1,24 @@
1
+ describe "Aurora::Server" do
2
+
3
+ before do
4
+ @serv = Specr.new :port => 6211
5
+ end
6
+
7
+ it "should authenticate users with proper credentials" do
8
+ response = JSON.parse(Rack::MockRequest.new(@serv).post("/user/auth/test", :input => '&password=pass&').body)
9
+ response['status'].should == 200
10
+ end
11
+
12
+ it "should provide a token for authenticated users with proper credentials" do
13
+ response = JSON.parse(Rack::MockRequest.new(@serv).post("/user/auth/test", :input => '&password=pass&').body)
14
+ response['status'].should == 200
15
+ response['body'].should == Digest::MD5.hexdigest(Time.now.to_s)
16
+ end
17
+
18
+ it "should return unauthorized error if improper credentials are attempting authentication" do
19
+ response = JSON.parse(Rack::MockRequest.new(@serv).post("/user/auth/test", :input => '&password=fail&').body)
20
+ response['status'].should == 401
21
+ response['body'].should == 'Unauthorized'
22
+ end
23
+
24
+ end
@@ -0,0 +1,20 @@
1
+ require 'rack/mock'
2
+ require 'aurora/server'
3
+
4
+ $test = true
5
+
6
+ # Testing inheriting the Aurora server
7
+ class Specr < Aurora::Server
8
+ def authenticate(user, pass)
9
+ # if pass isn't pass then it fails... get it?
10
+ pass == 'pass'
11
+ end
12
+ end
13
+
14
+ # Testing modifying the aurora server's authenticate method directly
15
+ class Aurora::Server
16
+ def authenticate(user, pass)
17
+ # if pass isn't pass then it fails... get it?
18
+ pass == 'pass'
19
+ end
20
+ end
metadata CHANGED
@@ -1,112 +1,68 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: aurora
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
5
- platform: ""
4
+ version: 0.1.10
5
+ platform: ruby
6
6
  authors:
7
7
  - Matt Todd
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2007-11-27 00:00:00 -05:00
12
+ date: 2008-02-19 00:00:00 -05:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
- name: json
16
+ name: halcyon
17
17
  version_requirement:
18
18
  version_requirements: !ruby/object:Gem::Requirement
19
19
  requirements:
20
20
  - - ">="
21
21
  - !ruby/object:Gem::Version
22
- version: 1.1.1
22
+ version: 0.3.28
23
23
  version:
24
- - !ruby/object:Gem::Dependency
25
- name: mongrel
26
- version_requirement:
27
- version_requirements: !ruby/object:Gem::Requirement
28
- requirements:
29
- - - ">="
30
- - !ruby/object:Gem::Version
31
- version: 1.1.1
32
- version:
33
- - !ruby/object:Gem::Dependency
34
- name: dhkeyexchange
35
- version_requirement:
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - ">="
39
- - !ruby/object:Gem::Version
40
- version: 1.0.0
41
- version:
42
- - !ruby/object:Gem::Dependency
43
- name: rack
44
- version_requirement:
45
- version_requirements: !ruby/object:Gem::Requirement
46
- requirements:
47
- - - ">="
48
- - !ruby/object:Gem::Version
49
- version: 0.2.0
50
- version:
51
- description: Simple authentication server and user permissions management tool.
52
- email: mtodd@clayton.edu
53
- executables: []
54
-
24
+ description: A Simple Authentication Server
25
+ email: chiology@gmail.com
26
+ executables:
27
+ - aurora
55
28
  extensions: []
56
29
 
57
30
  extra_rdoc_files:
58
- - History.txt
59
- - License.txt
60
- - Manifest.txt
61
- - README.txt
62
- - website/index.txt
31
+ - lib
63
32
  files:
64
- - History.txt
65
- - License.txt
66
- - Manifest.txt
67
- - README.txt
33
+ - lib
68
34
  - Rakefile
69
- - config/hoe.rb
70
- - config/requirements.rb
71
- - examples/basics.rb
72
- - lib/aurora.rb
35
+ - test/aurora
36
+ - test/aurora/server_spec.rb
37
+ - test/spec_helper.rb
38
+ - lib/aurora
73
39
  - lib/aurora/client.rb
74
- - lib/aurora/client/base.rb
75
- - lib/aurora/client/token.rb
40
+ - lib/aurora/migrations
41
+ - lib/aurora/migrations/001_create_users.rb
42
+ - lib/aurora/migrations/002_create_tokens.rb
76
43
  - lib/aurora/server.rb
77
- - lib/aurora/server/base.rb
78
- - lib/aurora/server/handler.rb
79
- - lib/aurora/server/server.rb
80
- - lib/aurora/server/token.rb
81
- - lib/aurora/version.rb
82
- - log/debug.log
83
- - script/destroy
84
- - script/generate
85
- - script/txt2html
86
- - setup.rb
87
- - tasks/deployment.rake
88
- - tasks/environment.rake
89
- - tasks/website.rake
90
- - test/test_aurora.rb
91
- - test/test_helper.rb
92
- - website/index.html
93
- - website/index.txt
94
- - website/javascripts/rounded_corners_lite.inc.js
95
- - website/stylesheets/screen.css
96
- - website/template.rhtml
44
+ - lib/aurora.rb
97
45
  has_rdoc: true
98
46
  homepage: http://aurora.rubyforge.org
99
47
  post_install_message:
100
48
  rdoc_options:
101
- - --main
102
- - README.txt
49
+ - --all
50
+ - --quiet
51
+ - --op
52
+ - rdoc
53
+ - --line-numbers
54
+ - --inline-source
55
+ - --title
56
+ - "\"Aurora Documentation\""
57
+ - --exclude
58
+ - "\"^(_darcs|test|pkg|.svn)/\""
103
59
  require_paths:
104
60
  - lib
105
61
  required_ruby_version: !ruby/object:Gem::Requirement
106
62
  requirements:
107
63
  - - ">="
108
64
  - !ruby/object:Gem::Version
109
- version: "0"
65
+ version: 1.8.6
110
66
  version:
111
67
  required_rubygems_version: !ruby/object:Gem::Requirement
112
68
  requirements:
@@ -114,13 +70,12 @@ required_rubygems_version: !ruby/object:Gem::Requirement
114
70
  - !ruby/object:Gem::Version
115
71
  version: "0"
116
72
  version:
117
- requirements: []
118
-
119
- rubyforge_project: aurora
120
- rubygems_version: 0.9.5
73
+ requirements:
74
+ - ""
75
+ rubyforge_project:
76
+ rubygems_version: 1.0.1
121
77
  signing_key:
122
78
  specification_version: 2
123
- summary: Simple authentication server and user permissions management tool.
124
- test_files:
125
- - test/test_aurora.rb
126
- - test/test_helper.rb
79
+ summary: A Simple Authentication Server
80
+ test_files: []
81
+