creationix-milk 0.0.9
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/.document +5 -0
- data/.gitignore +7 -0
- data/LICENSE +27 -0
- data/README.rdoc +7 -0
- data/Rakefile +62 -0
- data/VERSION +1 -0
- data/bin/milk +22 -0
- data/lib/milk.rb +82 -0
- data/lib/milk/application.rb +227 -0
- data/lib/milk/component.rb +142 -0
- data/lib/milk/field.rb +60 -0
- data/lib/milk/fields/component.haml +8 -0
- data/lib/milk/fields/component_array.haml +3 -0
- data/lib/milk/fields/component_array.rb +4 -0
- data/lib/milk/fields/image_chooser.haml +7 -0
- data/lib/milk/fields/image_chooser.rb +26 -0
- data/lib/milk/fields/login.haml +90 -0
- data/lib/milk/fields/markdown_field.haml +1 -0
- data/lib/milk/fields/markdown_field.rb +4 -0
- data/lib/milk/fields/page_chooser.haml +3 -0
- data/lib/milk/fields/page_chooser.rb +17 -0
- data/lib/milk/fields/sprite_chooser.haml +6 -0
- data/lib/milk/fields/sprite_chooser.rb +19 -0
- data/lib/milk/fields/text_field.haml +1 -0
- data/lib/milk/fields/text_field.rb +4 -0
- data/lib/milk/fields/xhtml.haml +253 -0
- data/lib/milk/haxe.rb +139 -0
- data/lib/milk/page.rb +139 -0
- data/lib/milk/tasks.rb +51 -0
- data/milk.gemspec +137 -0
- data/site_template/Rakefile +3 -0
- data/site_template/config.ru +16 -0
- data/site_template/config/config.yaml +31 -0
- data/site_template/config/foot.yaml +3 -0
- data/site_template/config/head.yaml +18 -0
- data/site_template/config/users.yaml +18 -0
- data/site_template/design/0-reset.sass +170 -0
- data/site_template/design/1-text.sass +65 -0
- data/site_template/design/960.sass +305 -0
- data/site_template/design/body.haml +1 -0
- data/site_template/design/body.rb +4 -0
- data/site_template/design/button.haml +2 -0
- data/site_template/design/button.rb +16 -0
- data/site_template/design/foot.haml +1 -0
- data/site_template/design/foot.rb +4 -0
- data/site_template/design/foot.sass +3 -0
- data/site_template/design/head.haml +3 -0
- data/site_template/design/head.rb +4 -0
- data/site_template/design/head.sass +27 -0
- data/site_template/design/page.haml +2 -0
- data/site_template/design/page.sass +7 -0
- data/site_template/design/sprites.sass +0 -0
- data/site_template/design/xhtml.haml +15 -0
- data/site_template/pages/About.yaml +14 -0
- data/site_template/pages/Home.yaml +14 -0
- data/site_template/pages/News.yaml +14 -0
- data/site_template/pages/NotFound.yaml +14 -0
- data/site_template/pages/Products.yaml +14 -0
- data/site_template/public/cache/About/index.html +42 -0
- data/site_template/public/cache/Home/index.html +44 -0
- data/site_template/public/cache/News/index.html +42 -0
- data/site_template/public/cache/Products/index.html +42 -0
- data/site_template/public/favicon.ico +0 -0
- data/site_template/public/images/README.txt +2 -0
- data/site_template/public/js/jquery-1.3.2.min.js +19 -0
- data/site_template/public/js/jquery-ui-1.7.2.custom.min.js +34 -0
- data/site_template/public/js/jquery.json-1.3.min.js +37 -0
- data/site_template/public/robots.txt +0 -0
- data/site_template/public/skin/images/ui-bg_diagonals-thick_18_b81900_40x40.png +0 -0
- data/site_template/public/skin/images/ui-bg_diagonals-thick_20_666666_40x40.png +0 -0
- data/site_template/public/skin/images/ui-bg_flat_10_000000_40x100.png +0 -0
- data/site_template/public/skin/images/ui-bg_glass_100_f6f6f6_1x400.png +0 -0
- data/site_template/public/skin/images/ui-bg_glass_100_fdf5ce_1x400.png +0 -0
- data/site_template/public/skin/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
- data/site_template/public/skin/images/ui-bg_gloss-wave_35_f6a828_500x100.png +0 -0
- data/site_template/public/skin/images/ui-bg_highlight-soft_100_eeeeee_1x100.png +0 -0
- data/site_template/public/skin/images/ui-bg_highlight-soft_75_ffe45c_1x100.png +0 -0
- data/site_template/public/skin/images/ui-icons_222222_256x240.png +0 -0
- data/site_template/public/skin/images/ui-icons_228ef1_256x240.png +0 -0
- data/site_template/public/skin/images/ui-icons_ef8c08_256x240.png +0 -0
- data/site_template/public/skin/images/ui-icons_ffd27a_256x240.png +0 -0
- data/site_template/public/skin/images/ui-icons_ffffff_256x240.png +0 -0
- data/site_template/public/skin/jquery-ui-1.7.2.custom.css +406 -0
- data/site_template/public/style/style.css +157 -0
- data/site_template/tmp/restart.txt +1 -0
- data/test/milk_test.rb +7 -0
- data/test/test_helper.rb +10 -0
- metadata +170 -0
data/.document
ADDED
data/.gitignore
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
Copyright (c) 2009, Tim Caswell
|
2
|
+
All rights reserved.
|
3
|
+
|
4
|
+
Redistribution and use in source and binary forms, with or without modification,
|
5
|
+
are permitted provided that the following conditions are met:
|
6
|
+
|
7
|
+
* Redistributions of source code must retain the above copyright notice,
|
8
|
+
this list of conditions and the following disclaimer.
|
9
|
+
|
10
|
+
* Redistributions in binary form must reproduce the above copyright notice,
|
11
|
+
this list of conditions and the following disclaimer in the documentation
|
12
|
+
and/or other materials provided with the distribution.
|
13
|
+
|
14
|
+
* Neither the name of the Creationix nor the names of its contributors may
|
15
|
+
be used to endorse or promote products derived from this software without
|
16
|
+
specific prior written permission.
|
17
|
+
|
18
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
19
|
+
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
20
|
+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
21
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
22
|
+
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
23
|
+
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
24
|
+
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
25
|
+
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
26
|
+
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
27
|
+
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
data/README.rdoc
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = "milk"
|
8
|
+
gem.summary = %Q{Milk is a rack based content management system built for ease of use and simplicity. Milk tastes great with and without cookies.}
|
9
|
+
gem.email = "tim@creationix.com"
|
10
|
+
gem.homepage = "http://github.com/creationix/milk"
|
11
|
+
gem.authors = ["Tim Caswell"]
|
12
|
+
gem.rubyforge_project = "milk"
|
13
|
+
gem.required_ruby_version = '>=1.9'
|
14
|
+
gem.add_dependency('rack', '>= 1.0.0')
|
15
|
+
gem.add_dependency('maruku', '>= 0.6.0')
|
16
|
+
gem.add_dependency('haml', '>= 2.0.9')
|
17
|
+
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
18
|
+
end
|
19
|
+
|
20
|
+
Jeweler::RubyforgeTasks.new
|
21
|
+
rescue LoadError
|
22
|
+
puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
|
23
|
+
end
|
24
|
+
|
25
|
+
require 'rake/testtask'
|
26
|
+
Rake::TestTask.new(:test) do |test|
|
27
|
+
test.libs << 'lib' << 'test'
|
28
|
+
test.pattern = 'test/**/*_test.rb'
|
29
|
+
test.verbose = true
|
30
|
+
end
|
31
|
+
|
32
|
+
begin
|
33
|
+
require 'rcov/rcovtask'
|
34
|
+
Rcov::RcovTask.new do |test|
|
35
|
+
test.libs << 'test'
|
36
|
+
test.pattern = 'test/**/*_test.rb'
|
37
|
+
test.verbose = true
|
38
|
+
end
|
39
|
+
rescue LoadError
|
40
|
+
task :rcov do
|
41
|
+
abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
|
46
|
+
task :default => :test
|
47
|
+
|
48
|
+
require 'rake/rdoctask'
|
49
|
+
Rake::RDocTask.new do |rdoc|
|
50
|
+
if File.exist?('VERSION.yml')
|
51
|
+
config = YAML.load(File.read('VERSION.yml'))
|
52
|
+
version = "#{config[:major]}.#{config[:minor]}.#{config[:patch]}"
|
53
|
+
else
|
54
|
+
version = ""
|
55
|
+
end
|
56
|
+
|
57
|
+
rdoc.rdoc_dir = 'rdoc'
|
58
|
+
rdoc.title = "milk #{version}"
|
59
|
+
rdoc.rdoc_files.include('README*')
|
60
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
61
|
+
end
|
62
|
+
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.0.9
|
data/bin/milk
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'fileutils'
|
4
|
+
|
5
|
+
if ARGV.length != 1
|
6
|
+
puts "\nMilk site generator\n"
|
7
|
+
puts "\nUsage:\n\tmilk [target project]\n\n"
|
8
|
+
exit 1
|
9
|
+
end
|
10
|
+
|
11
|
+
target_path = File.absolute_path(ARGV[0])
|
12
|
+
if File.directory?(target_path)
|
13
|
+
puts "\nERROR: there already exists a folder #{target_path}\n"
|
14
|
+
exit 1
|
15
|
+
end
|
16
|
+
|
17
|
+
puts "\nCreating milk site at #{target_path}\n"
|
18
|
+
FileUtils.mkdir_p(target_path, :verbose => true)
|
19
|
+
MILK_ROOT = target_path
|
20
|
+
require 'milk'
|
21
|
+
FileUtils.cp_r(Milk::TEMPLATE_DIR+"/.", target_path, :verbose => true)
|
22
|
+
puts "\nDone!\n\n"
|
data/lib/milk.rb
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
# Autoload some useful libraries
|
2
|
+
autoload 'Haml', 'haml'
|
3
|
+
autoload 'Sass', 'sass'
|
4
|
+
autoload 'Maruku', 'maruku'
|
5
|
+
autoload 'YAML', 'yaml'
|
6
|
+
autoload 'FileUtils', 'fileutils'
|
7
|
+
|
8
|
+
# Set up our main namespace with autoloaded parts
|
9
|
+
module Milk
|
10
|
+
VERSION = '0.0.5'
|
11
|
+
|
12
|
+
LIB_DIR = File.dirname(__FILE__)
|
13
|
+
BIN_DIR ||= File.absolute_path(File.dirname(__FILE__)+"/../../local/bin")
|
14
|
+
TEMPLATE_DIR = File.absolute_path(LIB_DIR+"/../site_template")
|
15
|
+
def self.get_milk_root
|
16
|
+
c = caller(1).collect { |line| line.split(':').first }
|
17
|
+
c = c.select { |line| line !~ /\/gems\// }
|
18
|
+
File.absolute_path(File.dirname(c.first))
|
19
|
+
end
|
20
|
+
MILK_ROOT ||= get_milk_root
|
21
|
+
CONFIG_DIR = MILK_ROOT + "/config"
|
22
|
+
|
23
|
+
# Load overrides from config file
|
24
|
+
config_file = CONFIG_DIR+"/config.yaml"
|
25
|
+
YAML.load(open(CONFIG_DIR+"/config.yaml")).each_pair do |key, value|
|
26
|
+
eval("#{key} = #{value.inspect}")
|
27
|
+
end if File.file?(config_file)
|
28
|
+
|
29
|
+
# Set defaults otherwise
|
30
|
+
COMPONENTS_DIR ||= MILK_ROOT + "/design"
|
31
|
+
PAGES_DIR ||= MILK_ROOT + "/pages"
|
32
|
+
PUBLIC_DIR ||= MILK_ROOT + "/public"
|
33
|
+
FIELDS_DIR ||= LIB_DIR + "/milk/fields"
|
34
|
+
|
35
|
+
$LOAD_PATH.unshift(LIB_DIR) unless $LOAD_PATH.include?(LIB_DIR)
|
36
|
+
autoload :Application, "milk/application"
|
37
|
+
autoload :Component, "milk/component"
|
38
|
+
autoload :Page, "milk/page"
|
39
|
+
autoload :Haxe, "milk/haxe"
|
40
|
+
autoload :Field, "milk/field"
|
41
|
+
autoload :Fields, "milk/field"
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
# Autoload the components of the user space app into the root namespace for easy use
|
46
|
+
Dir.glob(Milk::COMPONENTS_DIR + "/*.rb").each do |c|
|
47
|
+
name = c.split('/').last.gsub(/(.*)\.rb/) { $1 }
|
48
|
+
class_name = name.gsub(/\/(.?)/) { "::" + $1.upcase }.gsub(/(^|_)(.)/) { $2.upcase }
|
49
|
+
path = c.gsub(/(.*)\.rb/) { $1 }
|
50
|
+
autoload class_name.to_sym, path
|
51
|
+
end
|
52
|
+
|
53
|
+
# Include metaid for easy metaclass management
|
54
|
+
class Object
|
55
|
+
# The hidden singleton lurks behind everyone
|
56
|
+
def metaclass; class << self; self; end; end
|
57
|
+
def meta_eval &blk; metaclass.instance_eval &blk; end
|
58
|
+
|
59
|
+
# Adds methods to a metaclass
|
60
|
+
def meta_def name, &blk
|
61
|
+
meta_eval { define_method name, &blk }
|
62
|
+
end
|
63
|
+
|
64
|
+
# Defines an instance method within a class
|
65
|
+
def class_def name, &blk
|
66
|
+
class_eval { define_method name, &blk }
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
# Add ability to get constants from a string name.
|
71
|
+
# WARNING: this is akin to eval for security concerns.
|
72
|
+
class String
|
73
|
+
def constantize
|
74
|
+
const = Object
|
75
|
+
self.split("::").each do |part|
|
76
|
+
const = const.const_get(part)
|
77
|
+
end
|
78
|
+
const
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
|
@@ -0,0 +1,227 @@
|
|
1
|
+
module Milk
|
2
|
+
class Application
|
3
|
+
|
4
|
+
PAGE_PATH_REGEX = /^\/([a-zA-Z0-9_]+(\/[a-zA-Z0-9_]+)*)+\/*$/
|
5
|
+
EDIT_PATH_REGEX = /^\/([a-zA-Z0-9_]+(\/[a-zA-Z0-9_]+)*)+\/edit\/*$/
|
6
|
+
|
7
|
+
attr_reader :req
|
8
|
+
|
9
|
+
def initialize(require_ssl=false)
|
10
|
+
@require_ssl = require_ssl
|
11
|
+
end
|
12
|
+
|
13
|
+
def route
|
14
|
+
path = @req.path_info
|
15
|
+
|
16
|
+
if path == '/'
|
17
|
+
# Special case for root
|
18
|
+
path = '/Home'
|
19
|
+
end
|
20
|
+
|
21
|
+
# Fallback to match everything
|
22
|
+
regex = /(.*)/
|
23
|
+
|
24
|
+
# Route the request to the right callback
|
25
|
+
https = @req.env['HTTPS'] == 'on'
|
26
|
+
action = case
|
27
|
+
when @req.get?
|
28
|
+
case
|
29
|
+
when path == "/logout"
|
30
|
+
:logout
|
31
|
+
when path =~ EDIT_PATH_REGEX
|
32
|
+
regex = EDIT_PATH_REGEX
|
33
|
+
if @require_ssl && !https
|
34
|
+
:https_redirect
|
35
|
+
else
|
36
|
+
:edit
|
37
|
+
end
|
38
|
+
when path =~ PAGE_PATH_REGEX
|
39
|
+
regex = PAGE_PATH_REGEX
|
40
|
+
:view
|
41
|
+
end
|
42
|
+
when @req.delete?
|
43
|
+
if path =~ PAGE_PATH_REGEX
|
44
|
+
regex = PAGE_PATH_REGEX
|
45
|
+
:delete
|
46
|
+
end
|
47
|
+
when @req.post?
|
48
|
+
if path == '/login'
|
49
|
+
:login
|
50
|
+
elsif path =~ PAGE_PATH_REGEX
|
51
|
+
regex = PAGE_PATH_REGEX
|
52
|
+
:preview
|
53
|
+
end
|
54
|
+
when @req.put?
|
55
|
+
if path =~ PAGE_PATH_REGEX
|
56
|
+
regex = PAGE_PATH_REGEX
|
57
|
+
:save
|
58
|
+
end
|
59
|
+
end || :not_found
|
60
|
+
|
61
|
+
page_name = regex.match(path)[1]
|
62
|
+
|
63
|
+
if (action == :view || action == :edit)
|
64
|
+
begin
|
65
|
+
page = Milk::Page.find(page_name)
|
66
|
+
rescue Milk::PageNotFoundError
|
67
|
+
action = :not_found
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
if (action == :preview || action == :save)
|
72
|
+
page = Milk::Page.json_unserialize(YAML.load(@req.body.read), page_name)
|
73
|
+
end
|
74
|
+
|
75
|
+
if !@user && [:edit, :save, :delete].include?(action)
|
76
|
+
action = :login_form
|
77
|
+
end
|
78
|
+
|
79
|
+
return action, page_name, page
|
80
|
+
end
|
81
|
+
|
82
|
+
def obfuscate(value)
|
83
|
+
require 'base64'
|
84
|
+
len = Milk::SECRET.length
|
85
|
+
result = (0...value.length).collect { |i| value[i].ord ^ Milk::SECRET[i%len].ord }
|
86
|
+
Base64.encode64(result.pack("C*"))
|
87
|
+
end
|
88
|
+
|
89
|
+
def decode(code)
|
90
|
+
require 'base64'
|
91
|
+
len = Milk::SECRET.length
|
92
|
+
value = Base64.decode64(code)
|
93
|
+
result = (0...value.length).collect { |i| value[i].ord ^ Milk::SECRET[i%len].ord }
|
94
|
+
result.pack("C*")
|
95
|
+
end
|
96
|
+
|
97
|
+
def hash(email, password)
|
98
|
+
require 'digest/md5'
|
99
|
+
Digest::MD5.hexdigest("#{password}")
|
100
|
+
end
|
101
|
+
|
102
|
+
def logout()
|
103
|
+
@resp.delete_cookie('auth', :path => "/")
|
104
|
+
@resp.redirect(@req.params['dest'])
|
105
|
+
end
|
106
|
+
|
107
|
+
def flash(message=nil)
|
108
|
+
@resp.delete_cookie('flash', :path => "/") unless message
|
109
|
+
@resp.set_cookie('flash', :path => "/", :value => message) if message
|
110
|
+
@req.cookies['flash']
|
111
|
+
end
|
112
|
+
|
113
|
+
def login()
|
114
|
+
email = @req.params['email']
|
115
|
+
if email.length > 0
|
116
|
+
user = users[email]
|
117
|
+
if user
|
118
|
+
expected = user["hash"]
|
119
|
+
actual = hash(email, @req.params['password'])
|
120
|
+
if actual == expected
|
121
|
+
@resp.set_cookie('auth', :path => "/", :value => obfuscate(email), :secure=>@require_ssl, :httponly=>true)
|
122
|
+
else
|
123
|
+
flash "Incorrect password for user #{email}"
|
124
|
+
end
|
125
|
+
else
|
126
|
+
flash "User #{email} not found"
|
127
|
+
end
|
128
|
+
else
|
129
|
+
flash "Please enter user email and password"
|
130
|
+
end
|
131
|
+
@resp.redirect(@req.params['dest'])
|
132
|
+
end
|
133
|
+
|
134
|
+
def users
|
135
|
+
users_file = Milk::CONFIG_DIR+"/users.yaml"
|
136
|
+
YAML.load(open(users_file).read)
|
137
|
+
end
|
138
|
+
|
139
|
+
def load_user
|
140
|
+
@user = nil
|
141
|
+
if current = @req.cookies['auth']
|
142
|
+
email = decode(current)
|
143
|
+
@user = users[email]
|
144
|
+
@resp.delete_cookie('auth', :path => "/") unless @user
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
# Rack call interface
|
149
|
+
def call(env)
|
150
|
+
@req = Rack::Request.new(env)
|
151
|
+
@resp = Rack::Response.new
|
152
|
+
load_user
|
153
|
+
|
154
|
+
# Route the request
|
155
|
+
action, page_name, @page = route
|
156
|
+
|
157
|
+
# Send proper mime types for browsers that claim to accept it
|
158
|
+
@resp["Content-Type"] =
|
159
|
+
if env['HTTP_ACCEPT'].include? "application/xhtml+xml"
|
160
|
+
"application/xhtml+xml"
|
161
|
+
"text/html"
|
162
|
+
else
|
163
|
+
"text/html"
|
164
|
+
end
|
165
|
+
|
166
|
+
case action
|
167
|
+
when :not_found
|
168
|
+
@resp.status = 404
|
169
|
+
page = Milk::Page.find('NotFound')
|
170
|
+
Milk::Application.join_tree(page, self)
|
171
|
+
@resp.write page.view
|
172
|
+
when :view
|
173
|
+
Milk::Application.join_tree(@page, self)
|
174
|
+
html = @page.view
|
175
|
+
@page.save_to_cache(html) if Milk::USE_CACHE
|
176
|
+
@resp.write html
|
177
|
+
when :https_redirect
|
178
|
+
@resp.redirect('https://' + @req.host + @req.fullpath)
|
179
|
+
when :http_redirect
|
180
|
+
@resp.redirect('http://' + @req.host + @req.fullpath)
|
181
|
+
when :edit
|
182
|
+
Milk::Application.join_tree(@page, self)
|
183
|
+
@resp.write @page.edit
|
184
|
+
when :save
|
185
|
+
Milk::Application.join_tree(@page, self)
|
186
|
+
@resp.write @page.save
|
187
|
+
when :preview
|
188
|
+
Milk::Application.join_tree(@page, self)
|
189
|
+
@resp.write @page.preview
|
190
|
+
when :login_form
|
191
|
+
filename = FIELDS_DIR + "/login.haml"
|
192
|
+
@resp.write(::Haml::Engine.new(File.read(filename), :filename => filename).render(self))
|
193
|
+
when :login
|
194
|
+
login
|
195
|
+
when :logout
|
196
|
+
logout
|
197
|
+
when :access_denied
|
198
|
+
@resp.staus = 403
|
199
|
+
@resp.write "Access Denied"
|
200
|
+
else
|
201
|
+
@resp.status = 500
|
202
|
+
@resp.write action.to_s
|
203
|
+
end
|
204
|
+
@resp.finish
|
205
|
+
end
|
206
|
+
|
207
|
+
# method that walks an object linking Milk objects to eachother
|
208
|
+
def self.join_tree(obj, parent)
|
209
|
+
if [Milk::Page, Milk::Component, Milk::Application].any? {|klass| obj.kind_of? klass}
|
210
|
+
obj.parent = parent
|
211
|
+
obj.instance_variables.each do |name|
|
212
|
+
var = obj.instance_variable_get(name)
|
213
|
+
if var.class == Array
|
214
|
+
var.each do |subvar|
|
215
|
+
join_tree(subvar, obj)
|
216
|
+
end
|
217
|
+
end
|
218
|
+
end
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
end
|
223
|
+
|
224
|
+
class PageNotFoundError < Exception
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|