cortex-reaver 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (128) hide show
  1. data/LICENSE +25 -0
  2. data/README +48 -0
  3. data/bin/console +11 -0
  4. data/bin/cortex_reaver +110 -0
  5. data/bin/import.rb +78 -0
  6. data/lib/cortex_reaver.rb +114 -0
  7. data/lib/cortex_reaver/config.rb +21 -0
  8. data/lib/cortex_reaver/controller/comment.rb +113 -0
  9. data/lib/cortex_reaver/controller/config.rb +14 -0
  10. data/lib/cortex_reaver/controller/journal.rb +40 -0
  11. data/lib/cortex_reaver/controller/main.rb +56 -0
  12. data/lib/cortex_reaver/controller/page.rb +34 -0
  13. data/lib/cortex_reaver/controller/photograph.rb +45 -0
  14. data/lib/cortex_reaver/controller/project.rb +40 -0
  15. data/lib/cortex_reaver/controller/tag.rb +67 -0
  16. data/lib/cortex_reaver/controller/user.rb +71 -0
  17. data/lib/cortex_reaver/helper/activity.rb +9 -0
  18. data/lib/cortex_reaver/helper/attachments.rb +139 -0
  19. data/lib/cortex_reaver/helper/auth.rb +45 -0
  20. data/lib/cortex_reaver/helper/canonical.rb +55 -0
  21. data/lib/cortex_reaver/helper/crud.rb +317 -0
  22. data/lib/cortex_reaver/helper/date.rb +29 -0
  23. data/lib/cortex_reaver/helper/error.rb +14 -0
  24. data/lib/cortex_reaver/helper/feeds.rb +88 -0
  25. data/lib/cortex_reaver/helper/form.rb +114 -0
  26. data/lib/cortex_reaver/helper/navigation.rb +142 -0
  27. data/lib/cortex_reaver/helper/photographs.rb +25 -0
  28. data/lib/cortex_reaver/helper/tags.rb +47 -0
  29. data/lib/cortex_reaver/helper/workflow.rb +27 -0
  30. data/lib/cortex_reaver/migrations/001_users.rb +24 -0
  31. data/lib/cortex_reaver/migrations/002_pages.rb +29 -0
  32. data/lib/cortex_reaver/migrations/003_journals.rb +26 -0
  33. data/lib/cortex_reaver/migrations/004_photographs.rb +24 -0
  34. data/lib/cortex_reaver/migrations/005_projects.rb +27 -0
  35. data/lib/cortex_reaver/migrations/006_tags.rb +64 -0
  36. data/lib/cortex_reaver/migrations/007_comments.rb +40 -0
  37. data/lib/cortex_reaver/migrations/008_config.rb +23 -0
  38. data/lib/cortex_reaver/model/comment.rb +109 -0
  39. data/lib/cortex_reaver/model/journal.rb +53 -0
  40. data/lib/cortex_reaver/model/page.rb +87 -0
  41. data/lib/cortex_reaver/model/photograph.rb +133 -0
  42. data/lib/cortex_reaver/model/project.rb +49 -0
  43. data/lib/cortex_reaver/model/tag.rb +72 -0
  44. data/lib/cortex_reaver/model/user.rb +147 -0
  45. data/lib/cortex_reaver/public/css/admin.css +45 -0
  46. data/lib/cortex_reaver/public/css/custom.css +0 -0
  47. data/lib/cortex_reaver/public/css/form.css +51 -0
  48. data/lib/cortex_reaver/public/css/main.css +325 -0
  49. data/lib/cortex_reaver/public/css/photo.css +113 -0
  50. data/lib/cortex_reaver/public/css/ramaze_error.css +90 -0
  51. data/lib/cortex_reaver/public/css/text.css +25 -0
  52. data/lib/cortex_reaver/public/dispatch.fcgi +11 -0
  53. data/lib/cortex_reaver/public/images/CortexReaver.gif +0 -0
  54. data/lib/cortex_reaver/public/images/atom-xml-icon.png +0 -0
  55. data/lib/cortex_reaver/public/images/body.png +0 -0
  56. data/lib/cortex_reaver/public/images/border_bottom.png +0 -0
  57. data/lib/cortex_reaver/public/images/border_bottom_left.png +0 -0
  58. data/lib/cortex_reaver/public/images/border_bottom_right.png +0 -0
  59. data/lib/cortex_reaver/public/images/border_left.png +0 -0
  60. data/lib/cortex_reaver/public/images/border_right.png +0 -0
  61. data/lib/cortex_reaver/public/images/border_top.png +0 -0
  62. data/lib/cortex_reaver/public/images/border_top_left.png +0 -0
  63. data/lib/cortex_reaver/public/images/border_top_right.png +0 -0
  64. data/lib/cortex_reaver/public/images/comment.gif +0 -0
  65. data/lib/cortex_reaver/public/images/dark_trans.png +0 -0
  66. data/lib/cortex_reaver/public/images/delete.gif +0 -0
  67. data/lib/cortex_reaver/public/images/edit.gif +0 -0
  68. data/lib/cortex_reaver/public/images/header.png +0 -0
  69. data/lib/cortex_reaver/public/images/header.xcf +0 -0
  70. data/lib/cortex_reaver/public/images/header_background.png +0 -0
  71. data/lib/cortex_reaver/public/images/parent.gif +0 -0
  72. data/lib/cortex_reaver/public/images/rss-xml-icon.png +0 -0
  73. data/lib/cortex_reaver/public/images/sections.png +0 -0
  74. data/lib/cortex_reaver/public/images/sections_highlight.png +0 -0
  75. data/lib/cortex_reaver/public/js/admin.js +36 -0
  76. data/lib/cortex_reaver/public/js/cookie.js +27 -0
  77. data/lib/cortex_reaver/public/js/jquery.js +32 -0
  78. data/lib/cortex_reaver/public/js/photo.js +33 -0
  79. data/lib/cortex_reaver/snippets/array.rb +7 -0
  80. data/lib/cortex_reaver/snippets/ramaze/dispatcher/file.rb +37 -0
  81. data/lib/cortex_reaver/support/attachments.rb +235 -0
  82. data/lib/cortex_reaver/support/cached_rendering.rb +79 -0
  83. data/lib/cortex_reaver/support/canonical.rb +107 -0
  84. data/lib/cortex_reaver/support/comments.rb +69 -0
  85. data/lib/cortex_reaver/support/pagination.rb +38 -0
  86. data/lib/cortex_reaver/support/renderer.rb +196 -0
  87. data/lib/cortex_reaver/support/sequenceable.rb +248 -0
  88. data/lib/cortex_reaver/support/tags.rb +108 -0
  89. data/lib/cortex_reaver/support/timestamps.rb +33 -0
  90. data/lib/cortex_reaver/version.rb +8 -0
  91. data/lib/cortex_reaver/view/adminbox.rhtml +56 -0
  92. data/lib/cortex_reaver/view/blank_layout.rhtml +46 -0
  93. data/lib/cortex_reaver/view/comments/comment.rhtml +34 -0
  94. data/lib/cortex_reaver/view/comments/form.rhtml +25 -0
  95. data/lib/cortex_reaver/view/comments/list.rhtml +5 -0
  96. data/lib/cortex_reaver/view/comments/post_form.rhtml +36 -0
  97. data/lib/cortex_reaver/view/config/form.rhtml +10 -0
  98. data/lib/cortex_reaver/view/error.rhtml +72 -0
  99. data/lib/cortex_reaver/view/journals/form.rhtml +12 -0
  100. data/lib/cortex_reaver/view/journals/journal.rhtml +39 -0
  101. data/lib/cortex_reaver/view/journals/list.rhtml +33 -0
  102. data/lib/cortex_reaver/view/journals/short.rhtml +3 -0
  103. data/lib/cortex_reaver/view/journals/show.rhtml +5 -0
  104. data/lib/cortex_reaver/view/pages/form.rhtml +12 -0
  105. data/lib/cortex_reaver/view/pages/list.rhtml +26 -0
  106. data/lib/cortex_reaver/view/pages/show.rhtml +12 -0
  107. data/lib/cortex_reaver/view/photographs/atom_fragment.rhtml +82 -0
  108. data/lib/cortex_reaver/view/photographs/form.rhtml +19 -0
  109. data/lib/cortex_reaver/view/photographs/grid.rhtml +36 -0
  110. data/lib/cortex_reaver/view/photographs/list.rhtml +9 -0
  111. data/lib/cortex_reaver/view/photographs/short.rhtml +3 -0
  112. data/lib/cortex_reaver/view/photographs/show.rhtml +114 -0
  113. data/lib/cortex_reaver/view/photographs/sidebar.rhtml +7 -0
  114. data/lib/cortex_reaver/view/projects/form.rhtml +13 -0
  115. data/lib/cortex_reaver/view/projects/list.rhtml +27 -0
  116. data/lib/cortex_reaver/view/projects/show.rhtml +38 -0
  117. data/lib/cortex_reaver/view/tags/form.rhtml +9 -0
  118. data/lib/cortex_reaver/view/tags/list.rhtml +28 -0
  119. data/lib/cortex_reaver/view/tags/show.rhtml +51 -0
  120. data/lib/cortex_reaver/view/text_layout.rhtml +78 -0
  121. data/lib/cortex_reaver/view/users/form.rhtml +16 -0
  122. data/lib/cortex_reaver/view/users/list.rhtml +38 -0
  123. data/lib/cortex_reaver/view/users/login.rhtml +13 -0
  124. data/lib/cortex_reaver/view/users/register.rhtml +13 -0
  125. data/lib/cortex_reaver/view/users/show.rhtml +37 -0
  126. data/lib/cortex_reaver/view/users/user.rhtml +35 -0
  127. data/lib/proto/cortex_reaver.yaml +28 -0
  128. metadata +285 -0
