/
composition_engine.rb
143 lines (117 loc) · 3.08 KB
/
composition_engine.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
require 'cgi'
module CompositionEngine
SESSION_KEY = 'composition_engine'
PATH_PREFIX = '/engine'
def self.assign_user_to_session(session,user)
scope_session(session)['user'] = user
end
def self.extract_user_from_session(session)
scope_session(session)['user']
end
def self.scope_session(session)
session[SESSION_KEY]||= {}
end
class User < Hashie::Dash
property :nickname
property :uuid
end
class Middleware
attr_accessor :app, :env
def initialize(_app)
self.app = _app
end
def call(_env)
self.env = _env
call_override || app.call(_env)
end
def call_override
case scoped_path
when false
LoginHandler.force_login(env) #This returns false and defaults control to the next middleware if they're already logged in
when '/inspect'
[200,{'Content-Type' => 'text/plain'},[self.env.keys.map{|k| "#{k.inspect}: #{self.env[k].inspect}"}.join("\n")]]
when /^#{LoginHandler.resource_path}/
LoginHandler.handle(env)
else
[404,{'ContentType' => 'text/plain'},['Not Found']]
end
end
def scoped_path
return false if !(env['PATH_INFO'] =~ /^#{PATH_PREFIX}(\/.*)?$/)
return '/' if $1.nil?
return $1
end
end
class LoginHandler
attr_accessor :env
def self.handle(_env)
self.new(_env).handle
end
def self.force_login(_env)
inst = self.new(_env)
if inst.logged_in?
false
else
inst.new_login
end
end
def self.resource_path
'/login'
end
def self.prefixed_path
PATH_PREFIX+self.resource_path
end
def initialize(_env)
self.env = _env
end
def handle
if request.get?
new_login
elsif request.post?
create_login
end
end
def new_login(message = nil) #TODO: require form key so they can't spam POSTs
body = <<HTML
<html>
<body>
<h1>New User!</h1>
#{"<em>#{message}</em>" if message}
<p>Select a handle and click Login</p>
<form action='#{self.class.prefixed_path}' method='POST'>
<label for='login_nickname'>Nickname: </label><input type='text' name='login[nickname]' id='login_nickname'/>
<input type='submit' value='Login' />
</form>
</body>
</html>
HTML
[200,{'ContentType' => 'text/html'},[body]]
end
def create_login
nickname = params['login']['nickname']
if nickname.nil? || nickname.empty?
new_login("Nickname must not be blank!")
else
user = ::CompositionEngine::User.new(:nickname => nickname, :uuid => UUIDTools::UUID.random_create)
::CompositionEngine.assign_user_to_session(session,user)
[302,{'Location'=>'/'},[]]
end
end
def logged_in?
::CompositionEngine.extract_user_from_session(session)
end
private
def scoped_session
::CompositionEngine.scope_session(session)
end
def session
request.session
end
def params
request.params
end
def request
@_rack_request||= Rack::Request.new(env)
end
end
end