vanilla 1.9.11.1 → 1.9.12
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +2 -1
- data/config.ru +11 -1
- data/lib/vanilla/app.rb +16 -12
- data/lib/vanilla/authentication/warden.rb +42 -0
- data/lib/vanilla/authentication.rb +24 -0
- data/lib/vanilla/dynasnips/edit.rb +11 -11
- data/lib/vanilla/dynasnips/login.rb +9 -25
- data/lib/vanilla/dynasnips/new.rb +6 -5
- data/lib/vanilla/request.rb +30 -13
- data/lib/vanilla/snips/system.rb +1 -0
- metadata +14 -2
data/Rakefile
CHANGED
@@ -25,7 +25,7 @@ if Object.const_defined?(:Gem)
|
|
25
25
|
|
26
26
|
# Change these as appropriate
|
27
27
|
s.name = "vanilla"
|
28
|
-
s.version = "1.9.
|
28
|
+
s.version = "1.9.12"
|
29
29
|
s.summary = "A bliki-type web content thing."
|
30
30
|
s.author = "James Adam"
|
31
31
|
s.email = "james@lazyatom.com.com"
|
@@ -47,6 +47,7 @@ if Object.const_defined?(:Gem)
|
|
47
47
|
s.add_dependency("RedCloth", ">= 4.1.1")
|
48
48
|
s.add_dependency("BlueCloth", ">= 1.0.0")
|
49
49
|
s.add_dependency("treetop", ">= 1.4.1")
|
50
|
+
s.add_dependency("warden", ">= 0.5.2")
|
50
51
|
|
51
52
|
s.add_development_dependency("rspec") # add any other gems for testing/development
|
52
53
|
|
data/config.ru
CHANGED
@@ -2,9 +2,19 @@ $:.unshift File.join(File.dirname(__FILE__), *%w[lib])
|
|
2
2
|
require 'vanilla'
|
3
3
|
|
4
4
|
app = Vanilla::App.new(ENV['VANILLA_CONFIG'])
|
5
|
+
|
5
6
|
use Rack::Session::Cookie, :key => 'vanilla.session',
|
6
7
|
:path => '/',
|
7
8
|
:expire_after => 2592000,
|
8
9
|
:secret => app.config[:secret]
|
10
|
+
|
11
|
+
require 'vanilla/authentication/warden'
|
12
|
+
app.authenticator = Vanilla::Authentication::Warden.new(app)
|
13
|
+
use Warden::Manager do |manager|
|
14
|
+
manager.default_strategies :vanilla
|
15
|
+
manager.failure_app = lambda{|e| [401, {"Content-Type" => "text/plain"}, ["Fail App"]]}
|
16
|
+
end
|
17
|
+
|
9
18
|
use Rack::Static, :urls => ["/public"], :root => File.join(File.dirname(__FILE__))
|
10
|
-
|
19
|
+
|
20
|
+
run app
|
data/lib/vanilla/app.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'vanilla/request'
|
2
|
+
require 'vanilla/authentication'
|
2
3
|
require 'vanilla/routes'
|
3
4
|
require 'vanilla/soup_with_timestamps'
|
4
5
|
|
@@ -11,16 +12,19 @@ require 'vanilla/renderers/erb'
|
|
11
12
|
module Vanilla
|
12
13
|
class App
|
13
14
|
include Routes
|
14
|
-
|
15
|
+
|
15
16
|
attr_reader :request, :response, :config, :soup
|
16
|
-
|
17
|
+
attr_accessor :authenticator
|
18
|
+
|
17
19
|
def initialize(config_file=nil)
|
18
20
|
prepare_configuration(config_file)
|
19
21
|
@soup = SoupWithTimestamps.new(config[:soup])
|
22
|
+
@authenticator = Vanilla::Authentication::Base.new(self)
|
20
23
|
end
|
21
|
-
|
24
|
+
|
22
25
|
# Returns a Rack-appropriate 3-element array (via Rack::Response#finish)
|
23
26
|
def call(env)
|
27
|
+
env['vanilla.app'] = self
|
24
28
|
@request = Vanilla::Request.new(env, self)
|
25
29
|
@response = Rack::Response.new
|
26
30
|
|
@@ -30,7 +34,7 @@ module Vanilla
|
|
30
34
|
@response.status = 500
|
31
35
|
output = e.to_s
|
32
36
|
end
|
33
|
-
response_format = request.format
|
37
|
+
response_format = request.format
|
34
38
|
response_format = 'plain' if response_format == 'raw'
|
35
39
|
@response['Content-Type'] = "text/#{response_format}"
|
36
40
|
@response.write(output)
|
@@ -59,34 +63,34 @@ module Vanilla
|
|
59
63
|
end
|
60
64
|
end
|
61
65
|
|
62
|
-
# Given the snip and parameters, yield an instance of the appropriate
|
66
|
+
# Given the snip and parameters, yield an instance of the appropriate
|
63
67
|
# Vanilla::Render::Base subclass
|
64
68
|
def rendering(snip)
|
65
69
|
renderer_instance = renderer_for(snip).new(self)
|
66
70
|
yield renderer_instance
|
67
71
|
rescue Exception => e
|
68
|
-
"<pre>[Error rendering '#{snip.name}' - \"" +
|
69
|
-
e.message.gsub("<", "<").gsub(">", ">") + "\"]\n" +
|
72
|
+
"<pre>[Error rendering '#{snip.name}' - \"" +
|
73
|
+
e.message.gsub("<", "<").gsub(">", ">") + "\"]\n" +
|
70
74
|
e.backtrace.join("\n").gsub("<", "<").gsub(">", ">") + "</pre>"
|
71
75
|
end
|
72
|
-
|
76
|
+
|
73
77
|
# Returns the renderer class for a given snip
|
74
78
|
def renderer_for(snip)
|
75
79
|
return Renderers::Base unless snip.render_as && !snip.render_as.empty?
|
76
80
|
Vanilla::Renderers.const_get(snip.render_as)
|
77
81
|
end
|
78
|
-
|
82
|
+
|
79
83
|
# Other things can call this when a snip cannot be loaded.
|
80
84
|
def render_missing_snip(snip_name)
|
81
85
|
"[snip '#{snip_name}' cannot be found]"
|
82
86
|
end
|
83
|
-
|
87
|
+
|
84
88
|
def snip(attributes)
|
85
89
|
@soup.new_snip(attributes)
|
86
90
|
end
|
87
|
-
|
91
|
+
|
88
92
|
private
|
89
|
-
|
93
|
+
|
90
94
|
def prepare_configuration(config_file)
|
91
95
|
config_file ||= "config.yml"
|
92
96
|
@config = YAML.load(File.open(config_file)) rescue {}
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'warden'
|
2
|
+
|
3
|
+
module Vanilla
|
4
|
+
module Authentication
|
5
|
+
class Warden < Base
|
6
|
+
def initialize(app)
|
7
|
+
super
|
8
|
+
::Warden::Strategies.add(:vanilla, Vanilla::Authentication::Warden::Strategy)
|
9
|
+
end
|
10
|
+
|
11
|
+
def authenticated?
|
12
|
+
@app.request.env['warden'].authenticated?
|
13
|
+
end
|
14
|
+
|
15
|
+
def user
|
16
|
+
@app.request.env['warden'].user
|
17
|
+
end
|
18
|
+
|
19
|
+
def authenticate!
|
20
|
+
@app.request.env['warden'].authenticate!
|
21
|
+
end
|
22
|
+
|
23
|
+
def logout
|
24
|
+
@app.request.env['warden'].logout
|
25
|
+
end
|
26
|
+
|
27
|
+
class Strategy < ::Warden::Strategies::Base
|
28
|
+
def valid?
|
29
|
+
params["name"] || params["password"]
|
30
|
+
end
|
31
|
+
|
32
|
+
def authenticate!
|
33
|
+
if env['vanilla.app'].config[:credentials][params["name"]] == MD5.md5(params["password"]).to_s
|
34
|
+
success!(params["name"])
|
35
|
+
else
|
36
|
+
redirect!("/login")
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Vanilla
|
2
|
+
module Authentication
|
3
|
+
# A pass-through authenticator, which never
|
4
|
+
# requires a login
|
5
|
+
class Base
|
6
|
+
def initialize(app)
|
7
|
+
@app = app
|
8
|
+
end
|
9
|
+
|
10
|
+
def authenticated?
|
11
|
+
true
|
12
|
+
end
|
13
|
+
|
14
|
+
def user
|
15
|
+
end
|
16
|
+
|
17
|
+
def authenticate!
|
18
|
+
end
|
19
|
+
|
20
|
+
def logout
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -4,18 +4,18 @@ require 'vanilla/dynasnips/login'
|
|
4
4
|
# The edit dyna will load the snip given in the 'snip_to_edit' part of the
|
5
5
|
# params
|
6
6
|
class EditSnip < Dynasnip
|
7
|
-
include Login::Helper
|
8
|
-
|
9
7
|
snip_name "edit"
|
10
|
-
|
8
|
+
|
11
9
|
def get(snip_name=nil)
|
12
|
-
|
10
|
+
app.request.authenticate!
|
11
|
+
|
13
12
|
snip = app.soup[snip_name || app.request.params[:name]]
|
14
13
|
edit(snip)
|
15
14
|
end
|
16
|
-
|
15
|
+
|
17
16
|
def post(*args)
|
18
|
-
|
17
|
+
app.request.authenticate!
|
18
|
+
|
19
19
|
snip_attributes = cleaned_params
|
20
20
|
snip_attributes.delete(:save_button)
|
21
21
|
return 'no params' if snip_attributes.empty?
|
@@ -29,20 +29,20 @@ class EditSnip < Dynasnip
|
|
29
29
|
app.soup << snip_attributes
|
30
30
|
%{Created snip #{link_to snip_attributes[:name]} ok}
|
31
31
|
end
|
32
|
-
|
32
|
+
|
33
33
|
def edit(snip)
|
34
34
|
renderer = Vanilla::Renderers::Erb.new(app)
|
35
35
|
renderer.instance_eval { @snip_to_edit = snip } # hacky!
|
36
36
|
snip_in_edit_template = renderer.render_without_including_snips(app.soup['edit'], :template)
|
37
37
|
prevent_snip_inclusion(snip_in_edit_template)
|
38
38
|
end
|
39
|
-
|
39
|
+
|
40
40
|
private
|
41
|
-
|
41
|
+
|
42
42
|
def prevent_snip_inclusion(content)
|
43
43
|
content.gsub("{", "{").gsub("}" ,"}")
|
44
44
|
end
|
45
|
-
|
45
|
+
|
46
46
|
attribute :template, %{
|
47
47
|
<form action="<%= url_to 'edit' %>" method="post">
|
48
48
|
<dl class="attributes">
|
@@ -57,4 +57,4 @@ class EditSnip < Dynasnip
|
|
57
57
|
<button name='save_button'>Save</button>
|
58
58
|
</form>
|
59
59
|
}
|
60
|
-
end
|
60
|
+
end
|
@@ -3,43 +3,27 @@ require 'yaml'
|
|
3
3
|
require 'md5'
|
4
4
|
|
5
5
|
class Login < Dynasnip
|
6
|
-
module Helper
|
7
|
-
def logged_in?
|
8
|
-
!current_user.nil?
|
9
|
-
end
|
10
|
-
|
11
|
-
def current_user
|
12
|
-
app.request.session['logged_in_as']
|
13
|
-
end
|
14
|
-
|
15
|
-
def login_required
|
16
|
-
"You need to <a href='/login'>login</a> to do that."
|
17
|
-
end
|
18
|
-
end
|
19
|
-
include Helper
|
20
|
-
|
21
6
|
def get(*args)
|
22
|
-
if
|
7
|
+
if app.request.authenticated?
|
23
8
|
login_controls
|
24
9
|
else
|
25
10
|
render(self, 'template')
|
26
11
|
end
|
27
12
|
end
|
28
|
-
|
13
|
+
|
29
14
|
def post(*args)
|
30
|
-
if app.
|
31
|
-
app.request.session['logged_in_as'] = cleaned_params[:name]
|
15
|
+
if app.request.authenticate!
|
32
16
|
login_controls
|
33
17
|
else
|
34
18
|
"login fail!"
|
35
19
|
end
|
36
20
|
end
|
37
|
-
|
21
|
+
|
38
22
|
def delete(*args)
|
39
|
-
app.request.
|
23
|
+
app.request.logout
|
40
24
|
"Logged out"
|
41
25
|
end
|
42
|
-
|
26
|
+
|
43
27
|
attribute :template, <<-EHTML
|
44
28
|
<form action='/login' method='post'>
|
45
29
|
<label>Name: <input type="text" name="name"></input></label>
|
@@ -47,10 +31,10 @@ class Login < Dynasnip
|
|
47
31
|
<button>login</button>
|
48
32
|
</form>
|
49
33
|
EHTML
|
50
|
-
|
34
|
+
|
51
35
|
private
|
52
|
-
|
36
|
+
|
53
37
|
def login_controls
|
54
|
-
"logged in as {link_to
|
38
|
+
"logged in as #{link_to app.request.user}; <a href='/login?_method=delete'>logout</a>"
|
55
39
|
end
|
56
40
|
end
|
@@ -2,13 +2,14 @@ require 'vanilla/dynasnip'
|
|
2
2
|
require 'vanilla/dynasnips/login'
|
3
3
|
|
4
4
|
class NewSnip < Dynasnip
|
5
|
-
include Login::Helper
|
6
|
-
|
5
|
+
# include Login::Helper
|
6
|
+
|
7
7
|
snip_name :new
|
8
|
-
|
8
|
+
|
9
9
|
def handle(*arg)
|
10
|
-
|
10
|
+
app.request.authenticate!
|
11
|
+
|
11
12
|
base_params = {:render_as => '', :content => '', :author => current_user}.update(app.request.params)
|
12
13
|
editor = EditSnip.new(app).edit(Snip.new(base_params))
|
13
14
|
end
|
14
|
-
end
|
15
|
+
end
|
data/lib/vanilla/request.rb
CHANGED
@@ -4,9 +4,10 @@ module Vanilla
|
|
4
4
|
# Create a request with symbolised access to the params, and some special
|
5
5
|
# accessors to the snip, part and format based on our routing.
|
6
6
|
class Request
|
7
|
-
attr_reader :snip_name, :part, :format, :method
|
8
|
-
|
7
|
+
attr_reader :snip_name, :part, :format, :method, :env
|
8
|
+
|
9
9
|
def initialize(env, app)
|
10
|
+
@env = env
|
10
11
|
@rack_request = Rack::Request.new(env)
|
11
12
|
@app = app
|
12
13
|
determine_request_uri_parts
|
@@ -16,41 +17,57 @@ module Vanilla
|
|
16
17
|
# Don't you just love how terse functional programming tends to look like maths?
|
17
18
|
@symbolised_params ||= @rack_request.params.inject({}) { |p, (k,v)| p[k.to_sym] = v; p }
|
18
19
|
end
|
19
|
-
|
20
|
+
|
20
21
|
# Returns the snip referenced by the request's URL. Performs no exception
|
21
22
|
# handling, so if the snip does not exist, an exception will be thrown.
|
22
23
|
def snip
|
23
24
|
@app.soup[snip_name]
|
24
25
|
end
|
25
|
-
|
26
|
+
|
26
27
|
def cookies
|
27
28
|
@rack_request.cookies
|
28
29
|
end
|
29
|
-
|
30
|
+
|
30
31
|
def ip
|
31
32
|
@rack_request.env["REMOTE_ADDR"]
|
32
33
|
end
|
33
|
-
|
34
|
+
|
34
35
|
def session
|
35
36
|
@rack_request.env["rack.session"]
|
36
37
|
end
|
37
|
-
|
38
|
+
|
39
|
+
def authenticated?
|
40
|
+
@app.authenticator.authenticated?
|
41
|
+
end
|
42
|
+
|
43
|
+
def user
|
44
|
+
@app.authenticator.user
|
45
|
+
end
|
46
|
+
|
47
|
+
def authenticate!
|
48
|
+
@app.authenticator.authenticate!
|
49
|
+
end
|
50
|
+
|
51
|
+
def logout
|
52
|
+
@app.authenticator.logout
|
53
|
+
end
|
54
|
+
|
38
55
|
private
|
39
|
-
|
56
|
+
|
40
57
|
def determine_request_uri_parts
|
41
58
|
@snip_name, @part, @format = request_uri_parts(@rack_request)
|
42
59
|
@format ||= 'html'
|
43
60
|
@method = (params.delete(:_method) || @rack_request.request_method).downcase
|
44
61
|
end
|
45
|
-
|
62
|
+
|
46
63
|
def uri_path(request)
|
47
64
|
request.path_info
|
48
65
|
end
|
49
|
-
|
66
|
+
|
50
67
|
URL_ROOT = /\A\/\Z/ # i.e. /
|
51
68
|
URL_SNIP = /\A\/([\w\-\s]+)(\/|\.(\w+))?\Z/ # i.e. /start, /start.html
|
52
69
|
URL_SNIP_AND_PART = /\A\/([\w\-\s]+)\/([\w\-\s]+)(\/|\.(\w+))?\Z/ # i.e. /blah/part, /blah/part.raw
|
53
|
-
|
70
|
+
|
54
71
|
# Returns an array of the requested snip, part and format
|
55
72
|
def request_uri_parts(request)
|
56
73
|
case CGI.unescape(uri_path(request))
|
@@ -64,6 +81,6 @@ module Vanilla
|
|
64
81
|
[]
|
65
82
|
end
|
66
83
|
end
|
67
|
-
|
84
|
+
|
68
85
|
end
|
69
|
-
end
|
86
|
+
end
|
data/lib/vanilla/snips/system.rb
CHANGED
@@ -9,6 +9,7 @@ system.main_template = <<-HTML
|
|
9
9
|
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
|
10
10
|
<title>{current_snip name}</title>
|
11
11
|
<script language="javascript" src="/public/javascripts/jquery.js"></script>
|
12
|
+
<script language="javascript" src="/public/javascripts/jquery.autogrow-textarea.js"></script>
|
12
13
|
<script language="javascript" src="/public/javascripts/vanilla.js"></script>
|
13
14
|
<link rel="stylesheet" type="text/css" media="screen" href="<%= url_to("system", "css.css") %>" />
|
14
15
|
</head>
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: vanilla
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.9.
|
4
|
+
version: 1.9.12
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- James Adam
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-10
|
12
|
+
date: 2009-11-10 00:00:00 +00:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -72,6 +72,16 @@ dependencies:
|
|
72
72
|
- !ruby/object:Gem::Version
|
73
73
|
version: 1.4.1
|
74
74
|
version:
|
75
|
+
- !ruby/object:Gem::Dependency
|
76
|
+
name: warden
|
77
|
+
type: :runtime
|
78
|
+
version_requirement:
|
79
|
+
version_requirements: !ruby/object:Gem::Requirement
|
80
|
+
requirements:
|
81
|
+
- - ">="
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: 0.5.2
|
84
|
+
version:
|
75
85
|
- !ruby/object:Gem::Dependency
|
76
86
|
name: rspec
|
77
87
|
type: :development
|
@@ -113,6 +123,8 @@ files:
|
|
113
123
|
- lib/defensio.rb
|
114
124
|
- lib/tasks/vanilla.rake
|
115
125
|
- lib/vanilla/app.rb
|
126
|
+
- lib/vanilla/authentication/warden.rb
|
127
|
+
- lib/vanilla/authentication.rb
|
116
128
|
- lib/vanilla/console.rb
|
117
129
|
- lib/vanilla/dynasnip.rb
|
118
130
|
- lib/vanilla/dynasnips/comments.rb
|