Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Added initial Rails app

  • Loading branch information...
commit b3d85637d8799e6125dcb97d7e00edac27c84961 0 parents
@d2d d2d authored
Showing with 21,023 additions and 0 deletions.
  1. +46 −0 CREDITS
  2. +3 −0  Capfile
  3. +340 −0 LICENSE
  4. +70 −0 README
  5. +10 −0 Rakefile
  6. +86 −0 app/controllers/about_controller.rb
  7. +452 −0 app/controllers/account_controller.rb
  8. +11 −0 app/controllers/activity_controller.rb
  9. +81 −0 app/controllers/admin/articles_controller.rb
  10. +155 −0 app/controllers/admin/bill_summaries_controller.rb
  11. +176 −0 app/controllers/admin/commentary_controller.rb
  12. +110 −0 app/controllers/admin/comments_controller.rb
  13. +53 −0 app/controllers/admin/featured_people_controller.rb
  14. +33 −0 app/controllers/admin/hot_bills_controller.rb
  15. +8 −0 app/controllers/admin/index_controller.rb
  16. +78 −0 app/controllers/admin/sidebar_items_controller.rb
  17. +52 −0 app/controllers/admin/sidebars_controller.rb
  18. +64 −0 app/controllers/admin/site_text_controller.rb
  19. +100 −0 app/controllers/admin/site_text_pages_controller.rb
  20. +251 −0 app/controllers/admin/stats_controller.rb
  21. +47 −0 app/controllers/admin/tags_controller.rb
  22. +14 −0 app/controllers/admin/thunderdome_controller.rb
  23. +53 −0 app/controllers/admin/upcoming_bills_controller.rb
  24. +3 −0  app/controllers/admin/user_roles_controller.rb
  25. +14 −0 app/controllers/admin/user_warnings_controller.rb
  26. +87 −0 app/controllers/admin/users_controller.rb
  27. +370 −0 app/controllers/api_controller.rb
  28. +199 −0 app/controllers/application_controller.rb
  29. +109 −0 app/controllers/articles_controller.rb
  30. +261 −0 app/controllers/battle_royale_controller.rb
  31. +696 −0 app/controllers/bill_controller.rb
  32. +16 −0 app/controllers/cache_controller.rb
  33. +26 −0 app/controllers/commentary_controller.rb
  34. +190 −0 app/controllers/comments_controller.rb
  35. +125 −0 app/controllers/committee_controller.rb
  36. +10 −0 app/controllers/contact_controller.rb
  37. +21 −0 app/controllers/districts_controller.rb
  38. +134 −0 app/controllers/facebook_controller.rb
  39. +408 −0 app/controllers/friends_controller.rb
  40. +83 −0 app/controllers/gossip_controller.rb
  41. +47 −0 app/controllers/index_controller.rb
  42. +201 −0 app/controllers/issue_controller.rb
  43. +98 −0 app/controllers/mailing_list_items_controller.rb
  44. +10 −0 app/controllers/meta_controller.rb
  45. +75 −0 app/controllers/money_trail_controller.rb
  46. +36 −0 app/controllers/notebook_files_controller.rb
  47. +87 −0 app/controllers/notebook_items_controller.rb
  48. +117 −0 app/controllers/notebook_links_controller.rb
  49. +2 −0  app/controllers/notebook_notes_controller.rb
  50. +2 −0  app/controllers/notebook_videos_controller.rb
  51. +744 −0 app/controllers/people_controller.rb
  52. +131 −0 app/controllers/political_notebooks_controller.rb
  53. +525 −0 app/controllers/profile_controller.rb
  54. +504 −0 app/controllers/resources_controller.rb
  55. +294 −0 app/controllers/roll_call_controller.rb
  56. +39 −0 app/controllers/scrape_tools_controller.rb
  57. +177 −0 app/controllers/search_controller.rb
  58. +30 −0 app/controllers/states_controller.rb
  59. +11 −0 app/controllers/thunderdome_controller.rb
  60. +82 −0 app/controllers/twitter_configs_controller.rb
  61. +56 −0 app/controllers/twitter_controller.rb
  62. +183 −0 app/controllers/user_feeds_controller.rb
  63. +84 −0 app/controllers/user_mailing_lists_controller.rb
  64. +23 −0 app/controllers/video_controller.rb
  65. +88 −0 app/controllers/watch_dogs_controller.rb
  66. +45 −0 app/controllers/watchdogs_controller.rb
  67. +85 −0 app/controllers/wiki_links_controller.rb
  68. +5 −0 app/helpers/about_helper.rb
  69. +2 −0  app/helpers/account_helper.rb
  70. +6 −0 app/helpers/activity_helper.rb
  71. +2 −0  app/helpers/admin/comments_helper.rb
  72. +30 −0 app/helpers/admin/stats_helper.rb
  73. +2 −0  app/helpers/admin/thunderdome_helper.rb
  74. +2 −0  app/helpers/admin/user_roles_helper.rb
  75. +2 −0  app/helpers/api_helper.rb
  76. +882 −0 app/helpers/application_helper.rb
  77. +41 −0 app/helpers/battle_royale_helper.rb
  78. +259 −0 app/helpers/bill_helper.rb
  79. +2 −0  app/helpers/commentary_helper.rb
  80. +2 −0  app/helpers/comments_helper.rb
  81. +5 −0 app/helpers/committee_helper.rb
  82. +2 −0  app/helpers/contact_helper.rb
  83. +2 −0  app/helpers/crp_controller_helper.rb
  84. +2 −0  app/helpers/districts_helper.rb
  85. +9 −0 app/helpers/facebook_helper.rb
  86. +2 −0  app/helpers/featured_people_helper.rb
  87. +10 −0 app/helpers/friends_helper.rb
  88. +19 −0 app/helpers/gossip_helper.rb
  89. +88 −0 app/helpers/index_helper.rb
  90. +23 −0 app/helpers/industry_helper.rb
  91. +19 −0 app/helpers/issue_helper.rb
  92. +2 −0  app/helpers/mailing_list_items_helper.rb
  93. +2 −0  app/helpers/meta_helper.rb
  94. +15 −0 app/helpers/notebook_items_helper.rb
  95. +14 −0 app/helpers/notebook_links_helper.rb
  96. +8 −0 app/helpers/notebook_videos_helper.rb
  97. +202 −0 app/helpers/people_helper.rb
  98. +2 −0  app/helpers/political_notebook_helper.rb
  99. +55 −0 app/helpers/political_notebooks_helper.rb
  100. +123 −0 app/helpers/profile_helper.rb
  101. +16 −0 app/helpers/remote_link_renderer.rb
  102. +33 −0 app/helpers/resources_helper.rb
  103. +112 −0 app/helpers/roll_call_helper.rb
  104. +2 −0  app/helpers/scrape_tools_helper.rb
  105. +8 −0 app/helpers/search_helper.rb
  106. +12 −0 app/helpers/span_link_renderer.rb
  107. +2 −0  app/helpers/states_helper.rb
  108. +14 −0 app/helpers/thunderdome_helper.rb
  109. +2 −0  app/helpers/twitter_configs_helper.rb
  110. +2 −0  app/helpers/twitter_helper.rb
  111. +2 −0  app/helpers/user_feeds_helper.rb
  112. +2 −0  app/helpers/user_mailing_lists_helper.rb
  113. +2 −0  app/helpers/watch_dogs_helper.rb
  114. +81 −0 app/helpers/watchdogs_helper.rb
  115. +2 −0  app/helpers/wiki_links_helper.rb
  116. +181 −0 app/models/action.rb
  117. +3 −0  app/models/action_reference.rb
  118. +9 −0 app/models/amendment.rb
  119. +5 −0 app/models/api_hit.rb
  120. +90 −0 app/models/article.rb
  121. +7 −0 app/models/article_sweeper.rb
  122. +1,326 −0 app/models/bill.rb
  123. +7 −0 app/models/bill_battle.rb
  124. +3 −0  app/models/bill_comment.rb
  125. +7 −0 app/models/bill_committee.rb
  126. +6 −0 app/models/bill_cosponsor.rb
  127. +6 −0 app/models/bill_fulltext.rb
  128. +4 −0 app/models/bill_interest_group.rb
  129. +3 −0  app/models/bill_position_organization.rb
  130. +7 −0 app/models/bill_relation.rb
  131. +5 −0 app/models/bill_stats.rb
  132. +8 −0 app/models/bill_subject.rb
  133. +15 −0 app/models/bill_text_node.rb
  134. +81 −0 app/models/bill_text_version.rb
  135. +3 −0  app/models/bill_title.rb
  136. +12 −0 app/models/bill_vote.rb
  137. +47 −0 app/models/bookmark.rb
  138. +47 −0 app/models/bounce_handler.rb
  139. +164 −0 app/models/comment.rb
  140. +4 −0 app/models/comment_score.rb
  141. +182 −0 app/models/commentary.rb
  142. +6 −0 app/models/commentary_rating.rb
  143. +309 −0 app/models/committee.rb
  144. +8 −0 app/models/committee_meeting.rb
  145. +4 −0 app/models/committee_meetings_bill.rb
  146. +9 −0 app/models/committee_person.rb
  147. +28 −0 app/models/committee_report.rb
  148. +5 −0 app/models/committee_stats.rb
  149. +218 −0 app/models/comparison.rb
  150. +3 −0  app/models/comparison_data_point.rb
  151. +21 −0 app/models/congress_session.rb
  152. +4 −0 app/models/contributor.rb
  153. +18 −0 app/models/crp_industry.rb
  154. +16 −0 app/models/crp_interest_group.rb
  155. +3 −0  app/models/crp_sector.rb
  156. +3 −0  app/models/dem_dem_comparison.rb
  157. +229 −0 app/models/district.rb
  158. +73 −0 app/models/emailer.rb
  159. +21 −0 app/models/facebook_publisher.rb
  160. +13 −0 app/models/facebook_user.rb
  161. +30 −0 app/models/facebook_user_bill.rb
  162. +21 −0 app/models/featured_person.rb
  163. +8 −0 app/models/featured_person_sweeper.rb
  164. +5 −0 app/models/forum.rb
  165. +28 −0 app/models/fragment_cache_sweeper.rb
  166. +41 −0 app/models/friend.rb
  167. +4 −0 app/models/friend_email.rb
  168. +3 −0  app/models/friend_invite.rb
  169. +26 −0 app/models/friend_observer.rb
  170. +28 −0 app/models/gossip.rb
  171. +2 −0  app/models/gpo_billtext_timestamp.rb
  172. +4 −0 app/models/hot_bill_category.rb
  173. +7 −0 app/models/index_sweeper.rb
  174. +5 −0 app/models/industry_stats.rb
  175. +5 −0 app/models/issue_stats.rb
  176. +245 −0 app/models/list_representative.rb
  177. +245 −0 app/models/list_senator.rb
  178. +8 −0 app/models/mailing_list_item.rb
  179. +2 −0  app/models/meta.rb
  180. +11 −0 app/models/mini_mailing_list.rb
  181. +30 −0 app/models/notebook_file.rb
  182. +28 −0 app/models/notebook_item.rb
  183. +55 −0 app/models/notebook_link.rb
  184. +7 −0 app/models/notebook_note.rb
  185. +32 −0 app/models/notebook_video.rb
  186. +39 −0 app/models/page_view.rb
  187. +2 −0  app/models/panel_referrer.rb
  188. +1,602 −0 app/models/person.rb
  189. +9 −0 app/models/person_approval.rb
  190. +6 −0 app/models/person_cycle_contribution.rb
  191. +6 −0 app/models/person_sector.rb
  192. +19 −0 app/models/person_stats.rb
  193. +3 −0  app/models/person_view.rb
  194. +40 −0 app/models/political_notebook.rb
  195. +9 −0 app/models/privacy_option.rb
  196. +8 −0 app/models/refer.rb
  197. +3 −0  app/models/rep_dem_comparison.rb
  198. +3 −0  app/models/rep_rep_comparison.rb
  199. +12 −0 app/models/role.rb
  200. +145 −0 app/models/roll_call.rb
  201. +66 −0 app/models/roll_call_vote.rb
  202. +9 −0 app/models/search.rb
  203. +45 −0 app/models/sector.rb
  204. +3 −0  app/models/sidebar.rb
  205. +7 −0 app/models/sidebar_item.rb
  206. +23 −0 app/models/site_text.rb
  207. +3 −0  app/models/site_text_page.rb
  208. +167 −0 app/models/state.rb
  209. +390 −0 app/models/subject.rb
  210. +30 −0 app/models/subject_relation.rb
  211. +5 −0 app/models/twitter_config.rb
  212. +16 −0 app/models/upcoming_bill.rb
  213. +791 −0 app/models/user.rb
  214. +25 −0 app/models/user_ip_address.rb
  215. +75 −0 app/models/user_mailing_list.rb
  216. +68 −0 app/models/user_notifier.rb
  217. +11 −0 app/models/user_observer.rb
  218. +3 −0  app/models/user_role.rb
  219. +6 −0 app/models/user_warning.rb
  220. +8 −0 app/models/video.rb
  221. +15 −0 app/models/watch_dog.rb
  222. +63 −0 app/models/wiki_link.rb
  223. +8 −0 app/models/write_rep_email.rb
  224. +4 −0 app/models/write_rep_email_msgid.rb
  225. +27 −0 app/models/zipcode_district.rb
  226. +1 −0  app/views/about/_learn.html.erb
  227. +139 −0 app/views/about/beta_feedback.html.erb
  228. +11 −0 app/views/about/blog.html.erb
  229. +75 −0 app/views/about/congress.html.erb
  230. +32 −0 app/views/about/copyright_policy.html.erb
  231. +51 −0 app/views/about/hillstaff.html.erb
  232. +149 −0 app/views/about/howtouse.html.erb
  233. +232 −0 app/views/about/index.html.erb
  234. +23 −0 app/views/about/political_notebooks.html.erb
  235. +46 −0 app/views/about/privacy_policy.html.erb
  236. +41 −0 app/views/about/resources.html.erb
  237. +91 −0 app/views/about/rss.html.erb
  238. +14 −0 app/views/about/screencast.html.erb
  239. +104 −0 app/views/about/terms_of_service.html.erb
  240. +1 −0  app/views/account/_learn.html.erb
  241. +20 −0 app/views/account/accept_tos.html.erb
  242. +7 −0 app/views/account/confirm.html.erb
  243. +6 −0 app/views/account/forgot_password.html.erb
  244. +56 −0 app/views/account/index.html.erb
  245. +110 −0 app/views/account/login.html.erb
  246. +95 −0 app/views/account/login_modal.html.erb
  247. +10 −0 app/views/account/logout.html.erb
  248. +30 −0 app/views/account/new_openid.html.erb
  249. +1 −0  app/views/account/pwmail.html.erb
  250. +7 −0 app/views/account/reset_password.html.erb
  251. +75 −0 app/views/account/signup.html.erb
  252. +36 −0 app/views/account/welcome.html.erb
  253. +10 −0 app/views/account/why.html.erb
  254. +11 −0 app/views/activity/_latest_actions.html.erb
  255. +16 −0 app/views/activity/_learn.html.erb
  256. +7 −0 app/views/activity/latest.html.erb
  257. +31 −0 app/views/admin/articles/_form.html.erb
  258. +1 −0  app/views/admin/articles/_learn.html.erb
  259. +7 −0 app/views/admin/articles/edit.html.erb
  260. +33 −0 app/views/admin/articles/list.html.erb
  261. +9 −0 app/views/admin/articles/new.html.erb
  262. +21 −0 app/views/admin/articles/show.html.erb
  263. 0  app/views/admin/bill_summaries/_learn.html.erb
  264. +26 −0 app/views/admin/bill_summaries/_new_bill_form.html.erb
  265. +30 −0 app/views/admin/bill_summaries/defaulttitle.html.erb
  266. +9 −0 app/views/admin/bill_summaries/edit.html.erb
  267. +6 −0 app/views/admin/bill_summaries/index.html.erb
  268. +6 −0 app/views/admin/bill_summaries/new_bill.html.erb
  269. +1 −0  app/views/admin/bill_summaries/save_new_bill.html.erb
  270. +16 −0 app/views/admin/bill_summaries/session_relations.html.erb
  271. +43 −0 app/views/admin/commentary/_form.html.erb
  272. +1 −0  app/views/admin/commentary/_learn.html.erb
  273. +6 −0 app/views/admin/commentary/edit.html.erb
  274. +27 −0 app/views/admin/commentary/list.html.erb
  275. +8 −0 app/views/admin/commentary/new.html.erb
  276. +40 −0 app/views/admin/commentary/pending.html.erb
  277. +8 −0 app/views/admin/commentary/show.html.erb
  278. +25 −0 app/views/admin/comments/comments_search.html.erb
  279. +44 −0 app/views/admin/comments/index.html.erb
  280. +12 −0 app/views/admin/featured_people/_form.html.erb
  281. +1 −0  app/views/admin/featured_people/_learn.html.erb
  282. +9 −0 app/views/admin/featured_people/edit.html.erb
  283. +25 −0 app/views/admin/featured_people/list.html.erb
  284. +8 −0 app/views/admin/featured_people/new.html.erb
  285. +8 −0 app/views/admin/featured_people/show.html.erb
  286. +1 −0  app/views/admin/index/_learn.html.erb
  287. +50 −0 app/views/admin/index/index.html.erb
  288. +14 −0 app/views/admin/sidebar_items/_form.html.erb
  289. +10 −0 app/views/admin/sidebar_items/_item.html.erb
  290. +15 −0 app/views/admin/sidebar_items/_item_entry.html.erb
  291. +1 −0  app/views/admin/sidebar_items/_learn.html.erb
  292. +9 −0 app/views/admin/sidebar_items/edit.html.erb
  293. +26 −0 app/views/admin/sidebar_items/list.html.erb
  294. +24 −0 app/views/admin/sidebar_items/manage.html.erb
  295. +10 −0 app/views/admin/sidebar_items/new.html.erb
  296. +8 −0 app/views/admin/sidebar_items/show.html.erb
  297. +20 −0 app/views/admin/sidebars/_form.html.erb
  298. +1 −0  app/views/admin/sidebars/_learn.html.erb
  299. +9 −0 app/views/admin/sidebars/edit.html.erb
  300. +26 −0 app/views/admin/sidebars/list.html.erb
