vanilla 1.9.11.1 → 1.9.12
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 +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
|