aurora 0.0.1 → 0.1.10
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.
- data/Rakefile +150 -4
- data/bin/aurora +250 -0
- data/lib/aurora.rb +36 -1
- data/lib/aurora/client.rb +61 -12
- data/lib/aurora/migrations/001_create_users.rb +13 -0
- data/lib/aurora/migrations/002_create_tokens.rb +13 -0
- data/lib/aurora/server.rb +264 -16
- data/test/aurora/server_spec.rb +24 -0
- data/test/spec_helper.rb +20 -0
- metadata +37 -82
- data/History.txt +0 -4
- data/License.txt +0 -20
- data/Manifest.txt +0 -33
- data/README.txt +0 -56
- data/config/hoe.rb +0 -76
- data/config/requirements.rb +0 -17
- data/examples/basics.rb +0 -14
- data/lib/aurora/client/base.rb +0 -15
- data/lib/aurora/client/token.rb +0 -7
- data/lib/aurora/server/base.rb +0 -69
- data/lib/aurora/server/handler.rb +0 -54
- data/lib/aurora/server/server.rb +0 -7
- data/lib/aurora/server/token.rb +0 -34
- data/lib/aurora/version.rb +0 -9
- data/log/debug.log +0 -0
- data/script/destroy +0 -14
- data/script/generate +0 -14
- data/script/txt2html +0 -74
- data/setup.rb +0 -1585
- data/tasks/deployment.rake +0 -34
- data/tasks/environment.rake +0 -7
- data/tasks/website.rake +0 -17
- data/test/test_aurora.rb +0 -11
- data/test/test_helper.rb +0 -2
- data/website/index.html +0 -143
- data/website/index.txt +0 -77
- data/website/javascripts/rounded_corners_lite.inc.js +0 -285
- data/website/stylesheets/screen.css +0 -138
- data/website/template.rhtml +0 -48
@@ -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
|
data/lib/aurora/server.rb
CHANGED
@@ -1,26 +1,274 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
#!/usr/bin/env ruby
|
3
2
|
#--
|
4
|
-
#
|
5
|
-
#
|
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
|
-
#
|
11
|
+
# dependencies
|
10
12
|
#++
|
11
13
|
|
12
|
-
require
|
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
|
-
#
|
17
|
+
# module
|
21
18
|
#++
|
22
19
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
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
|
data/test/spec_helper.rb
ADDED
@@ -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.
|
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:
|
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:
|
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:
|
22
|
+
version: 0.3.28
|
23
23
|
version:
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
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
|
-
-
|
59
|
-
- License.txt
|
60
|
-
- Manifest.txt
|
61
|
-
- README.txt
|
62
|
-
- website/index.txt
|
31
|
+
- lib
|
63
32
|
files:
|
64
|
-
-
|
65
|
-
- License.txt
|
66
|
-
- Manifest.txt
|
67
|
-
- README.txt
|
33
|
+
- lib
|
68
34
|
- Rakefile
|
69
|
-
-
|
70
|
-
-
|
71
|
-
-
|
72
|
-
- lib/aurora
|
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/
|
75
|
-
- lib/aurora/
|
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
|
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
|
-
- --
|
102
|
-
-
|
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:
|
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:
|
120
|
-
rubygems_version: 0.
|
73
|
+
requirements:
|
74
|
+
- ""
|
75
|
+
rubyforge_project:
|
76
|
+
rubygems_version: 1.0.1
|
121
77
|
signing_key:
|
122
78
|
specification_version: 2
|
123
|
-
summary: Simple
|
124
|
-
test_files:
|
125
|
-
|
126
|
-
- test/test_helper.rb
|
79
|
+
summary: A Simple Authentication Server
|
80
|
+
test_files: []
|
81
|
+
|