@@ -0,0 +1,45 @@
1
+ module Ramaze
2
+ module Helper
3
+ # Provides authentication services
4
+ module Auth
5
+ # Is the current user an admin?
6
+ def admin?
7
+ u = session[:user] and u.admin?
8
+ end
9
+
10
+ # Tries to log in a user by login and password. If successful, sets
11
+ # session[:user] to the user and returns that user. Otherwise returns
12
+ # false.
13
+ def do_login(login, password)
14
+ if user = CortexReaver::User.authenticate(login, password)
15
+ # Successful login
16
+ session[:user] = user
17
+ else
18
+ false
19
+ end
20
+ end
21
+
22
+ # Log out the current user, and returns the user object.
23
+ def do_logout
24
+ session.delete :user
25
+ end
26
+
27
+ def require_admin
28
+ if session[:user] and session[:user].admin?
29
+ true
30
+ elsif session[:user]
31
+ flash[:error] = "You must have administrative privileges to do this."
32
+ redirect :/
33
+ else
34
+ flash[:notice] = "Please log in first."
35
+ session[:target_uri] = request.request_uri
36
+ redirect R('/users', :login)
37
+ end
38
+ end
39
+
40
+ def error_403
41
+ respond 'Forbidden', 403
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,55 @@
1
+ module Ramaze
2
+ module Helper
3
+ module Canonical
4
+ Helper::LOOKUP << self
5
+
6
+ # Returns the canonical name for this model, given a candidate new name.
7
+ def canonicalize
8
+ respond self.class.const_get('MODEL').canonicalize(
9
+ request[:new],
10
+ request[:id]
11
+ )
12
+ end
13
+
14
+ private
15
+
16
+ # Adds an AJAX-ified name field for a model.
17
+ def live_name_field(model, opts={:name => 'name', :watch => 'title'})
18
+ name = opts[:name]
19
+ watch = opts[:watch]
20
+ title = opts[:title] || name.to_s.titleize
21
+
22
+ s = "<p><label for=\"#{name}\">#{title}</label>"
23
+ s << "<input name=\"#{name}\" id=\"#{name}\" type=\"text\" value=\"#{attr_h(model.send(opts[:name]))}\" /></p>"
24
+
25
+ s << <<EOF
26
+ <script type="text/javascript">
27
+ /* <![CDATA[ */
28
+
29
+ // Updates the "name" field as the watched field changes.
30
+ $('##{watch}').change(function () {
31
+ $.get('#{Rs('canonicalize')}', {
32
+ new: $('##{watch}').val(),
33
+ id: '#{model.id}'
34
+ }, function(response) {
35
+ $('##{name}').val(response);
36
+ })
37
+ });
38
+
39
+ // Canonicalizes the name when we're done, just to make sure.
40
+ $('##{name}').blur(function() {
41
+ $.get('#{Rs('canonicalize')}', {
42
+ new: $('##{name}').val(),
43
+ id: '#{model.id}'
44
+ }, function(response) {
45
+ $('##{name}').val(response);
46
+ })
47
+ });
48
+
49
+ /* ]]> */
50
+ </script>
51
+ EOF
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,317 @@
1
+ module Ramaze
2
+ module Helper
3
+ # Provides list, create, read, update, and delete functionality for Cortex
4
+ # Reaver. Centralizes the lookup and database logic for re-use across
5
+ # several models.
6
+ #
7
+ # Requires pagination, auth, workflow, and feeds
8
+ module Crud
9
+ require 'builder'
10
+
11
+ Helper::LOOKUP << self
12
+
13
+ def self.included(base)
14
+ base.instance_eval do
15
+ # Provides on_save, on_create, on_update callbacks for controllers,
16
+ # which defines how the controller CRUD sets attributes on the
17
+ # primary model.
18
+
19
+ # This block is called when a new model is being created. The model
20
+ # and request are passed to the block. The resulting model is stored
21
+ # in the database. Example:
22
+ #
23
+ # JournalController.on_save do |journal, request|
24
+ # journal.title = request[:title]
25
+ # journal.body = request[:body].downcase
26
+ # end
27
+
28
+ def self.on_create(&block)
29
+ unless block_given? and block.arity == 2
30
+ raise ArgumentError.new("needs a block with two arguments")
31
+ end
32
+ @on_create = block
33
+ end
34
+
35
+ def self.on_update(&block)
36
+ unless block_given? and block.arity == 2
37
+ raise ArgumentError.new("needs a block with two arguments")
38
+ end
39
+ @on_update = block
40
+ end
41
+
42
+ def self.on_save(&block)
43
+ unless block_given? and block.arity == 2
44
+ raise ArgumentError.new("needs a block with two arguments")
45
+ end
46
+ @on_save = block
47
+ end
48
+
49
+ def self.on_second_save(&block)
50
+ unless block_given? and block.arity == 2
51
+ raise ArgumentError.new("needs a block with two arguments")
52
+ end
53
+ @on_second_save = block
54
+ end
55
+
56
+ def self.on_create_block
57
+ @on_create
58
+ end
59
+
60
+ def self.on_save_block
61
+ @on_save
62
+ end
63
+
64
+ def self.on_second_save_block
65
+ @on_second_save
66
+ end
67
+
68
+ def self.on_update_block
69
+ @on_update
70
+ end
71
+ end
72
+
73
+ base.class_eval do
74
+ # Check that MODEL is defined, so we know what we're working with.
75
+ unless const_defined?('MODEL')
76
+ raise RuntimeError.new("can't use CRUD helper unless MODEL is set.")
77
+ end
78
+
79
+ # Set the singular and plural instance vars for MODEL.
80
+ unless const_defined?('SINGULAR_MODEL_VAR')
81
+ const_set('SINGULAR_MODEL_VAR', '@' + const_get('MODEL').to_s.demodulize.underscore)
82
+ end
83
+ unless const_defined?('PLURAL_MODEL_VAR')
84
+ const_set('PLURAL_MODEL_VAR', const_get('SINGULAR_MODEL_VAR').pluralize)
85
+ end
86
+
87
+ # Prevent conflicts with our 0-ary action methods. Not needed if
88
+ # we're using controller/show/name instead of controller/name
89
+ #
90
+ #begin
91
+ # const_get('MODEL').reserved_canonical_names += ['index', 'new']
92
+ #rescue
93
+ #end
94
+
95
+ # This action can't be in the normal module body, or it breaks things.
96
+ def new
97
+ require_admin
98
+
99
+ @title = "New #{h model_class.to_s.demodulize.titleize}"
100
+ @form_action = :new
101
+
102
+ if request.post?
103
+ begin
104
+ # Create model
105
+ CortexReaver.db.transaction do
106
+ @model = model_class.new
107
+
108
+ # Initial callbacks
109
+ if block = self.class.on_save_block
110
+ block.call(@model, request)
111
+ end
112
+ if block = self.class.on_create_block
113
+ block.call(@model, request)
114
+ end
115
+
116
+ # Save for the first time
117
+ raise unless @model.save
118
+
119
+ # Second save callback, if applicable
120
+ if block = self.class.on_second_save_block
121
+ block.call(@model, request)
122
+ raise unless @model.save
123
+ end
124
+
125
+ flash[:notice] = "Created #{model_class.to_s.demodulize.downcase} #{h @model.to_s}."
126
+ redirect @model.url
127
+ end
128
+ rescue => e
129
+ # An error occurred
130
+ Ramaze::Log.error e.inspect + e.backtrace.join("\n")
131
+ flash[:error] = "Couldn't create #{model_class.to_s.demodulize.downcase} #{h request[:title]}: #{h e}."
132
+ set_singular_model_var @model
133
+ end
134
+ else
135
+ set_singular_model_var model_class.new
136
+ end
137
+ end
138
+ end
139
+ end
140
+
141
+ private
142
+
143
+ # Returns the model class for this controller, e.g., 'Journal'
144
+ def model_class
145
+ self.class.const_get('MODEL')
146
+ end
147
+
148
+ # Set the singular instance var for this controller, e.g. '@journal'.
149
+ def set_singular_model_var(value)
150
+ instance_variable_set(self.class.const_get('SINGULAR_MODEL_VAR'), value)
151
+ end
152
+
153
+ # Set the plural instance var for this controller, e.g. '@journals'
154
+ def set_plural_model_var(value)
155
+ instance_variable_set(self.class.const_get('PLURAL_MODEL_VAR'), value)
156
+ end
157
+
158
+ public
159
+
160
+ # Normal actions start here.
161
+
162
+ def index(id = nil)
163
+ if id
164
+ # Redirect to show
165
+ #
166
+ # This way, you can (assuming your name doesn't conflict with an existing
167
+ # action) tell people to visit /journals/my-cool-event, and it will go to
168
+ # /journals/show/my-cool-event.
169
+ raw_redirect Rs(:show, id), :status => 301
170
+ else
171
+ # Display index
172
+ page :last
173
+ end
174
+ end
175
+
176
+ def delete(id)
177
+ require_admin
178
+
179
+ if @model = model_class.get(id)
180
+ if @model.destroy
181
+ flash[:notice] = "#{model_class.to_s.demodulize.downcase} #{h @model.to_s} deleted."
182
+ redirect Rs()
183
+ else
184
+ flash[:notice] = "Couldn't delete #{model_class.to_s.demodulize.downcase} #{h @model.to_s}."
185
+ redirect @model.url
186
+ end
187
+ else
188
+ flash[:error] = "No such #{model_class.to_s.demodulize.downcase} (#{h id}) exists."
189
+ redirect Rs()
190
+ end
191
+ end
192
+
193
+ def edit(id = nil)
194
+ require_admin
195
+
196
+ if @model = model_class.get(id)
197
+ @title = "Edit #{model_class.to_s.demodulize.downcase} #{h @model.to_s}"
198
+ if @model.class.respond_to? :canonical_name_attr
199
+ @form_action = "edit/#{@model.send(@model.class.canonical_name_attr)}"
200
+ else
201
+ @form_action = "edit/#{@model.id}"
202
+ end
203
+
204
+ set_singular_model_var @model
205
+
206
+ if request.post?
207
+ begin
208
+ # Update model
209
+ CortexReaver.db.transaction do
210
+ # Initial callbacks
211
+ if block = self.class.on_save_block
212
+ block.call(@model, request)
213
+ end
214
+ if block = self.class.on_update_block
215
+ block.call(@model, request)
216
+ end
217
+
218
+ # Save
219
+ raise unless @model.save
220
+
221
+ # Second callbacks and save if applicable
222
+ if block = self.class.on_second_save_block
223
+ block.call(@model, request)
224
+ raise unless @model.save
225
+ end
226
+
227
+ flash[:notice] = "Updated #{model_class.to_s.demodulize.downcase} #{h @model.to_s}."
228
+ redirect @model.url
229
+ end
230
+ rescue => e
231
+ # An error occurred
232
+ Ramaze::Log.error e.inspect + e.backtrace.join("\n")
233
+ flash[:error] = "Couldn't update #{model_class.to_s.demodulize.downcase} #{h @model.to_s}: #{h e}."
234
+ end
235
+ end
236
+ else
237
+ flash[:error] = "No such #{model_class.to_s.demodulize.downcase} (#{id}) exists."
238
+ redirect Rs()
239
+ end
240
+ end
241
+
242
+ def page(page)
243
+
244
+ page = case page
245
+ when Symbol
246
+ page
247
+ when 'first'
248
+ :first
249
+ when 'last'
250
+ :last
251
+ when nil
252
+ error_404
253
+ else
254
+ page.to_i
255
+ end
256
+
257
+ @title = "#{model_class.to_s.demodulize.pluralize.titleize}"
258
+ if self.class.private_method_defined? :feed and model_class.respond_to? :atom_url
259
+ feed @title, model_class.atom_url
260
+ end
261
+ @models = model_class.window(page)
262
+ @page = page
263
+
264
+ if model_class.count.zero?
265
+ # There are NO models
266
+ elsif @models.empty?
267
+ # Empty page
268
+ error_404
269
+ end
270
+
271
+ set_plural_model_var @models
272
+
273
+ workflow "New #{model_class.to_s.demodulize}", Rs(:new)
274
+
275
+ render_template :list
276
+ end
277
+
278
+ def show(id)
279
+ if id and @model = model_class.get(id)
280
+ # Found that model
281
+ # Redirect IDs to names
282
+ raw_redirect(@model.url, :status => 301) if id =~ /^\d+$/
283
+
284
+ @title = h @model.to_s
285
+ set_singular_model_var @model
286
+
287
+ # Retrieve pending comment from session, if applicable.
288
+ if comment = session[:pending_comment] and comment.parent == @model
289
+ @new_comment = session.delete :pending_comment
290
+ else
291
+ # Create a comment to be posted
292
+ @new_comment = CortexReaver::Comment.new
293
+ @new_comment.send("#{model_class.to_s.demodulize.underscore.downcase}=", @model)
294
+ end
295
+
296
+ if session[:user]
297
+ @new_comment.user = session[:user]
298
+ end
299
+
300
+ # ID component of edit/delete links
301
+ if @model.class.respond_to? :canonical_name_attr
302
+ id = @model.send(@model.class.canonical_name_attr)
303
+ else
304
+ id = @model.id
305
+ end
306
+
307
+ workflow "Edit this #{model_class.to_s.demodulize}", Rs(:edit, id)
308
+ workflow "Delete this #{model_class.to_s.demodulize}", Rs(:delete, id)
309
+ render_template :show
310
+ elsif id
311
+ # Didn't find that model
312
+ error_404
313
+ end
314
+ end
315
+ end
316
+ end
317
+ end
@@ -0,0 +1,29 @@
1
+ module Ramaze
2
+ module Helper
3
+ # Provides assistance methods for displaying dates of objects.
4
+ module Date
5
+ # Puts out a line describing the creation (and modification) date of a
6
+ # model. If times are within identical_tolerance seconds (for example,
7
+ # because you forgot something on the form, hit back, and updated the
8
+ # record), the update time isn't displayed.
9
+ def date_line(model, identical_tolerance = 3600)
10
+ c = model.created_on
11
+ u = model.updated_on
12
+ date = '<span class="date">' + c.strftime('%A, %e %B %Y, %H:%M') + "</span>"
13
+
14
+ if (u - c) > identical_tolerance
15
+ # A significant modification time.
16
+ if u.year != c.year
17
+ date << " (updated <span class=\"date\">#{u.strftime('%A, %e %B %Y, %H:%M')}</span>)"
18
+ elsif u.day != c.day
19
+ date << " (updated <span class=\"date\">#{u.strftime('%A, %e %B, %H:%M')})</span>"
20
+ else
21
+ date << " (updated <span class=\"date\">#{u.strftime('%H:%M')}</span>)"
22
+ end
23
+ end
24
+
25
+ date
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,14 @@
1
+ module Ramaze
2
+ module Helper
3
+ # Provides some error pages
4
+ module Error
5
+ def error_404
6
+ respond 'Page not found', 404
7
+ end
8
+
9
+ def error_403
10
+ respond 'Forbidden', 403
11
+ end
12
+ end
13
+ end
14
+ end