Sorry, we could not display the entire diff because too many files (4,998) changed.
46 CREDITS
@@ -0,0 +1,46 @@
+# OpenCongress - a Ruby on Rails application for displaying information about Congress
+#
+# Copyright (C) 2005-2006 Participatory Culture Foundation
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+#
+
+The Participatory Politics Foundation is:
+
+Board of Directors
+
+Tiffiniy Cheng
+Nicholas Nassar
+David Moore
+Nicholas Reville
+Holmes Wilson
+
+Staff
+
+David Moore, Executive Director
+Andrew Packer, Project Coordinator
+Andy Ross, Software Developer
+Donny Shaw, Researcher / Blogger
+David Shettler, Software Developer
+
+Other Contributors
+
+Ben Matasar
+Neil Cook
+Jason Packer
+Scott Chacon
+Jeff Mielke
+
+Built with support from the Sunlight Foundation.
3  Capfile
@@ -0,0 +1,3 @@
+load 'deploy' if respond_to?(:namespace) # cap2 differentiator
+Dir['vendor/plugins/*/recipes/*.rb'].each { |plugin| load(plugin) }
+load 'config/deploy'
340 LICENSE
@@ -0,0 +1,340 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
70 README
@@ -0,0 +1,70 @@
+# OpenCongress - a Ruby on Rails application for displaying information about Congress
+#
+# Copyright (C) 2005-2006 Participatory Culture Foundation
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+== OpenCongress Rails Project
+
+-- Installing OpenCongress --
+
+First of all, the OpenCongress project is a PostgreSQL only project. Don't have delusions of using MySQL with it or you will be hurtin. Since I personally had little experience with Postgres before this, I will include some tips for all you Mysql only guys and gals out there.
+
+Here is what you have to do to get OpenCongress close to working on your personal machine :
+
+ 1. install postgresql
+
+ 2. install tsearch in contrib
+
+ 3. gem install ferret, bluecloth, simple-rss, postgres-pr
+
+ 4. copy config/database.sample to config/database.yml and edit it
+
+ 5. create the databases
+ createdb opencongress_dev
+ opencongress_dev < db/tsearch2.sql
+ createdb opencongress_test
+
+ 6. rake migrate
+
+--
+
+Next, you will have to get the data from govtrack and fill in your database with the parsed govtrack data
+
+ mkdir /data/govtrack/109
+ cd /data/govtrack/109
+ rsync -az govtrack.us::govtrackdata/us/109/bills .
+ rsync -az govtrack.us::govtrackdata/us/109/repstats .
+ rsync -az govtrack.us::govtrackdata/us/109/bills.index.xml .
+ rsync -az govtrack.us::govtrackdata/us/109/committeeschedule.xml .
+ rsync -az govtrack.us::govtrackdata/us/109/rolls .
+
+Now, you will have to actually parse the data
+
+ ruby bin/govtrack_parse_people.rb
+ ruby bin/govtrack_parse_bills.rb
+ ruby bin/govtrack_parse_committees.rb
+ ruby bin/govtrack_parse_committee_schedules.rb
+ ruby parse_individual_bills.rb
+
+--
+
+Now, just run 'mongrel_rails start' and you should have something going on localhost:3000 - have fun!
+
+Lastly, some Postgres tips:
+
+ starting pg: pg_ctl -D data -l logfile start
+ accessing pg from the command line : psql opencongress_dev
+
10 Rakefile
@@ -0,0 +1,10 @@
+# Add your own tasks in files placed in lib/tasks ending in .rake,
+# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
+
+require(File.join(File.dirname(__FILE__), 'config', 'boot'))
+
+require 'rake'
+require 'rake/testtask'
+require 'rake/rdoctask'
+
+require 'tasks/rails'
86 app/controllers/about_controller.rb
@@ -0,0 +1,86 @@
+class AboutController < ApplicationController
+# caches_page :index, :blog, :resources, :congress, :howtouse, :rss, :feedback
+ skip_before_filter :has_accepted_tos?
+ skip_before_filter :store_location, :only => ["privacy_policy","terms_of_service"]
+
+
+ def index
+ @learn_off = true
+ @breadcrumb = {
+ 1 => { 'text' => "About", 'url' => { :controller => 'about' } }
+ }
+ @page_title = 'About Open Congress'
+ end
+
+ def blog
+ @learn_off = true
+ @breadcrumb = {
+ 1 => { 'text' => "About Blog", 'url' => { :controller => 'about', :action => 'blog' } }
+ }
+ @page_title = 'About OpenCongress Blog'
+ end
+
+ def resources
+ @page_title = "General Overview / Information about Congress"
+ @learn_off = true
+ @breadcrumb = {
+ 1 => { 'text' => "Congress Resources", 'url' => { :controller => 'about', :action => 'resources' } }
+ }
+ end
+
+ def congress
+ # Set @learn_off to remove "Learn More" from the layout
+ @learn_off = true
+ @page_title = 'About Congress'
+ end
+
+ def howtouse
+ @learn_off = true
+ @breadcrumb = {
+ 1 => { 'text' => "How To Use Open Congress", 'url' => { :controller => 'about', :action => 'howtouse'} }
+ }
+ @page_title = "How To Use Open Congress"
+ end
+
+ def beta_feedback
+ @learn_off = true
+ @breadcrumb = {
+ 1 => { 'text' => "Feedback", 'url' => { :controller => 'about', :action => 'beta_feedback'} }
+ }
+ @page_title = "Feedback"
+ end
+
+ def rss
+ @learn_off = true
+ @breadcrumb = {
+ 1 => { 'text' => "RSS", 'url' => { :controller => 'about', :action => 'rss' } }
+ }
+ @page_title = "Use RSS to Easily Track Developments in Congress"
+ end
+
+ def political_notebooks
+ @learn_off = true
+ @page_title = "About My Political Notebook"
+ end
+
+ def screencast
+ @learn_off
+ @page_title = "Screencast"
+ end
+
+ def terms_of_service
+ @head_title = "Terms of Service and Comment Policy"
+ end
+
+ def privacy_policy
+ @head_title = "Privacy Policy"
+ end
+
+private
+
+
+ def learn_from_controller(controller_name)
+ text = render_to_string(:partial => "#{controller_name}/learn")
+ process_bluecloth_text(text)
+ end
+end
452 app/controllers/account_controller.rb
@@ -0,0 +1,452 @@
+class AccountController < ApplicationController
+ before_filter :login_from_cookie, :except => "reset_password"
+ before_filter :login_required, :only => ["welcome","accept_tos"]
+ after_filter :check_forums, :only => ["login","activate"]
+ after_filter :check_wiki, :only => ["login", "activate"]
+
+ skip_before_filter :store_location
+
+ skip_before_filter :has_accepted_tos?, :only => ["accept_tos","logout"]
+
+ include OpenIdAuthentication
+
+# observer :user_observer
+
+ def index
+ if current_user.to_s == "false"
+ redirect_to(:action => 'login')
+ else
+ redirect_to(:controller => "profile", :action => "profile", :login => current_user.login)
+ end
+ end
+
+ def get_user_email
+ if params[:id] == API_KEYS['wiki_callback_key']
+ user = User.find(:first, :conditions => ["lower(login) = ?", params[:login].downcase])
+ render :text => "#{user.email}"
+ else
+ redirect_to :action => :index
+ end
+ end
+
+ def get_user_full_name
+ if params[:id] == API_KEYS['wiki_callback_key']
+ user = User.find(:first, :conditions => ["lower(login) = ?", params[:login].downcase])
+ render :text => "#{user.full_name}"
+ else
+ redirect_to :action => :index
+ end
+ end
+
+ def login
+ if params[:login_action]
+ session[:login_action] = {:url => session[:return_to], :action_result => params[:login_action]}
+ end
+
+ # Forum Integration
+ if params[:modal]
+ render :action => "login_modal", :layout => false
+ end
+
+ if params[:ReturnUrl]
+ session[:return_to] = params[:ReturnUrl]
+ end
+
+ if params[:wiki_return_page]
+ session[:return_to] = "#{WIKI_URL}/#{params[:wiki_return_page]}"
+ end
+ if using_open_id?
+ open_id_authentication(params[:openid_url])
+ elsif params[:user]
+ beer = User.find_by_login(params[:user][:login])
+ logger.info beer.to_yaml
+ self.current_user = User.authenticate(params[:user][:login], params[:user][:password])
+ return unless request.post?
+ else
+ return unless request.post?
+ end
+
+ if logged_in?
+ self.current_user.update_attribute(:previous_login_date, self.current_user.last_login ? self.current_user.last_login : Time.now)
+ self.current_user.update_attribute(:last_login, Time.now)
+ ip = self.current_user.user_ip_addresses.find_or_create_by_addr(UserIpAddress.int_form(request.remote_ip))
+ self.current_user.check_feed_key
+ process_login_actions
+ if params[:remember_me] == "1"
+ self.current_user.remember_me
+ cookies[:auth_token] = { :value => self.current_user.remember_token , :expires => self.current_user.remember_token_expires_at }
+ end
+ if self.current_user.fans.find(:first, :conditions => ["confirmed = ? AND created_at > ?", false, self.current_user.previous_login_date])
+ flash[:notice] = "Logged in * " + "<a href='#{url_for(:controller => "friends", :login => self.current_user.login)}'>New Friends Requests!</a> *"
+ else
+ flash[:notice] = "Logged in successfully"
+ end
+ redirect_back_or_default(:controller => 'profile', :action => 'profile', :login => current_user.login)
+ else
+ flash.now[:warning] = "Login failed"
+ end
+ end
+
+ def accept_tos
+ @page_title = "Please Accept our Terms of Service and Privacy Policy"
+ if request.post?
+ user = User.find_by_id(current_user.id)
+ if params[:accept_tos] == "1"
+ user.accepted_tos = true
+ user.accepted_tos_at = Time.now
+ user.save!
+ logger.info "USER TOS: #{user.accepted_tos}"
+ self.current_user = User.find_by_id(user.id)
+ redirect_back_or_default(:controller => 'profile', :action => 'profile', :login => current_user.login)
+ end
+ end
+ end
+
+ def signup
+ @page_title = "Create a New Account"
+
+ logger.info session.inspect
+
+ @user = User.new(params[:user])
+ @user.email = session[:invite].invitee_email unless session[:invite].nil? or request.post?
+
+ return unless request.post?
+ @user.accepted_tos = true
+ @user.accepted_tos_at = Time.now
+
+
+ if @user.zipcode
+ @senators, @reps = Person.find_current_congresspeople_by_zipcode(@user.zipcode, @user.zip_four)
+ @user.representative_id = @reps.first.id if (@reps && @reps.length == 1)
+ end
+ @user.save!
+
+ # check for an invitation
+ if session[:invite]
+ Friend.create_confirmed_friendship(@user, session[:invite].inviter)
+ session[:invite] = nil
+ end
+
+ redirect_to(:controller => '/account', :action => 'confirm', :login => @user.login)
+ rescue ActiveRecord::RecordInvalid
+ render :action => 'signup'
+ end
+
+ def confirm
+ @user = User.find_by_login(params[:login], :conditions => ["activated_at is null"])
+ end
+
+ def logout
+ if params[:wiki_return_page]
+ session[:return_to] = "http://www.opencongress.org/wiki/#{params[:wiki_return_page]}"
+ end
+ redirect_loc = session[:return_to]
+ self.current_user.forget_me if logged_in?
+ cookies.delete :auth_token
+ cookies.delete '_session_id'
+ # Forum Integration
+ cookies.delete 'lussumocookieone'
+ cookies.delete 'lussumocookietwo'
+ cookies['PHPSESSID'] = {:value => '', :path => '/', :expires => Time.at(0), :domain => ".www.opencongress.org" }
+ cookies['PHPSESSID'] = {:value => '', :path => '/', :expires => Time.at(0), :domain => ".opencongress.org" }
+ cookies['PHPSESSID'] = {:value => '', :path => '/', :expires => Time.at(0), :domain => ".www.opencongress.org" }
+ cookies.delete 'wikiToken', {:domain => '.opencongress.org'}
+ cookies.delete 'wiki_session', {:domain => '.opencongress.org'}
+ cookies.delete 'wikiUserID', {:domain => '.opencongress.org'}
+ cookies.delete 'wikiUserName', {:domain => '.opencongress.org'}
+
+ reset_session
+ session[:return_to] = redirect_loc
+ flash[:notice] = "You have been logged out."
+
+ #redirect_back_or_default('/')
+ redirect_to :controller => 'index'
+ end
+
+ def activate
+ @user = User.find_by_activation_code(params[:id])
+ if @user and @user.activate
+ self.current_user = @user
+ redirect_to(:controller => '/account', :action => 'welcome')
+ return
+ else
+ flash[:notice] = "Invalid Confirmation Link"
+ redirect_to(:controller => '/account', :action => "signup")
+ return
+ end
+
+ end
+
+ def welcome
+ @user = current_user
+ @show_tracked_list = true
+ @most_viewed_bills = PageView.popular('Bill', DEFAULT_COUNT_TIME, 5)
+ @senators, @reps = Person.find_current_congresspeople_by_zipcode(@user.zipcode, @user.zip_four) if ( logged_in? && @user == current_user && !(@user.zipcode.nil? || @user.zipcode.empty?))
+ end
+
+ def forgot_password
+ @breadcrumb = {
+ 1 => { 'text' => "Forgot Password", 'url' => "/account/forgot_password" }
+ }
+
+ return unless request.post?
+ if @user = User.find_by_email(params[:user][:email])
+ @user.forgot_password
+ @user.save!
+# redirect_back_or_default(:controller => '/account', :action => 'index')
+ @page_title = "Forgot Password"
+ render :action => "pwmail"
+ else
+ flash[:notice] = "Could not find a user with that email address"
+ end
+ end
+
+ def reset_password
+ redirect_to '/account/forgot_password' and return if params[:id].blank?
+ @user = User.find_by_password_reset_code(params[:id])
+ @breadcrumb = {
+ 1 => { 'text' => "Reset Password", 'url' => "/account/reset_password" }
+ }
+ raise if @user.nil?
+ return if @user unless request.post?
+ if (params[:user][:password] == params[:user][:password_confirmation])
+ self.current_user = @user #for the next two lines to work
+ current_user.password_confirmation = params[:user][:password_confirmation]
+ current_user.password = params[:user][:password]
+ @user.reset_password
+ flash[:notice] = current_user.save ? "Password reset" : "Password not reset"
+ else
+ flash[:notice] = "Password mismatch"
+ end
+ redirect_back_or_default(:controller => '/account', :action => 'index')
+ end
+
+ def profile
+ @user = User.find_by_login(params[:user])
+ end
+ def change_pw
+ @user = current_user
+ if (params[:user][:password] == params[:user][:password_confirmation])
+ self.current_user = @user #for the next two lines to work
+ current_user.password_confirmation = params[:user][:password_confirmation]
+ current_user.password = params[:user][:password]
+ @user.reset_password
+ flash[:notice] = current_user.save ? "Password reset" : "Password not reset"
+ else
+ flash[:notice] = "Password mismatch"
+ end
+ redirect_back_or_default(:controller => '/profile', :action => 'profile', :login => current_user.login)
+ end
+ def mailing_list
+ if params[:user][:mailing] && params[:user][:mailing] == "1"
+ current_user.mailing = true
+ flash[:notice] = "Subscribed to the Mailing List"
+ else
+ current_user.mailing = false
+ flash[:notice] = "Un-Subscribed from the Mailing List"
+ end
+ current_user.save!
+ redirect_back_or_default(:controller => '/profile', :action => 'profile', :login => current_user.login)
+ end
+
+ def why
+ end
+
+ def invited
+ invite = FriendInvite.find_by_invite_key(params[:id])
+
+ session[:invite] = invite
+
+ redirect_to :controller => 'register'
+ end
+
+ def new_openid
+ @page_title = "New OpenID Account"
+ identity_url = session[:idurl]
+ if request.post? && identity_url
+ begin
+ @user = User.new(params[:user])
+ @user.identity_url = identity_url
+ @user.email = session[:invite].invitee_email unless session[:invite].nil? or request.post?
+
+ if @user.zipcode
+ @senators, @reps = Person.find_current_congresspeople_by_zipcode(@user.zipcode, @user.zip_four)
+ @user.representative_id = @reps.first.id if (@reps && @reps.length == 1)
+ end
+ @user.save!
+
+ # check for an invitation
+ if session[:invite]
+ Friend.create_confirmed_friendship(@user, session[:invite].inviter)
+ session[:invite] = nil
+ end
+
+ redirect_to(:controller => '/account', :action => 'confirm', :login => @user.login)
+ rescue ActiveRecord::RecordInvalid
+ render :action => 'signup'
+ end
+ end
+ end
+
+ def check_forums
+ if logged_in?
+ begin
+ fuser = Forum.find(:first, :conditions => ["Name = ?", current_user.login])
+ unless fuser
+ fuser = Forum.create({:Name => current_user.login, :Password => current_user.crypted_password, :RoleID => 3, :DateFirstVisit => Time.new(), :DateLastActive => Time.new()})
+ end
+ vkey = Digest::SHA1.hexdigest( Time.now.to_s.split(//).sort_by {rand}.join )
+ fuser.VerificationKey = vkey
+ fuser.save
+ cookies[:lussumocookieone] = fuser.UserID.to_s
+ cookies[:lussumocookietwo] = vkey
+ rescue
+ end
+ end
+ end
+
+ def check_wiki
+ if logged_in?
+ begin
+ require 'net/http'
+ require 'uri'
+ require 'cgi'
+
+ cookie_domain = '.opencongress.org'
+
+ data = "wpName=#{CGI::escape(current_user.login)}&wpPassword=#{API_KEY['wiki_pass']}&wpLoginattempt=Log%20in&#{API_KEYS['wiki_key']}=true"
+
+ headers = {
+ 'Content-Type' => 'application/x-www-form-urlencoded'
+ }
+
+ http = Net::HTTP.new(RAILS_ENV == 'production' ? 'wiki.opencongress.org' : WIKI_BASE.gsub(/http:\/\//,''), 80)
+
+ path = "/index.php?title=Special:UserLogin&returnto=Main_Page"
+ resp, data = http.post(path,data,headers)
+
+ returned_cookies = resp['set-cookie'].split(',')
+ returned_cookies.each do |b|
+ b.strip!
+ if b =~ /^([A-Za-z0-9_]+)\=([A-Za-z0-9_]+)/
+ cookie_name, cookie_value = [$1, $2]
+ logger.info cookie_name
+ cookies[cookie_name] = {:value => cookie_value, :expires => 30.days.from_now, :domain => cookie_domain, :path => '/'}
+ end
+ end
+ rescue
+ end
+ end
+ end
+
+ def add_openid
+ authenticate_with_open_id(params[:identity_url]) do |status, identity_url, registration|
+ if status.successful?
+ user = User.find_by_id(current_user.id)
+ user.identity_url = identity_url
+ if user.save
+ flash[:notice] = "OpenID identity added"
+ else
+ flash[:notice] = "A user already exists with that open ID"
+ end
+ else
+ flash[:notice] = "Failed Login"
+ end
+ redirect_to user_profile_path(current_user.login)
+ end
+ end
+
+ protected
+
+# def open_id_authentication
+# authenticate_with_open_id do |result, identity_url|
+# if result.successful?
+# self.current_user = User.find_or_create_by_identity_url(identity_url)
+# end
+# end
+# end
+ def open_id_authentication(identity_url)
+ # Pass optional :required and :optional keys to specify what sreg fields you want.
+ # Be sure to yield registration, a third argument in the #authenticate_with_open_id block.
+ authenticate_with_open_id(identity_url, :required => [:nickname, :email]) do |status, identity_url, registration|
+ if status.successful?
+ if self.current_user = User.find_by_identity_url(identity_url)
+ # registration is a hash containing the valid sreg keys given above
+ # use this to map them to fields of your user model
+# {'login=' => 'nickname', 'email=' => 'email', 'full_name=' => 'fullname'}.each do |attr, reg|
+# current_user.send(attr, registration[reg]) unless registration[reg].blank?
+# end
+ unless self.current_user.save
+ flash[:error] = "Error saving the fields from your OpenID profile: #{current_user.errors.full_messages.to_sentence}"
+ end
+ else
+ u = User.new()
+ {'login=' => 'nickname', 'email=' => 'email', 'full_name=' => 'fullname'}.each do |attr, reg|
+ u.send(attr, registration[reg]) unless registration[reg].blank?
+ end
+ if u.save && self.current_user = User.find_by_identity_url(identity_url)
+ logger.info "rock on"
+ else
+ session[:idurl] = identity_url
+ redirect_to :action => "new_openid" and return
+ end
+ end
+ end
+ end
+ end
+
+ private
+ def root_url
+ home_url
+ end
+ def process_login_actions
+ #debugger
+ if session[:action] && session[:action][:url]
+ case session[:action][:url]
+ when /\/bill\/([0-9]{3}-\w{2,})\//
+ ident = $1
+ if ident
+ bill = Bill.find_by_ident(ident)
+ if bill
+ if session[:login_action][:action_result].to_i == 0
+ b = BillVote.find_or_create_by_user_id_and_bill_id(current_user.id, bill.id)
+ b.support = 0
+ b.save
+ elsif session[:login_action][:action_result].to_i == 1
+ b = BillVote.find_or_create_by_user_id_and_bill_id(current_user.id, bill.id)
+ b.support = 1
+ b.save
+ end
+ end
+ end
+ end
+ if session[:login_action][:action_result]
+ if session[:login_action][:action_result] == 'track'
+ case session[:login_action][:url]
+ when /\/bill\/([0-9]{3}-\w{2,})\//
+ ident = $1
+ if ident
+ bill = Bill.find_by_ident(ident)
+ if bill
+ bookmark = Bookmark.new(:user_id => current_user.id)
+ bill.bookmarks << bookmark
+ end
+ end
+ when /\/([^\/]+)\/[^\/]+\/(\d+)/
+ obj = $1
+ id = $2
+ if id && obj
+ object = Object.const_get(obj)
+ this_object = object.find_by_id(id)
+ if this_object
+ bookmark = Bookmark.new(:user_id => current_user.id)
+ this_object.bookmarks << bookmark
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+
+end
11 app/controllers/activity_controller.rb
@@ -0,0 +1,11 @@
+class ActivityController < ApplicationController
+
+ def latest
+ actions = Action.find(:all, :limit => 24, :order => 'datetime DESC',
+ :conditions => ["datetime > ?", Time.new.months_ago(3)])
+
+ # The classification groups actions by date non-linearly
+ # to present them in the most desirable fashion.
+ @actions = Action::classify_by_date(actions)
+ end
+end
81 app/controllers/admin/articles_controller.rb
@@ -0,0 +1,81 @@
+class Admin::ArticlesController < Admin::IndexController
+ before_filter :can_blog
+
+ # GETs should be safe (see http://www.w3.org/2001/tag/doc/whenToUseGet.html)
+ verify :method => :post, :only => [ :destroy, :create, :update ],
+ :redirect_to => { :action => :list }
+
+ cache_sweeper :article_sweeper, :only => [ :destroy, :update ]
+
+ public
+ def index
+ list
+ render :action => 'list'
+ end
+
+ def list
+ @articles = Article.paginate(:all, :order => "created_at desc", :per_page => 30, :page => params[:page])
+ end
+
+ def show
+ @article = Article.find(params[:id])
+ end
+
+ def new
+ @article = Article.new
+ end
+
+ def create
+ if @article = Article.create(params[:article])
+ @article.user_id = current_user.id
+ @article.save
+
+ expire_page :controller => '/blog'
+ expire_page :controller => '/articles'
+ expire_page :controller => '/index'
+ expire_page :controller => '/articles', :action => 'view', :id => @article
+
+ flash[:notice] = 'Article was successfully created.'
+ redirect_to :action => 'list'
+ else
+ render :action => 'new'
+ end
+ end
+
+ def edit
+ @article = Article.find(params[:id])
+ end
+
+ def edit_blogroll
+ a = Article.find_by_title("***BLOGROLL***")
+ if a
+ flash[:notice] = "Make sure title stays '***BLOGROLL***' and the published button stays off!"
+ redirect_to :action => 'edit', :id => a.id
+ else
+ flash[:error] = "Couldn't find blogroll in DB!"
+ redirect_to :action => 'list'
+ end
+ end
+
+ def update
+ @article = Article.find(params[:id])
+ if @article.update_attributes(params[:article])
+
+ expire_page :controller => '/blog'
+ expire_page :controller => '/articles'
+ expire_page :controller => '/index'
+ expire_page :controller => '/articles', :action => 'view', :id => @article
+
+ flash[:notice] = 'Article was successfully updated.'
+ redirect_to :action => 'show', :id => @article
+ else
+ render :action => 'edit'
+ end
+ end
+
+ def destroy
+ Article.find(params[:id]).destroy
+ redirect_to :action => 'list'
+ end
+
+end
155 app/controllers/admin/bill_summaries_controller.rb
@@ -0,0 +1,155 @@
+class Admin::BillSummariesController < Admin::IndexController
+ before_filter :can_blog
+
+ def index
+ @page_title = "Bill Plain Language Summaries"
+ end
+
+ def new_bill
+ @page_title = 'Add a new bill'
+ @bill = Bill.new
+ end
+
+ def save_new_bill
+ @bill = Bill.new(params[:bill])
+ @bill.save
+
+ title = BillTitle.new(params[:title])
+ title.title_type = 'official'
+ title.as = 'introduced'
+ title.bill = @bill
+ title.save
+
+ action = Action.new(params[:intro_action])
+ action.action_type = 'introduced'
+ action.date = Time.at(action.datetime)
+ action.bill = @bill
+ action.save
+
+ @bill.introduced = Time.at(action.datetime)
+ @bill.save
+ end
+
+ def edit
+ @page_title = "Bill Plain Language Summaries"
+ @bill = Bill.find_by_ident(params[:id])
+
+ unless @bill
+ flash[:notice] = "Could not find bill with ID=#{params[:id]}"
+ redirect_to :action => 'index'
+ end
+ end
+
+ def update
+ @bill = Bill.find_by_ident(params[:bill][:ident])
+
+ @bill.plain_language_summary = params[:bill][:plain_language_summary]
+ @bill.save
+
+ flash[:notice] = "#{@bill.title_typenumber_only} has been updated"
+ redirect_to :action => 'index'
+ end
+
+ def addtitle
+ if params[:title][:title].blank?
+ flash[:error] = "You didn't enter a bill title!"
+ redirect_to :controller => 'bill', :action => 'show', :id => Bill.find_by_id(params[:title][:bill_id]).ident
+ return
+ end
+
+ bt = BillTitle.find_or_create_by_title_and_bill_id(params[:title][:title], params[:title][:bill_id])
+ bt.update_attributes(params[:title])
+ redirect_to :controller => 'admin/bill_summaries', :action => 'defaulttitle',
+ :id => Bill.find_by_id(params[:title][:bill_id]).ident
+ end
+
+ def defaulttitle
+ @bill = Bill.find_by_ident(params[:id])
+
+ unless @bill
+ flash[:notice] = "Could not find bill with ID=#{params[:id]}"
+ redirect_to :action => 'index'
+ end
+ end
+
+ def updatedefaulttitle
+ @bill = Bill.find_by_ident(params[:id])
+
+ if params[:default_title].nil?
+ flash[:error] = "You didn't select anything!"
+ redirect_to :action => 'defaulttitle', :id => @bill.ident
+ return
+ end
+
+ # set none of the titles to default
+ @bill.bill_titles.each do |t|
+ t.is_default = false
+ t.save
+ end
+
+ if params[:default_title][:title_id] == 'none'
+ flash[:notice] = "No default title set for bill #{@bill.title_typenumber_only}"
+ else
+ bt = BillTitle.find_by_id(params[:default_title][:title_id])
+
+ if bt.nil? || (bt.bill != @bill)
+ flash[:error] = "An Internal Error Has Occurred!"
+ redirect_to :action => 'defaulttitle', :id => @bill.ident
+ return
+ end
+
+ bt.is_default = true
+ bt.save
+
+ flash[:notice] = "Default Title Selected."
+ end
+
+ redirect_to :action => 'defaulttitle', :id => @bill.ident
+ end
+
+ def session_relations
+ @relations = BillRelation.find(:all, :conditions => "relation='session'")
+ end
+
+ def session_relations_add
+ @bill = Bill.find_by_ident(params[:relation][:bill_ident]) unless params[:relation][:bill_ident].blank?
+ @related_bill = Bill.find_by_ident(params[:relation][:related_bill_ident]) unless params[:relation][:related_bill_ident].blank?
+
+ if @bill and @related_bill
+ BillRelation.create(:bill_id => @bill.id, :related_bill_id => @related_bill.id, :relation => 'session')
+ flash[:notice] = "Relation created!"
+ else
+ flash[:error] = "Problem finding one or both of the bills!"
+ end
+
+ redirect_to :action => 'session_relations'
+ end
+
+ def session_relations_delete
+ @relation = BillRelation.find_by_id(params[:id])
+ if @relation
+ @relation.destroy
+ flash[:notice] = "Relation deleted!"
+ else
+ flash[:error] = "ERROR: Relation not found!"
+ end
+
+ redirect_to :action => 'session_relations'
+ end
+
+ def toggle_frontpage_hot
+ @bill = Bill.find_by_ident(params[:bill_id])
+
+ if @bill
+ @bill.is_frontpage_hot = !@bill.is_frontpage_hot?
+ @bill.save
+
+ flash[:notice] = "#{@bill.title_typenumber_only} #{@bill.is_frontpage_hot? ? 'added to' : 'removed from'} homepage."
+ redirect_to :controller => '/bill', :action => 'show', :id => @bill.ident
+ else
+ flash[:error] = "Bill not found!"
+ redirect_to :controller => 'admin/index'
+ end
+ end
+
+end
176 app/controllers/admin/commentary_controller.rb
@@ -0,0 +1,176 @@
+class Admin::CommentaryController < Admin::IndexController
+ before_filter :can_moderate, :only => ["pending", "update_pending"]
+ def index
+ list
+ render :action => 'list'
+ end
+
+ # GETs should be safe (see http://www.w3.org/2001/tag/doc/whenToUseGet.html)
+ verify :method => :post, :only => [ :destroy, :create, :update ],
+ :redirect_to => { :action => :list }
+
+ def list
+ # this action is too costly, redirect
+ redirect_to :controller => 'admin/index'
+
+ #@commentary_pages, @commentaries = paginate :commentaries, :per_page => 10
+ end
+
+ def pending
+ @commentaries = Commentary.find_all_by_status('PENDING', :limit => 10)
+ @total_commentaries = Commentary.count_by_sql("SELECT count(*) FROM commentaries WHERE status='PENDING'")
+
+ @page_title = "Pending News and Blog Articles"
+ end
+
+ def clear_cache
+ ActionController::Base.cache_store.clear
+
+ flash[:notice] = "memcache cleared."
+
+ redirect_to :controller => "/admin/index"
+ end
+
+ def update_pending
+ statuses = params[:commentary]
+
+ if statuses
+ statuses.keys.each do |k|
+ c = Commentary.find_by_id(k)
+
+ if c
+ c.status = statuses[k]
+ c.is_ok = 'true' if statuses[k] == 'OK'
+ c.save
+ end
+ end
+
+ flash[:notice] = "Commentaries have been updated"
+ end
+
+ redirect_to :action => 'pending'
+ end
+
+ def add
+ @people = (Person.representatives << Person.senators).flatten
+ @page_title = "Add a News/Blog Article"
+ end
+
+ def show
+ @commentary = Commentary.find(params[:id])
+ end
+
+ def new
+ @commentary = Commentary.new
+
+ if params[:commentariable_type].blank? && params[:commentariable_id].blank?
+ redirect_to :action => 'add'
+ else
+ klass = Object.const_get params[:commentariable_type]
+ @commentary.commentariable = klass.find_by_id(params[:commentariable_id])
+ end
+ end
+
+ def create
+ @commentary = Commentary.new(params[:commentary])
+ @commentary.status = 'OK'
+ @commentary.is_ok = true
+
+ if @commentary.save
+ flash[:notice] = 'Commentary was successfully created.'
+ @commentary.commentariable.expire_commentary_fragments(@commentary.is_news? ? 'news' : 'blog')
+ case @commentary.commentariable_type
+ when 'Bill'
+ redirect_to :controller => '/bill', :action => 'show', :id => @commentary.commentariable.ident
+ when 'Person'
+ redirect_to :controller => '/people', :action => 'show', :id => @commentary.commentariable
+ when 'UpcomingBill'
+ redirect_to :controller => '/bill', :action => 'upcoming', :id => @commentary.commentariable
+ else
+ render :action => 'list'
+ end
+ else
+ render :action => 'new'
+ end
+ end
+
+ def edit
+ @commentary = Commentary.find(params[:id])
+ end
+
+ def update
+ @commentary = Commentary.find(params[:id])
+
+ if @commentary.update_attributes(params[:commentary])
+ flash[:notice] = 'Commentary was successfully updated.'
+ case @commentary.commentariable_type
+ when 'Bill'
+ redirect_to :controller => '/bill', :action => 'show', :id => @commentary.commentariable.ident
+ when 'Person'
+ redirect_to :controller => '/people', :action => 'show', :id => @commentary.commentariable
+ when 'UpcomingBill'
+ redirect_to :controller => '/bill', :action => 'upcoming', :id => @commentary.commentariable
+ else
+ render :action => 'list'
+ end
+ else
+ render :action => 'edit'
+ end
+ end
+
+ def mass_delete
+ @commentary_ids = params[:mass_delete_ids]
+
+ c = nil
+ object = nil
+ @commentary_ids.each do |c_id|
+ c = Commentary.find_by_id(c_id)
+ if c
+ c.status = 'DELETED'
+ c.is_ok = false
+ c.save
+
+ object = c.commentariable unless object
+ logger.info "%%%%%%%%%%%%%%%%%%% #{c_id}"
+ end
+ end
+
+ object.expire_commentary_fragments(c.is_news? ? 'news' : 'blog')
+
+ case c.commentariable_type
+ when 'Bill'
+ redirect_to :controller => '/bill', :action => (c.is_news? ? 'news' : 'blogs'), :id => c.commentariable.ident
+ when 'Person'
+ redirect_to :controller => '/people', :action => (c.is_news? ? 'news' : 'blogs'), :id => c.commentariable
+ when 'UpcomingBill'
+ redirect_to :controller => '/bill', :action => 'upcoming', :id => c.commentariable
+ end
+ end
+
+ def destroy
+ @commentary = Commentary.find(params[:id])
+
+ case @commentary.commentariable_type
+ when 'Bill'
+ @redirect_controller = '/bill'
+ @redirect_action = 'show'
+ @redirect_id = @commentary.commentariable.ident
+ when 'Person'
+ @redirect_controller = '/people'
+ @redirect_action = 'show'
+ @redirect_id = @commentary.commentariable
+ when 'UpcomingBill'
+ @redirect_controller = '/bill'
+ @redirect_action = 'upcoming'
+ @redirect_id = @commentary.commentariable
+ end
+
+ @commentary.status = 'DELETED'
+ @commentary.is_ok = false
+ @commentary.save
+
+ flash[:notice] = 'Commentary was deleted.'
+
+ redirect_to :controller => @redirect_controller, :action => @redirect_action, :id => @redirect_id
+ end
+end
110 app/controllers/admin/comments_controller.rb
@@ -0,0 +1,110 @@
+class Admin::CommentsController < Admin::IndexController
+ before_filter :admin_login_required
+ skip_before_filter :store_location, :only => ["bulk_operations"]
+
+
+ def index
+ if params[:flagged_only]
+ @teh_comments = Comment.paginate_by_flagged_and_censored(true,false, :order => "created_at ASC", :page => params[:page], :per_page => 100)
+ @page_title = "Flagged Comments"
+ else
+ @page_title = "Comment Moderation"
+ @teh_comments = Comment.paginate_by_ok_and_censored(nil,false, :order => "created_at ASC", :page => params[:page], :per_page => 100)
+ end
+ @learn_off = true
+ end
+
+ def comments_search
+ if request.post?
+ @comments = Comment.find(:all, :conditions => ["comment LIKE ?", "%#{params[:q]}%"])
+ @comments = nil if @comments.empty?
+ if params[:delete_comms]
+ @comments.each do |c|
+ c.destroy
+ end
+ @comments = nil
+ end
+ end
+ end
+
+ def bulk_operation
+
+ if params[:ban_ip]
+ params[:ban_ip].each do |commentid|
+ comment = Comment.find_by_id(params[:id])
+ if comment && !comment.ip_address.blank? && comment.ip_address !=~ /^127./
+ noob = ApacheBan.create_by_ip(comment.ip_address)
+ end
+ comment = nil
+ end
+ end
+
+ if params[:warn_user]
+ params[:warn_user].each do |commentid|
+ comment = Comment.find_by_id(commentid)
+ if comment && comment.user
+ comment.comment_warn(current_user)
+ comment.update_attribute(:censored, true)
+ end
+ end
+ end
+
+ unless params[:ban_user].nil? || params[:ban_user].empty?
+ comments = Comment.find_all_by_id(params[:ban_user])
+ users = comments.collect {|p| p.user_id}.compact.uniq.flatten
+ Comment.update_all("censored = true", ["id in (?)", params[:ban_user]])
+ User.update_all("is_banned = true", ["id in (?)", users]) unless users.empty?
+ end
+
+ unless params[:censor].nil? || params[:censor].empty?
+ Comment.update_all("censored = true", ["id in (?)", params[:censor]])
+ end
+
+ unless params[:ok].nil? || params[:ok].empty?
+ Comment.update_all("ok = true", ["id in (?)", params[:ok]])
+ Comment.update_all("flagged = false", ["id in (?)", params[:ok]])
+ end
+
+
+ unless params[:unflag].nil? || params[:unflag].empty?
+ Comment.update_all("flagged = false", ["id in (?)", params[:unflag]])
+ end
+
+ redirect_to('/admin/comments?flagged_only=true')
+
+ end
+
+ def set_ok
+ @tis_admin = true
+ c = Comment.find_by_id(params[:id])
+ c.update_attribute(:ok, true)
+ render :update do |page|
+ page.hide("comment#{c.id}")
+ end
+ end
+
+ def warn_user
+ @c = Comment.find_by_id(params[:id])
+ @user = c.user
+ @user.comment_warn(@c, current_user)
+ end
+
+ def unflag
+ @tis_admin = true
+ c = Comment.find_by_id(params[:id])
+ c.update_attribute(:flagged, false)
+ render :update do |page|
+ page.hide("comment#{c.id}")
+ end
+ end
+
+ def censor
+ @tis_admin = true
+ comment = Comment.find_by_id(params[:id])
+ comment.update_attribute(:censored, true)
+ render :update do |page|
+ page.hide("comment#{comment.id}")
+ end
+ end
+
+end
53 app/controllers/admin/featured_people_controller.rb
@@ -0,0 +1,53 @@
+class Admin::FeaturedPeopleController < Admin::IndexController
+ cache_sweeper :featured_person_sweeper, :only => [ :destroy, :create, :update ]
+
+ def index
+ list
+ render :action => 'list'
+ end
+
+ # GETs should be safe (see http://www.w3.org/2001/tag/doc/whenToUseGet.html)
+ verify :method => :post, :only => [ :destroy, :create, :update ],
+ :redirect_to => { :action => :list }
+
+ def list
+ @featured_people = FeaturedPerson.paginate(:all, :per_page => 30, :order => "created_at DESC", :page => params[:page])
+ end
+
+ def show
+ @featured_person = FeaturedPerson.find(params[:id])
+ end
+
+ def new
+ @featured_person = FeaturedPerson.new
+ end
+
+ def create
+ @featured_person = FeaturedPerson.new(params[:featured_person])
+ if @featured_person.save
+ flash[:notice] = 'FeaturedPerson was successfully created.'
+ redirect_to :action => 'list'
+ else
+ render :action => 'new'
+ end
+ end
+
+ def edit
+ @featured_person = FeaturedPerson.find(params[:id])
+ end
+
+ def update
+ @featured_person = FeaturedPerson.find(params[:id])
+ if @featured_person.update_attributes(params[:featured_person])
+ flash[:notice] = 'FeaturedPerson was successfully updated.'
+ redirect_to :action => 'show', :id => @featured_person
+ else
+ render :action => 'edit'
+ end
+ end
+
+ def destroy
+ FeaturedPerson.find(params[:id]).destroy
+ redirect_to :action => 'list'
+ end
+end
33 app/controllers/admin/hot_bills_controller.rb
@@ -0,0 +1,33 @@
+class Admin::HotBillsController < Admin::IndexController
+ before_filter :can_blog
+
+ def index
+ end
+
+ def addbill
+ bill = Bill.find_by_id(params[:bill][:id])
+
+ if bill
+ if params[:bill][:hot_bill_category_id] == 'new'
+ unless params[:hot_bill_category][:name].blank?
+ c = HotBillCategory.find_or_create_by_name(params[:hot_bill_category][:name])
+ c.save
+
+ bill.hot_bill_category = c
+
+ end
+ else
+ bill.hot_bill_category_id = params[:bill][:hot_bill_category_id].blank? ?
+ nil : params[:bill][:hot_bill_category_id]
+ end
+
+ bill.plain_language_summary = params[:bill][:plain_language_summary]
+ bill.save
+
+ redirect_to :controller => '/bill', :action => 'show', :id => bill.ident
+ else
+ redirect_to :controller => 'index'
+ end
+ end
+
+end
8 app/controllers/admin/index_controller.rb
@@ -0,0 +1,8 @@
+class Admin::IndexController < ApplicationController
+ before_filter :login_required
+ before_filter :no_users
+
+ def index
+ end
+
+end
78 app/controllers/admin/sidebar_items_controller.rb
@@ -0,0 +1,78 @@
+class Admin::SidebarItemsController < Admin::IndexController
+ def index
+ list
+ render :action => 'list'
+ end
+
+ # GETs should be safe (see http://www.w3.org/2001/tag/doc/whenToUseGet.html)
+ verify :method => :post, :only => [ :destroy, :create, :update ],
+ :redirect_to => { :action => :list }
+
+ def list
+ @sidebar_items = SidebarItem.paginate(:all, :per_page => 30, :page => params[:page])
+ end
+
+ def show
+ @sidebar_items = SidebarItem.find(params[:id])
+ end
+
+ def manage
+ redirect_to :controller => 'sidebars', :action => 'list' unless params[:sidebar_id]
+ @sidebar = Sidebar.find(params[:sidebar_id])
+ @sidebar_items = @sidebar.sidebar_items
+ logger.warn @sidebar_items.inspect
+ end
+
+ def new
+ redirect_to :controller => 'sidebars' unless params[:sidebar_id]
+ @sidebar = Sidebar.find(params[:sidebar_id])
+ @sidebar_items = SidebarItem.new
+ end
+
+ def create
+ @sidebar_items = SidebarItem.new(params[:sidebar_items])
+ @sidebar = Sidebar.find(params[:sidebar_items][:sidebar_id])
+
+ if @sidebar.class_type == 'Bill'
+ session, bill_type, number = Bill.ident(params[:sidebar_items][:bill_id])
+ bill = Bill.find_by_session_and_bill_type_and_number(session, bill_type, number)
+
+ if bill
+ @sidebar_items.bill = bill
+ else
+ flash[:notice] = 'The bill ID you entered is not valid'
+ render :action => 'new'
+ end
+ end
+
+ if @sidebar_items.save
+ flash[:notice] = 'SidebarItems was successfully created.'
+ redirect_to :action => 'manage', :sidebar_id => @sidebar
+ else
+ render :action => 'new'
+ end
+ end
+
+ def edit
+ @sidebar_items = SidebarItem.find(params[:id])
+ @sidebar = @sidebar_items.sidebar
+ end
+
+ def update
+ @sidebar_items = SidebarItem.find(params[:id])
+ if @sidebar_items.update_attributes(params[:sidebar_items])
+ flash[:notice] = 'SidebarItems was successfully updated.'
+ redirect_to :action => 'manage', :sidebar_id => @sidebar_items.sidebar
+ else
+ render :action => 'edit'
+ end
+ end
+
+ def destroy
+ sbi = SidebarItem.find(params[:id])
+ sb = sbi.sidebar
+ sbi.destroy
+
+ redirect_to :action => 'manage', :sidebar_id => sb
+ end
+end
52 app/controllers/admin/sidebars_controller.rb
@@ -0,0 +1,52 @@
+class Admin::SidebarsController < Admin::IndexController
+ before_filter :can_text
+ def index
+ list
+ render :action => 'list'
+ end
+
+ # GETs should be safe (see http://www.w3.org/2001/tag/doc/whenToUseGet.html)
+ verify :method => :post, :only => [ :destroy, :create, :update ],
+ :redirect_to => { :action => :list }
+
+ def list
+ @sidebars = Sidebar.paginate(:all,