rethoth 0.4.1
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.
- checksums.yaml +7 -0
- data/LICENSE +26 -0
- data/bin/thoth +233 -0
- data/lib/proto/config.ru +45 -0
- data/lib/proto/thoth.conf.sample +206 -0
- data/lib/thoth/cache.rb +53 -0
- data/lib/thoth/config.rb +158 -0
- data/lib/thoth/controller/admin.rb +75 -0
- data/lib/thoth/controller/api/comment.rb +73 -0
- data/lib/thoth/controller/api/page.rb +134 -0
- data/lib/thoth/controller/api/post.rb +122 -0
- data/lib/thoth/controller/api/tag.rb +59 -0
- data/lib/thoth/controller/archive.rb +50 -0
- data/lib/thoth/controller/comment.rb +173 -0
- data/lib/thoth/controller/main.rb +193 -0
- data/lib/thoth/controller/media.rb +172 -0
- data/lib/thoth/controller/page.rb +167 -0
- data/lib/thoth/controller/post.rb +310 -0
- data/lib/thoth/controller/search.rb +86 -0
- data/lib/thoth/controller/tag.rb +107 -0
- data/lib/thoth/controller.rb +48 -0
- data/lib/thoth/errors.rb +35 -0
- data/lib/thoth/helper/admin.rb +86 -0
- data/lib/thoth/helper/cookie.rb +45 -0
- data/lib/thoth/helper/error.rb +122 -0
- data/lib/thoth/helper/pagination.rb +131 -0
- data/lib/thoth/helper/wiki.rb +77 -0
- data/lib/thoth/helper/ysearch.rb +89 -0
- data/lib/thoth/importer/pants.rb +81 -0
- data/lib/thoth/importer/poseidon.rb +54 -0
- data/lib/thoth/importer/thoth.rb +103 -0
- data/lib/thoth/importer.rb +131 -0
- data/lib/thoth/layout/default.rhtml +47 -0
- data/lib/thoth/middleware/minify.rb +82 -0
- data/lib/thoth/migrate/001_create_schema.rb +108 -0
- data/lib/thoth/migrate/002_add_media_size.rb +37 -0
- data/lib/thoth/migrate/003_add_post_draft.rb +38 -0
- data/lib/thoth/migrate/004_add_comment_email.rb +37 -0
- data/lib/thoth/migrate/005_add_page_position.rb +37 -0
- data/lib/thoth/migrate/006_add_comment_close_delete.rb +43 -0
- data/lib/thoth/migrate/007_add_comment_summary.rb +37 -0
- data/lib/thoth/model/comment.rb +216 -0
- data/lib/thoth/model/media.rb +87 -0
- data/lib/thoth/model/page.rb +204 -0
- data/lib/thoth/model/post.rb +262 -0
- data/lib/thoth/model/tag.rb +80 -0
- data/lib/thoth/model/tags_posts_map.rb +34 -0
- data/lib/thoth/monkeypatch/sequel/model/errors.rb +37 -0
- data/lib/thoth/plugin/thoth_delicious.rb +105 -0
- data/lib/thoth/plugin/thoth_flickr.rb +86 -0
- data/lib/thoth/plugin/thoth_pinboard.rb +98 -0
- data/lib/thoth/plugin/thoth_tags.rb +68 -0
- data/lib/thoth/plugin/thoth_twitter.rb +175 -0
- data/lib/thoth/plugin.rb +59 -0
- data/lib/thoth/public/css/admin.css +223 -0
- data/lib/thoth/public/css/thoth.css +592 -0
- data/lib/thoth/public/images/admin-sprite.png +0 -0
- data/lib/thoth/public/images/thoth-sprite.png +0 -0
- data/lib/thoth/public/js/admin/comments.js +116 -0
- data/lib/thoth/public/js/admin/name.js +244 -0
- data/lib/thoth/public/js/admin/tagcomplete.js +332 -0
- data/lib/thoth/public/js/lazyload-min.js +4 -0
- data/lib/thoth/public/js/thoth.js +203 -0
- data/lib/thoth/public/robots.txt +5 -0
- data/lib/thoth/version.rb +37 -0
- data/lib/thoth/view/admin/index.rhtml +1 -0
- data/lib/thoth/view/admin/login.rhtml +23 -0
- data/lib/thoth/view/admin/toolbar.rhtml +117 -0
- data/lib/thoth/view/admin/welcome.rhtml +58 -0
- data/lib/thoth/view/archive/index.rhtml +24 -0
- data/lib/thoth/view/comment/comment.rhtml +47 -0
- data/lib/thoth/view/comment/delete.rhtml +15 -0
- data/lib/thoth/view/comment/form.rhtml +81 -0
- data/lib/thoth/view/comment/index.rhtml +68 -0
- data/lib/thoth/view/comment/list.rhtml +48 -0
- data/lib/thoth/view/media/delete.rhtml +15 -0
- data/lib/thoth/view/media/edit.rhtml +12 -0
- data/lib/thoth/view/media/form.rhtml +7 -0
- data/lib/thoth/view/media/list.rhtml +35 -0
- data/lib/thoth/view/media/media.rhtml +44 -0
- data/lib/thoth/view/media/new.rhtml +7 -0
- data/lib/thoth/view/page/delete.rhtml +15 -0
- data/lib/thoth/view/page/edit.rhtml +15 -0
- data/lib/thoth/view/page/form.rhtml +57 -0
- data/lib/thoth/view/page/index.rhtml +9 -0
- data/lib/thoth/view/page/list.rhtml +49 -0
- data/lib/thoth/view/page/new.rhtml +15 -0
- data/lib/thoth/view/post/comments.rhtml +12 -0
- data/lib/thoth/view/post/compact.rhtml +48 -0
- data/lib/thoth/view/post/delete.rhtml +15 -0
- data/lib/thoth/view/post/edit.rhtml +15 -0
- data/lib/thoth/view/post/form.rhtml +83 -0
- data/lib/thoth/view/post/index.rhtml +48 -0
- data/lib/thoth/view/post/list.rhtml +61 -0
- data/lib/thoth/view/post/new.rhtml +15 -0
- data/lib/thoth/view/post/tiny.rhtml +4 -0
- data/lib/thoth/view/search/index.rhtml +45 -0
- data/lib/thoth/view/tag/index.rhtml +34 -0
- data/lib/thoth/view/thoth/css.rhtml +9 -0
- data/lib/thoth/view/thoth/footer.rhtml +15 -0
- data/lib/thoth/view/thoth/header.rhtml +23 -0
- data/lib/thoth/view/thoth/index.rhtml +11 -0
- data/lib/thoth/view/thoth/js.rhtml +6 -0
- data/lib/thoth/view/thoth/sidebar.rhtml +38 -0
- data/lib/thoth/view/thoth/util/pager.rhtml +23 -0
- data/lib/thoth/view/thoth/util/simple_pager.rhtml +15 -0
- data/lib/thoth/view/thoth/util/table_sortheader.rhtml +20 -0
- data/lib/thoth.rb +394 -0
- metadata +409 -0
data/lib/thoth/config.rb
ADDED
@@ -0,0 +1,158 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (c) 2009 Ryan Grove <ryan@wonko.com>
|
3
|
+
# All rights reserved.
|
4
|
+
#
|
5
|
+
# Redistribution and use in source and binary forms, with or without
|
6
|
+
# modification, are permitted provided that the following conditions are met:
|
7
|
+
#
|
8
|
+
# * Redistributions of source code must retain the above copyright notice,
|
9
|
+
# this list of conditions and the following disclaimer.
|
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
|
+
# * Neither the name of this project nor the names of its contributors may be
|
14
|
+
# used to endorse or promote products derived from this software without
|
15
|
+
# specific prior written permission.
|
16
|
+
#
|
17
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
18
|
+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
19
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
20
|
+
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
|
21
|
+
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
22
|
+
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
23
|
+
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
24
|
+
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
25
|
+
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
26
|
+
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
27
|
+
#++
|
28
|
+
|
29
|
+
module Thoth
|
30
|
+
|
31
|
+
module Config; class << self
|
32
|
+
|
33
|
+
# Adds the specified config Hash to Thoth's config lookup chain. Any
|
34
|
+
# configuration values in _config_ will be used as defaults unless they're
|
35
|
+
# specified earlier in the lookup chain (i.e. in Thoth's config file).
|
36
|
+
def <<(config)
|
37
|
+
raise ArgumentError, "config must be a Hash" unless config.is_a?(Hash)
|
38
|
+
|
39
|
+
(@lookup ||= []) << config
|
40
|
+
cache_config
|
41
|
+
|
42
|
+
@lookup
|
43
|
+
end
|
44
|
+
|
45
|
+
# Loads the specified configuration file.
|
46
|
+
def load(file)
|
47
|
+
raise Thoth::Error, "Config file not found: #{file}" unless File.file?(file)
|
48
|
+
|
49
|
+
@live = {
|
50
|
+
'db' => "sqlite:///#{HOME_DIR}/db/live.db",
|
51
|
+
|
52
|
+
'site' => {
|
53
|
+
'name' => "New Thoth Blog",
|
54
|
+
'desc' => "Thoth is awesome.",
|
55
|
+
'url' => "http://localhost:7000/",
|
56
|
+
|
57
|
+
'core_js' => [
|
58
|
+
'http://yui.yahooapis.com/2.8.0/build/yahoo-dom-event/yahoo-dom-event.js',
|
59
|
+
'/js/thoth.js'
|
60
|
+
],
|
61
|
+
|
62
|
+
'css' => [],
|
63
|
+
'js' => [],
|
64
|
+
|
65
|
+
'enable_comments' => true,
|
66
|
+
'enable_sitemap' => true,
|
67
|
+
|
68
|
+
'gravatar' => {
|
69
|
+
'enabled' => true,
|
70
|
+
'default' => "identicon",
|
71
|
+
'rating' => "g",
|
72
|
+
'size' => 32
|
73
|
+
}
|
74
|
+
},
|
75
|
+
|
76
|
+
'admin' => {
|
77
|
+
'name' => "John Doe",
|
78
|
+
'email' => "",
|
79
|
+
'user' => "thoth",
|
80
|
+
'pass' => "thoth",
|
81
|
+
'seed' => "6d552ac197a862b82b85868d6c245feb"
|
82
|
+
},
|
83
|
+
|
84
|
+
'plugins' => [],
|
85
|
+
|
86
|
+
'media' => File.join(HOME_DIR, 'media'),
|
87
|
+
|
88
|
+
'server' => {
|
89
|
+
'adapter' => 'webrick',
|
90
|
+
'address' => '0.0.0.0',
|
91
|
+
'port' => 7000,
|
92
|
+
'enable_cache' => true,
|
93
|
+
'enable_minify' => true,
|
94
|
+
'error_log' => File.join(HOME_DIR, 'log', 'error.log'),
|
95
|
+
|
96
|
+
'memcache' => {
|
97
|
+
'enabled' => false,
|
98
|
+
'servers' => ['localhost:11211:1']
|
99
|
+
}
|
100
|
+
},
|
101
|
+
|
102
|
+
'timestamp' => {
|
103
|
+
'long' => "%A %B %d, %Y @ %I:%M %p (%Z)",
|
104
|
+
'short' => "%Y-%m-%d %I:%M"
|
105
|
+
}
|
106
|
+
}
|
107
|
+
|
108
|
+
@dev = {
|
109
|
+
'db' => "sqlite:///#{HOME_DIR}/db/dev.db",
|
110
|
+
|
111
|
+
'server' => {
|
112
|
+
'enable_cache' => false,
|
113
|
+
'enable_minify' => false
|
114
|
+
}
|
115
|
+
}
|
116
|
+
|
117
|
+
begin
|
118
|
+
config = YAML.load(Erubis::Eruby.new(File.read(file)).result(binding)) || {}
|
119
|
+
rescue => e
|
120
|
+
raise Thoth::ConfigError, "Config error in #{file}: #{e}"
|
121
|
+
end
|
122
|
+
|
123
|
+
@lookup ||= if Thoth.trait[:mode] == :production
|
124
|
+
[config['live'] || {}, @live]
|
125
|
+
else
|
126
|
+
[config['dev'] || {}, config['live'] || {}, @dev, @live]
|
127
|
+
end
|
128
|
+
|
129
|
+
cache_config
|
130
|
+
end
|
131
|
+
|
132
|
+
def method_missing(name)
|
133
|
+
(@cached || {})[name.to_s] || {}
|
134
|
+
end
|
135
|
+
|
136
|
+
private
|
137
|
+
|
138
|
+
# Merges configs such that those earlier in the lookup chain override those
|
139
|
+
# later in the chain.
|
140
|
+
def cache_config
|
141
|
+
@cached = {}
|
142
|
+
|
143
|
+
@lookup.reverse.each do |c|
|
144
|
+
c.each {|k, v| @cached[k] = config_merge(@cached[k] || {}, v) }
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
def config_merge(master, value)
|
149
|
+
if value.is_a?(Hash)
|
150
|
+
value.each {|k, v| master[k] = config_merge(master[k] || {}, v) }
|
151
|
+
return master
|
152
|
+
end
|
153
|
+
|
154
|
+
value
|
155
|
+
end
|
156
|
+
|
157
|
+
end; end
|
158
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (c) 2017 John Pagonis <john@pagonis.org>
|
3
|
+
# Copyright (c) 2009 Ryan Grove <ryan@wonko.com>
|
4
|
+
# All rights reserved.
|
5
|
+
#
|
6
|
+
# Redistribution and use in source and binary forms, with or without
|
7
|
+
# modification, are permitted provided that the following conditions are met:
|
8
|
+
#
|
9
|
+
# * Redistributions of source code must retain the above copyright notice,
|
10
|
+
# this list of conditions and the following disclaimer.
|
11
|
+
# * Redistributions in binary form must reproduce the above copyright notice,
|
12
|
+
# this list of conditions and the following disclaimer in the documentation
|
13
|
+
# and/or other materials provided with the distribution.
|
14
|
+
# * Neither the name of this project nor the names of its contributors may be
|
15
|
+
# 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"
|
19
|
+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
20
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
21
|
+
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
|
22
|
+
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
23
|
+
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
24
|
+
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
25
|
+
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
26
|
+
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
27
|
+
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
28
|
+
#++
|
29
|
+
|
30
|
+
module Thoth
|
31
|
+
class AdminController < Controller
|
32
|
+
map '/admin'
|
33
|
+
|
34
|
+
def index
|
35
|
+
if auth_key_valid?
|
36
|
+
@title = 'Welcome to Thoth'
|
37
|
+
@public_root = PUBLIC_DIR
|
38
|
+
@view_root = VIEW_DIR
|
39
|
+
else
|
40
|
+
@title = 'Login'
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
# Authenticates an admin login by checking the _username_ and _password_
|
45
|
+
# request parameters against the +ADMIN_USER+ and +ADMIN_PASS+ values in the
|
46
|
+
# Thoth config file.
|
47
|
+
#
|
48
|
+
# On a successful login, an auth cookie named <em>thoth_auth</em> will be
|
49
|
+
# set and the user will be redirected to the referring URL. On an
|
50
|
+
# unsuccessful login attempt, a flash message named <em>login_error</em>
|
51
|
+
# will be set and the user will be redirected to the referring URL without
|
52
|
+
# an auth cookie.
|
53
|
+
def login
|
54
|
+
username, password = request[:username, :password]
|
55
|
+
|
56
|
+
if username == Config.admin['user'] && password == Config.admin['pass']
|
57
|
+
# Set an auth cookie that expires in two weeks.
|
58
|
+
response.set_cookie('thoth_auth', :expires => Time.now + 1209600,
|
59
|
+
:path => '/', :value => auth_key)
|
60
|
+
|
61
|
+
redirect_referrer
|
62
|
+
end
|
63
|
+
|
64
|
+
flash[:error] = 'Invalid username or password.'
|
65
|
+
redirect_referrer
|
66
|
+
end
|
67
|
+
|
68
|
+
# Deletes the <em>thoth_auth</em> cookie and redirects to the home page.
|
69
|
+
def logout
|
70
|
+
response.delete_cookie('thoth_auth', :path => '/')
|
71
|
+
redirect(MainController.r())
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (c) 2009 Ryan Grove <ryan@wonko.com>
|
3
|
+
# All rights reserved.
|
4
|
+
#
|
5
|
+
# Redistribution and use in source and binary forms, with or without
|
6
|
+
# modification, are permitted provided that the following conditions are met:
|
7
|
+
#
|
8
|
+
# * Redistributions of source code must retain the above copyright notice,
|
9
|
+
# this list of conditions and the following disclaimer.
|
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
|
+
# * Neither the name of this project nor the names of its contributors may be
|
14
|
+
# used to endorse or promote products derived from this software without
|
15
|
+
# specific prior written permission.
|
16
|
+
#
|
17
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
18
|
+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
19
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
20
|
+
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
|
21
|
+
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
22
|
+
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
23
|
+
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
24
|
+
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
25
|
+
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
26
|
+
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
27
|
+
#++
|
28
|
+
|
29
|
+
module Thoth
|
30
|
+
class CommentApiController < Controller
|
31
|
+
map '/api/comment'
|
32
|
+
layout nil
|
33
|
+
|
34
|
+
# Deletes the specified comment. Returns an HTTP 200 response on success, an
|
35
|
+
# HTTP 500 response on failure, or an HTTP 404 response if the specified
|
36
|
+
# comment does not exist.
|
37
|
+
#
|
38
|
+
# ==== Query Parameters (POST only)
|
39
|
+
#
|
40
|
+
# id:: comment id
|
41
|
+
# token:: form token
|
42
|
+
#
|
43
|
+
# ==== Sample Response
|
44
|
+
#
|
45
|
+
# ===== Success
|
46
|
+
#
|
47
|
+
# {"success":true}
|
48
|
+
#
|
49
|
+
# ===== Failure
|
50
|
+
#
|
51
|
+
# {"error":"The comment could not be deleted due to a database error."}
|
52
|
+
#
|
53
|
+
def delete
|
54
|
+
error_403 unless auth_key_valid? && form_token_valid?
|
55
|
+
error_405 unless request.post?
|
56
|
+
error_404 unless request[:id] && @comment = Comment[request[:id]]
|
57
|
+
|
58
|
+
response['Content-Type'] = 'application/json'
|
59
|
+
|
60
|
+
@comment.deleted = true
|
61
|
+
|
62
|
+
if @comment.save(:changed => true, :validate => false)
|
63
|
+
Ramaze::Cache.action.clear
|
64
|
+
Ramaze::Cache.cache_helper_value.clear
|
65
|
+
JSON.generate({:success => true})
|
66
|
+
else
|
67
|
+
respond(JSON.generate({
|
68
|
+
:error => 'The comment could not be deleted due to a database error.'
|
69
|
+
}, 500))
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,134 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (c) 2009 Ryan Grove <ryan@wonko.com>
|
3
|
+
# All rights reserved.
|
4
|
+
#
|
5
|
+
# Redistribution and use in source and binary forms, with or without
|
6
|
+
# modification, are permitted provided that the following conditions are met:
|
7
|
+
#
|
8
|
+
# * Redistributions of source code must retain the above copyright notice,
|
9
|
+
# this list of conditions and the following disclaimer.
|
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
|
+
# * Neither the name of this project nor the names of its contributors may be
|
14
|
+
# used to endorse or promote products derived from this software without
|
15
|
+
# specific prior written permission.
|
16
|
+
#
|
17
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
18
|
+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
19
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
20
|
+
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
|
21
|
+
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
22
|
+
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
23
|
+
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
24
|
+
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
25
|
+
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
26
|
+
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
27
|
+
#++
|
28
|
+
|
29
|
+
module Thoth
|
30
|
+
class PageApiController < Controller
|
31
|
+
map '/api/page'
|
32
|
+
layout nil
|
33
|
+
|
34
|
+
# Returns a response indicating whether the specified page name is valid and
|
35
|
+
# not already taken. Returns an HTTP 200 response on success.
|
36
|
+
#
|
37
|
+
# ==== Query Parameters
|
38
|
+
#
|
39
|
+
# name:: page name to check
|
40
|
+
#
|
41
|
+
# ==== Sample Response
|
42
|
+
#
|
43
|
+
# {"valid":true,"unique":true}
|
44
|
+
#
|
45
|
+
def check_name
|
46
|
+
error_403 unless auth_key_valid?
|
47
|
+
|
48
|
+
unless request[:name] && request[:name].length > 0
|
49
|
+
error_400('Missing required parameter: name')
|
50
|
+
end
|
51
|
+
|
52
|
+
response['Content-Type'] = 'application/json'
|
53
|
+
|
54
|
+
name = request[:name].to_s
|
55
|
+
|
56
|
+
JSON.generate({
|
57
|
+
:valid => Page.name_valid?(name),
|
58
|
+
:unique => Page.name_unique?(name)
|
59
|
+
})
|
60
|
+
end
|
61
|
+
|
62
|
+
# Suggests a valid and unique name for the specified page title. Returns an
|
63
|
+
# HTTP 200 response on success.
|
64
|
+
#
|
65
|
+
# ==== Query Parameters
|
66
|
+
#
|
67
|
+
# title:: page title
|
68
|
+
#
|
69
|
+
# ==== Sample Response
|
70
|
+
#
|
71
|
+
# {"name":"ninjas-are-awesome"}
|
72
|
+
#
|
73
|
+
def suggest_name
|
74
|
+
error_403 unless auth_key_valid?
|
75
|
+
|
76
|
+
unless request[:title] && request[:title].length > 0
|
77
|
+
error_400('Missing required parameter: title')
|
78
|
+
end
|
79
|
+
|
80
|
+
response['Content-Type'] = 'application/json'
|
81
|
+
|
82
|
+
JSON.generate({"name" => Page.suggest_name(request[:title])})
|
83
|
+
end
|
84
|
+
|
85
|
+
# Sets the display position of the specified page. If the new position is
|
86
|
+
# already in use by another page, that page's position (and any others) will
|
87
|
+
# be adjusted as necessary. Returns an HTTP 200 response on success. This
|
88
|
+
# action only accepts POST requests.
|
89
|
+
#
|
90
|
+
# ==== POST Parameters
|
91
|
+
#
|
92
|
+
# id:: page id
|
93
|
+
# position:: new display position
|
94
|
+
#
|
95
|
+
# ==== Sample Response
|
96
|
+
#
|
97
|
+
# Indicates that the display position for page id 42 was successfully set to
|
98
|
+
# 3.
|
99
|
+
#
|
100
|
+
# {"id":42,"position":3}
|
101
|
+
#
|
102
|
+
def set_position
|
103
|
+
error_403 unless auth_key_valid?
|
104
|
+
error_405 unless request.post?
|
105
|
+
|
106
|
+
[:id, :position].each do |param|
|
107
|
+
unless request[param] && request[param].length > 0
|
108
|
+
error_400("Missing required parameter: #{param}")
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
id = request[:id].to_i
|
113
|
+
position = request[:position].to_i
|
114
|
+
|
115
|
+
unless page = Page[id]
|
116
|
+
error_400("Invalid page id: #{id}")
|
117
|
+
end
|
118
|
+
|
119
|
+
begin
|
120
|
+
Page.normalize_positions
|
121
|
+
Page.set_position(page, position)
|
122
|
+
|
123
|
+
rescue => e
|
124
|
+
error_400("Error setting page position: #{e}")
|
125
|
+
end
|
126
|
+
|
127
|
+
JSON.generate({
|
128
|
+
:id => id,
|
129
|
+
:position => position
|
130
|
+
})
|
131
|
+
end
|
132
|
+
|
133
|
+
end
|
134
|
+
end
|
@@ -0,0 +1,122 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (c) 2009 Ryan Grove <ryan@wonko.com>
|
3
|
+
# All rights reserved.
|
4
|
+
#
|
5
|
+
# Redistribution and use in source and binary forms, with or without
|
6
|
+
# modification, are permitted provided that the following conditions are met:
|
7
|
+
#
|
8
|
+
# * Redistributions of source code must retain the above copyright notice,
|
9
|
+
# this list of conditions and the following disclaimer.
|
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
|
+
# * Neither the name of this project nor the names of its contributors may be
|
14
|
+
# used to endorse or promote products derived from this software without
|
15
|
+
# specific prior written permission.
|
16
|
+
#
|
17
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
18
|
+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
19
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
20
|
+
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
|
21
|
+
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
22
|
+
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
23
|
+
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
24
|
+
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
25
|
+
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
26
|
+
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
27
|
+
#++
|
28
|
+
|
29
|
+
module Thoth
|
30
|
+
class PostApiController < Controller
|
31
|
+
map '/api/post'
|
32
|
+
layout nil
|
33
|
+
|
34
|
+
# Returns a response indicating whether the specified post name is valid and
|
35
|
+
# not already taken. Returns an HTTP 200 response on success or an HTTP 500
|
36
|
+
# response on error.
|
37
|
+
#
|
38
|
+
# ==== Query Parameters
|
39
|
+
#
|
40
|
+
# name:: post name to check
|
41
|
+
#
|
42
|
+
# ==== Sample Response
|
43
|
+
#
|
44
|
+
# {"valid":true,"unique":true}
|
45
|
+
#
|
46
|
+
def check_name
|
47
|
+
error_403 unless auth_key_valid?
|
48
|
+
|
49
|
+
unless request[:name] && request[:name].length > 0
|
50
|
+
error_400('Missing required parameter: name')
|
51
|
+
end
|
52
|
+
|
53
|
+
response['Content-Type'] = 'application/json'
|
54
|
+
|
55
|
+
name = request[:name].to_s
|
56
|
+
|
57
|
+
JSON.generate({
|
58
|
+
:valid => Post.name_valid?(name),
|
59
|
+
:unique => Post.name_unique?(name)
|
60
|
+
})
|
61
|
+
end
|
62
|
+
|
63
|
+
# Deletes the specified comment. Returns an HTTP 200 response on success, an
|
64
|
+
# HTTP 500 response on error, or an HTTP 404 response if the specified
|
65
|
+
# comment does not exist.
|
66
|
+
#
|
67
|
+
# ==== Query Parameters (POST only)
|
68
|
+
#
|
69
|
+
# id:: comment id
|
70
|
+
# token:: form token
|
71
|
+
#
|
72
|
+
# ==== Sample Response
|
73
|
+
#
|
74
|
+
# ===== Success
|
75
|
+
#
|
76
|
+
# {"success":true}
|
77
|
+
#
|
78
|
+
# ===== Failure
|
79
|
+
#
|
80
|
+
# {"error":"The comment could not be deleted due to a database error."}
|
81
|
+
#
|
82
|
+
def delete
|
83
|
+
error_403 unless auth_key_valid? && form_token_valid?
|
84
|
+
error_405 unless request.post?
|
85
|
+
error_404 unless request[:id] && @comment = Comment[request[:id]]
|
86
|
+
|
87
|
+
response['Content-Type'] = 'application/json'
|
88
|
+
|
89
|
+
if @comment.destroy
|
90
|
+
Ramaze::Cache.action.clear
|
91
|
+
JSON.generate({:success => true})
|
92
|
+
else
|
93
|
+
respond(JSON.generate({
|
94
|
+
:error => 'The comment could not be deleted due to a database error.'
|
95
|
+
}, 500))
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
# Suggests a valid and unique name for the specified post title. Returns an
|
100
|
+
# HTTP 200 response on success or an HTTP 500 response on error.
|
101
|
+
#
|
102
|
+
# ==== Query Parameters
|
103
|
+
#
|
104
|
+
# title:: post title
|
105
|
+
#
|
106
|
+
# ==== Sample Response
|
107
|
+
#
|
108
|
+
# {"name":"ninjas-are-awesome"}
|
109
|
+
#
|
110
|
+
def suggest_name
|
111
|
+
error_403 unless auth_key_valid?
|
112
|
+
|
113
|
+
unless request[:title] && request[:title].length > 0
|
114
|
+
error_400('Missing required parameter: title')
|
115
|
+
end
|
116
|
+
|
117
|
+
response['Content-Type'] = 'application/json'
|
118
|
+
|
119
|
+
JSON.generate({"name" => Post.suggest_name(request[:title])})
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (c) 2009 Ryan Grove <ryan@wonko.com>
|
3
|
+
# All rights reserved.
|
4
|
+
#
|
5
|
+
# Redistribution and use in source and binary forms, with or without
|
6
|
+
# modification, are permitted provided that the following conditions are met:
|
7
|
+
#
|
8
|
+
# * Redistributions of source code must retain the above copyright notice,
|
9
|
+
# this list of conditions and the following disclaimer.
|
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
|
+
# * Neither the name of this project nor the names of its contributors may be
|
14
|
+
# used to endorse or promote products derived from this software without
|
15
|
+
# specific prior written permission.
|
16
|
+
#
|
17
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
18
|
+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
19
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
20
|
+
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
|
21
|
+
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
22
|
+
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
23
|
+
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
24
|
+
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
25
|
+
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
26
|
+
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
27
|
+
#++
|
28
|
+
|
29
|
+
module Thoth
|
30
|
+
class TagApiController < Controller
|
31
|
+
map '/api/tag'
|
32
|
+
layout nil
|
33
|
+
|
34
|
+
# Returns a JSON array of existing tag names and usage counts for tags that
|
35
|
+
# begin with the specified query string.
|
36
|
+
#
|
37
|
+
# ==== Query Parameters
|
38
|
+
#
|
39
|
+
# q:: query string
|
40
|
+
# limit:: (optional) maximum number of tags to return
|
41
|
+
#
|
42
|
+
# ==== Sample Response
|
43
|
+
#
|
44
|
+
# [["foo",15],["foobar",11],["foosball",2]]
|
45
|
+
def suggest
|
46
|
+
error_403 unless auth_key_valid?
|
47
|
+
|
48
|
+
unless request[:q]
|
49
|
+
error_400('Missing required parameter: q')
|
50
|
+
end
|
51
|
+
|
52
|
+
query = request[:q].lstrip
|
53
|
+
limit = request[:limit] ? request[:limit].to_i : 1000
|
54
|
+
|
55
|
+
response['Content-Type'] = 'application/json'
|
56
|
+
JSON.generate(Tag.suggest(query, limit))
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (c) 2009 Ryan Grove <ryan@wonko.com>
|
3
|
+
# All rights reserved.
|
4
|
+
#
|
5
|
+
# Redistribution and use in source and binary forms, with or without
|
6
|
+
# modification, are permitted provided that the following conditions are met:
|
7
|
+
#
|
8
|
+
# * Redistributions of source code must retain the above copyright notice,
|
9
|
+
# this list of conditions and the following disclaimer.
|
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
|
+
# * Neither the name of this project nor the names of its contributors may be
|
14
|
+
# used to endorse or promote products derived from this software without
|
15
|
+
# specific prior written permission.
|
16
|
+
#
|
17
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
18
|
+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
19
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
20
|
+
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
|
21
|
+
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
22
|
+
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
23
|
+
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
24
|
+
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
25
|
+
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
26
|
+
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
27
|
+
#++
|
28
|
+
|
29
|
+
module Thoth
|
30
|
+
class ArchiveController < Controller
|
31
|
+
map '/archive'
|
32
|
+
helper :cache, :pagination
|
33
|
+
|
34
|
+
cache_action(:method => :index, :ttl => 120) { auth_key_valid? }
|
35
|
+
|
36
|
+
def index(page = 1)
|
37
|
+
page = page.to_i
|
38
|
+
error_404 unless page >= 1
|
39
|
+
|
40
|
+
@posts = Post.recent(page, 10)
|
41
|
+
|
42
|
+
error_404 if page > @posts.page_count && @posts.page_count > 0
|
43
|
+
|
44
|
+
@title = "#{Config.site['name']} Archives (page #{page} of " <<
|
45
|
+
"#{@posts.page_count > 0 ? @posts.page_count : 1})"
|
46
|
+
|
47
|
+
@pager = pager(@posts)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|