Changesets can be listed by changeset number.
The Git repository is here.
Changeset 178
Hub integration of Beast forum. Completed styling for RISC OS Open site.
Removed reliance on JavaScript. Added Textile hints to various views.
Added bespoke utility code used to port over RForum data for posterity;
note the rather large bug that it ignores the deleted flag on RForum
data.
Some amount of testing carried out on Firefox, Opera and Netsurf. Looks
OK so far, but there are definitely some aesthetic kinks to work out
still and doubtless some operational bugs will surface once it goes
live and is subjected to more intensive real world use.
- Comitted by: rool
- Date: Monday March 12 00:19:40 2007 (over 17 years ago)
Affected files:
- rool/rails/beast/trunk/utilities/
- rool/rails/beast/trunk/utilities/rforum_migration/
- rool/rails/beast/trunk/utilities/rforum_migration/controllers/
- rool/rails/beast/trunk/utilities/rforum_migration/models/
- rool/rails/beast/trunk/utilities/rforum_migration/views/
- rool/rails/beast/trunk/utilities/rforum_migration/views/rforumposts/
- rool/rails/beast/trunk/utilities/rforum_migration/views/rforumtopics/
- rool/rails/beast/trunk/utilities/rforum_migration/views/rforumusers/
- rool/rails/beast/trunk/utilities/rforum_migration/controllers/rforumposts_controller.rb
- rool/rails/beast/trunk/utilities/rforum_migration/controllers/rforumtopics_controller.rb
- rool/rails/beast/trunk/utilities/rforum_migration/controllers/rforumusers_controller.rb
- rool/rails/beast/trunk/utilities/rforum_migration/database.yml
- rool/rails/beast/trunk/utilities/rforum_migration/models/rforumpost.rb
- rool/rails/beast/trunk/utilities/rforum_migration/models/rforumtopic.rb
- rool/rails/beast/trunk/utilities/rforum_migration/models/rforumuser.rb
- rool/rails/beast/trunk/utilities/rforum_migration/views/rforumposts/extract.rhtml
- rool/rails/beast/trunk/utilities/rforum_migration/views/rforumtopics/extract.rhtml
- rool/rails/beast/trunk/utilities/rforum_migration/views/rforumusers/extract.rhtml
- rool/rails/beast/trunk/app/controllers/application.rb (diff)
- rool/rails/beast/trunk/app/controllers/forums_controller.rb (diff)
- rool/rails/beast/trunk/app/controllers/moderators_controller.rb (diff)
- rool/rails/beast/trunk/app/controllers/monitorships_controller.rb (diff)
- rool/rails/beast/trunk/app/controllers/posts_controller.rb (diff)
- rool/rails/beast/trunk/app/controllers/sessions_controller.rb (diff)
- rool/rails/beast/trunk/app/controllers/topics_controller.rb (diff)
- rool/rails/beast/trunk/app/controllers/users_controller.rb (diff)
- rool/rails/beast/trunk/app/helpers/application_helper.rb (diff)
- rool/rails/beast/trunk/app/models/user.rb (diff)
- rool/rails/beast/trunk/app/views/forums/index.rhtml (diff)
- rool/rails/beast/trunk/app/views/forums/show.rhtml (diff)
- rool/rails/beast/trunk/app/views/layouts/application.rhtml (diff)
- rool/rails/beast/trunk/app/views/posts/edit.rhtml (diff)
- rool/rails/beast/trunk/app/views/posts/index.rhtml (diff)
- rool/rails/beast/trunk/app/views/posts/monitored.rhtml (diff)
- rool/rails/beast/trunk/app/views/shared/_theme.rhtml (diff)
- rool/rails/beast/trunk/app/views/topics/edit.rhtml (diff)
- rool/rails/beast/trunk/app/views/topics/new.rhtml (diff)
- rool/rails/beast/trunk/app/views/topics/show.rhtml (diff)
- rool/rails/beast/trunk/app/views/users/show.rhtml (diff)
- rool/rails/beast/trunk/config/routes.rb (diff)
- rool/rails/beast/trunk/db/migrate/033_add_password_hash.rb (diff)
- rool/rails/beast/trunk/db/schema.rb (diff)
- rool/rails/beast/trunk/lib/authentication_system.rb (diff)
- rool/rails/beast/trunk/public/stylesheets/display.css (diff)
rool/rails/beast/trunk/app/controllers/application.rb:
prev. | current | |
class ApplicationController < ActionController::Base | ||
include ExceptionLoggable, BrowserFilters, AuthenticationSystem | ||
3 | | |
4 | # Hub single sign-on support. Run the Hub filters for all actions to | |
5 | # ensure activity timeouts etc. work properly. The login integration | |
6 | # with Hub is done using modifications to the forum's own mechanism | |
7 | # in lib/authentication_system.rb. | |
8 | ||
9 | require 'hub_sso_lib' | |
10 | include HubSsoLib::Core | |
11 | before_filter :hubssolib_beforehand | |
12 | after_filter :hubssolib_afterwards | |
13 | ||
14 | # Beast's usual preamble. | |
15 | ||
helper_method :current_user, :logged_in?, :admin?, :last_active | ||
before_filter :login_by_token | ||
rool/rails/beast/trunk/app/controllers/forums_controller.rb:
prev. | current | |
class ForumsController < ApplicationController | ||
2 | | |
before_filter :find_or_initialize_forum, :except => :index | ||
4 | @@hubssolib_permissions = HubSsoLib::Permissions.new({ | |
5 | :new => [ :admin, :webmaster ], | |
6 | :create => [ :admin, :webmaster ], | |
7 | :edit => [ :admin, :webmaster ], | |
8 | :update => [ :admin, :webmaster ], | |
9 | :destroy => [ :admin, :webmaster ], | |
10 | }) | |
11 | ||
12 | def ForumsController.hubssolib_permissions | |
13 | @@hubssolib_permissions | |
14 | end | |
15 | ||
def index | ||
@forums = Forum.find(:all, :order => "position") | ||
respond_to do |format| |
rool/rails/beast/trunk/app/controllers/moderators_controller.rb:
prev. | current | |
class ModeratorsController < ApplicationController | ||
2 | | |
3 | @@hubssolib_permissions = HubSsoLib::Permissions.new({ | |
4 | :new => [ :admin, :webmaster ], | |
5 | :create => [ :admin, :webmaster ], | |
6 | :edit => [ :admin, :webmaster ], | |
7 | :update => [ :admin, :webmaster ], | |
8 | :destroy => [ :admin, :webmaster ], | |
9 | }) | |
10 | ||
11 | def ModeratorsController.hubssolib_permissions | |
12 | @@hubssolib_permissions | |
13 | end | |
14 | ||
def destroy | ||
Moderatorship.delete_all ['id = ?', params[:id]] | ||
redirect_to user_path(params[:user_id]) |
rool/rails/beast/trunk/app/controllers/monitorships_controller.rb:
prev. | current | |
class MonitorshipsController < ApplicationController | ||
2 | | |
3 | @@hubssolib_permissions = HubSsoLib::Permissions.new({ | |
4 | :new => [ :admin, :webmaster, :privileged, :normal ], | |
5 | :create => [ :admin, :webmaster, :privileged, :normal ], | |
6 | :edit => [ :admin, :webmaster, :privileged, :normal ], | |
7 | :update => [ :admin, :webmaster, :privileged, :normal ], | |
8 | :destroy => [ :admin, :webmaster, :privileged, :normal ], | |
9 | }) | |
10 | ||
11 | def MonitorshipsController.hubssolib_permissions | |
12 | @@hubssolib_permissions | |
13 | end | |
14 | ||
def create | ||
@monitorship = Monitorship.find_or_initialize_by_user_id_and_topic_id(current_user.id, params[:topic_id]) | ||
@monitorship.update_attribute :active, true | ||
... | ... | |
end | ||
def destroy | ||
14 | | |
25 | # Beast HEAD does the following, but this leaks monitorships into | |
26 | # the database indefinitely, merely setting "active = t" or "f" | |
27 | # flags everywhere. The Posts controller just checks for the row | |
28 | # entries that match post and user ID, but not the active flag. | |
29 | # To make life simpler, just delete Monitorship entries that match | |
30 | # the given details. | |
31 | ||
32 | # Monitorship.update_all ['active = ?', false], ['user_id = ? and topic_id = ?', current_user.id, params[:topic_id]] | |
33 | ||
34 | monitorship = Monitorship.find_by_user_id_and_topic_id(current_user.id, params[:topic_id]) | |
35 | monitorship.destroy() if monitorship | |
36 | ||
respond_to do |format| | ||
format.html { redirect_to topic_path(params[:forum_id], params[:topic_id]) } | ||
format.js |
rool/rails/beast/trunk/app/controllers/posts_controller.rb:
prev. | current | |
class PostsController < ApplicationController | ||
2 | | |
3 | | |
2 | before_filter :find_post, :except => [:index, :index_rss, :create, :monitored, :search] | |
@@query_options = { :per_page => 25, :select => 'posts.*, topics.title as topic_title, forums.name as forum_name', :joins => 'inner join topics on posts.topic_id = topics.id inner join forums on topics.forum_id = forums.id', :order => 'posts.created_at desc' } | ||
5 | @@hubssolib_permissions = HubSsoLib::Permissions.new({ | |
6 | :new => [ :admin, :webmaster, :privileged, :normal ], | |
7 | :create => [ :admin, :webmaster, :privileged, :normal ], | |
8 | :edit => [ :admin, :webmaster, :privileged, :normal ], | |
9 | :update => [ :admin, :webmaster, :privileged, :normal ], | |
10 | :destroy => [ :admin, :webmaster ], | |
11 | }) | |
12 | ||
13 | def PostsController.hubssolib_permissions | |
14 | @@hubssolib_permissions | |
15 | end | |
16 | ||
def index | ||
7 | | |
8 | | |
9 | | |
10 | | |
11 | | |
18 | index_initialise | |
render_posts_or_xml | ||
end | ||
21 | ||
22 | # Backwards compatibility with RForum global feed via a routing hack. | |
23 | # | |
24 | def index_rss | |
25 | index_initialise | |
26 | render :action => "index.rxml", :layout => false | |
27 | end | |
def search | ||
conditions = params[:q].blank? ? nilil : Post.send(:sanitize_sql, ['LOWER(posts.body) LIKE ?', "%#{params[:q]}%"]) | ||
... | ... | |
end | ||
protected | ||
121 | def index_initialise | |
122 | conditions = [] | |
123 | [:user_id, :forum_id].each { |attr| conditions << Post.send(:sanitize_sql, ["posts.#{attr} = ?", params[attr]]) if params[attr] } | |
124 | conditions = conditions.any? ? conditions.collect { |c| "(#{c})" }.join(' AND ') : nil | |
125 | @post_pages, @posts = paginate(:posts, @@query_options.merge(:conditions => conditions)) | |
126 | @users = User.find(:all, :select => 'distinct *', :conditions => ['id in (?)', @posts.collect(&:user_id).uniq]).index_by(&:id) | |
127 | end | |
128 | ||
def authorized? | ||
action_name == 'create' || @post.editable_by?(current_user) | ||
end |
rool/rails/beast/trunk/app/controllers/sessions_controller.rb:
prev. | current | |
class SessionsController < ApplicationController | ||
3 | @@hubssolib_permissions = HubSsoLib::Permissions.new({ | |
4 | :new => [ :admin ], | |
5 | :create => [ :admin, :webmaster, :privileged, :normal ], | |
6 | :edit => [ :admin ], | |
7 | :update => [ :admin ], | |
8 | :destroy => [ :admin ], | |
9 | }) | |
10 | ||
11 | def SessionsController.hubssolib_permissions | |
12 | @@hubssolib_permissions | |
13 | end | |
14 | ||
def create | ||
self.current_user = User.authenticate(params[:login], params[:password]) | ||
17 | redirect_to home_path and return | |
18 | ||
19 | # Old pre-Hub code | |
20 | ||
if logged_in? | ||
cookies[:login_token]={ :value => "#{current_user.id};#{current_user.reset_login_key!}", :expires => Time.now.utc+1.year } if params[:remember_me]=="1" | ||
redirect_to home_path and return |
rool/rails/beast/trunk/app/controllers/topics_controller.rb:
prev. | current | |
class TopicsController < ApplicationController | ||
before_filter :find_forum_and_topic, :except => :index | ||
3 | | |
4 | ||
4 | @@hubssolib_permissions = HubSsoLib::Permissions.new({ | |
5 | :new => [ :admin, :webmaster, :privileged, :normal ], | |
6 | :create => [ :admin, :webmaster, :privileged, :normal ], | |
7 | :edit => [ :admin, :webmaster ], | |
8 | :update => [ :admin, :webmaster ], | |
9 | :destroy => [ :admin, :webmaster ], | |
10 | }) | |
11 | ||
12 | def TopicsController.hubssolib_permissions | |
13 | @@hubssolib_permissions | |
14 | end | |
15 | ||
def index | ||
respond_to do |format| | ||
format.html { redirect_to forum_path(params[:forum_id]) } |
rool/rails/beast/trunk/app/controllers/users_controller.rb:
prev. | current | |
class UsersController < ApplicationController | ||
2 | | |
3 | | |
2 | before_filter :find_user, :only => [:edit, :update, :destroy, :admin] | |
4 | @@hubssolib_permissions = HubSsoLib::Permissions.new({ | |
5 | :index => [ :admin, :webmaster ], | |
6 | :show => [ :admin, :webmaster, :privileged, :normal ], | |
7 | ||
8 | # Never use these. | |
9 | ||
10 | :new => [ :admin ], | |
11 | :create => [ :admin ], | |
12 | :edit => [ :admin ], | |
13 | :update => [ :admin ], | |
14 | :activate => [ :admin ], | |
15 | :admin => [ :admin ], | |
16 | :destroy => [ :admin ], | |
17 | }) | |
18 | ||
19 | def UsersController.hubssolib_permissions | |
20 | @@hubssolib_permissions | |
21 | end | |
22 | ||
def index | ||
respond_to do |format| | ||
format.html do |
rool/rails/beast/trunk/app/helpers/application_helper.rb:
prev. | current | |
end | ||
def avatar_for(user, size=32) | ||
15 | | |
15 | image_tag "http://www.gravatar.com/avatar.php?gravatar_id=#{MD5.md5(user.email)}&size=#{size}", :size => "#{size}x#{size}", :class => 'photo' | |
end | ||
def feed_icon_tag(title, url) |
rool/rails/beast/trunk/app/models/user.rb:
prev. | current | |
has_many :monitorships | ||
has_many :monitored_topics, :through => :monitorships, :conditions => ['monitorships.active = ?', true], :order => 'topics.replied_at desc', :source => :topic | ||
12 | | |
13 | | |
14 | | |
15 | | |
12 | # Commented out lots of stuff here. Users are built through | |
13 | # Hub now, so many of the requirements are invalid anyway. The | |
14 | # new replacement code is immediately below, before the old | |
15 | # commented out block. | |
16 | ||
17 | validates_uniqueness_of :login | |
18 | ||
19 | # validates_presence_of :login, :email, :password_hash | |
20 | # validates_length_of :login, :minimum => 2 | |
21 | # validates_length_of :password, :minimum => 5, :allow_nil => true | |
22 | # validates_confirmation_of :password, :on => :create | |
23 | # | |
24 | # # names that start with #s really upset me for some reason | |
25 | # validates_format_of :login, :with => /^[a-z]{2}(?:\w+)?$/i | |
26 | # | |
27 | # # names that start with #s really upset me for some reason | |
28 | # validates_format_of :display_name, :with => /^[a-z]{2}(?:[.'\-\w ]+)?$/i | |
29 | # | |
30 | # validates_uniqueness_of :login, :email, :display_name, :case_sensitive => false | |
31 | # before_validation { |u| u.display_name = u.login if u.display_name.blank? } | |
32 | # # first user becomes admin automatically | |
33 | # before_create { |u| u.admin = u.activated = true if User.count == 0 } | |
34 | # format_attribute :bio | |
17 | | |
18 | | |
36 | attr_reader :password | |
37 | ||
38 | # Relaxed protected attributes. Note that admin and activation flags | |
39 | # can now be mass-assigned. This is only acceptable because there is | |
40 | # no longer an external interface for modifying Users through the | |
41 | # user controller. | |
42 | ||
43 | attr_protected :posts_count, :created_at, :updated_at, :last_login_at, :topics_count | |
20 | | |
21 | | |
45 | # attr_protected :admin, :posts_count, :login, :created_at, :updated_at, :last_login_at, :topics_count, :activated | |
23 | | |
24 | | |
25 | | |
26 | | |
27 | | |
28 | ||
29 | | |
30 | | |
31 | ||
def self.currently_online | ||
User.find(:all, :conditions => ["last_seen_at > ?", Time.now.utc-5.minutes]) | ||
end |
rool/rails/beast/trunk/app/views/forums/index.rhtml:
prev. | current | |
<% content_for :right do %> | ||
3 | ||
4 | ||
5 | ||
6 | | |
7 | ||
8 | ||
<% if admin? %> | ||
10 | ||
11 | ||
4 | <h3>Admin</h3> | |
5 | <ul><li><%= link_to 'Create New Forum', new_forum_path, :class => "utility" %></li></ul> | |
<% end %> | ||
<% end %> |
rool/rails/beast/trunk/app/views/forums/show.rhtml:
prev. | current | |
<% content_for :right do %> | ||
<% unless @forum.description.blank? %> | ||
4 | <h3>Description</h3> | |
<%= @forum.description_html %> | ||
5 | ||
<% end %> | ||
8 | ||
9 | ||
<% if @forum.moderators.any? -%> | ||
9 | <h3>Moderators</h5> | |
10 | ||
<ul class="flat" style="margin-top:1em;"> | ||
<% @forum.moderators.each do |user| -%> | ||
<li><%= link_to user.display_name, user_path(user) %></li> | ||
<% end -%> | ||
</ul> | ||
<% else -%> | ||
17 | <h3>Unmoderated</h5> | |
18 | ||
<p>This forum is currently unmoderated.</p> | ||
<p>Please always be courteous.</p> | ||
<% end -%> | ||
... | ... | |
<% if @topic_pages.page_count > 1 -%> | ||
40 | ||
<p style="float:right; margin-top:0;"><%= link_to 'New topic', new_topic_path(@forum), :class => "utility" %></p> | ||
42 | ||
<p class="pages">Pages: <strong><%= pagination_links @topic_pages, :window_size => 10 %></strong></p> | ||
<% end -%> | ||
... | ... | |
<p class="pages">Pages: <strong><%= pagination_links @topic_pages, :window_size => 10 %></strong></p> | ||
<% end -%> | ||
98 | ||
<p><%= link_to 'New topic', new_topic_path(@forum), :class => "utility" %></p> | ||
100 |
rool/rails/beast/trunk/app/views/layouts/application.rhtml:
prev. | current | |
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> | ||
<title>RISC OS Open: Forum<%= ": #{h @page_title}" if @page_title %></title> | ||
<%= stylesheet_link_tag 'display' %> | ||
8 | ||
8 | <%# = javascript_include_tag "prototype", "effects", "lowpro", "application" %> | |
<% unless @feed_icons.blank? -%> | ||
<% @feed_icons.each do |feed| -%> | ||
<%= auto_discovery_link_tag :rss, feed[:url], :title => "Subscribe to '#{feed[:title]}'" %> | ||
... | ... | |
<%= render 'shared/fixed_sidebar' %> | ||
<p /> | ||
56 | | |
56 | <div class="sidebar-node"> | |
<%= @content_for_right %> | ||
</div> | ||
59 | | |
60 | | |
61 | | |
59 | ||
60 | <p /> | |
61 | <div class="sidebar-node"> | |
<h3>Options</h3> | ||
<ul> | ||
<li><%= link_to 'Forums', home_path, :rel => 'home' %></li> | ||
66 | | |
66 | <% if current_user && current_user != 0 && current_user.admin? -%><li><%= link_to 'Users', users_path %></li><% end -%> | |
<% if logged_in? %> | ||
68 | | |
69 | | |
70 | | |
68 | <li class="login"><%= link_to current_user.display_name, user_path(current_user) %></li> | |
69 | <li class="logout"><%= link_to "Logout", "/hub/account/logout" %></li> | |
<% else %> | ||
72 | | |
73 | | |
71 | <li><%= link_to "Login", "/hub/account/login" %></li> | |
<% end %> | ||
</ul> | ||
</div> |
rool/rails/beast/trunk/app/views/posts/edit.rhtml:
prev. | current | |
<h2><%= link_to h(@post.topic.title), topic_path(@post.forum_id, @post.topic) %></h2> | ||
5 | ||
6 | | |
5 | <%= error_messages_for :topic %> | |
8 | ||
<% form_for :post, :html => { :method => :put }, | ||
10 | | |
8 | :url => post_path(:forum_id => params[:forum_id], :topic_id => params[:topic_id], :id => @post, :page => params[:page]) do |f| -%> | |
<p id="post_body"><%= f.text_area :body %></p> | ||
12 | ||
13 | ||
11 | ||
12 | <p align="right"> | |
13 | <%= submit_tag 'Save' %>, | |
14 | <%= link_to 'cancel', topic_path(:forum_id => params[:forum_id], :id => params[:topic_id], :page => params[:page]) %>, | |
15 | </p> | |
16 | <% end -%> | |
17 | <% form_for(:post, | |
18 | { | |
19 | :html => { | |
20 | :method => :delete, | |
21 | :onsubmit => "return confirm('Are you sure you want to permanently delete this post?');" | |
22 | }, | |
23 | :url => post_path(:forum_id => params[:forum_id], | |
24 | :topic_id => params[:topic_id], | |
25 | :id => @post, | |
26 | :page => params[:page]) | |
27 | } | |
28 | ) do |f| -%> | |
29 | <p align="right"> | |
30 | or <%= submit_tag('Delete post forever') %> | |
31 | </p> | |
32 | <% end -%> | |
33 | ||
34 | <p /> | |
35 | <h5>Formatting Help</h5> | |
36 | ||
37 | <ul class="help"> | |
38 | <li>*bold* _italics_ bq. <span>(quotes)</span></li> | |
39 | <li>"IBM":http://www.ibm.com</li> | |
40 | <li>* or # <span>(lists)</span></li> | |
41 | </ul> | |
42 | ||
43 | See also the Textile reference <a href="http://hobix.com/textile/quick.html" target="_blank" onClick="quickRedReference(); return false;">here</a>. | |
44 | Don't worry about making mistakes - after adding a reply, you can edit | |
45 | your message as many times as you like. |
rool/rails/beast/trunk/app/views/posts/index.rhtml:
prev. | current | |
</div> | ||
<%= avatar_for @users[post.user_id] %> | ||
39 | | |
39 | <span class="fn"><%= link_to truncate(h(@users[post.user_id].display_name), 32), user_path(post.user_id), :class => (@users[post.user_id] == @users[@posts.first.user_id] ? "admin" : nil) %></span> | |
<span class="posts"><%= pluralize @users[post.user_id].posts_count, 'post' %></span> | ||
</td> | ||
<td class="body entry-content"> |
rool/rails/beast/trunk/app/views/posts/monitored.rhtml:
prev. | current | |
</div> | ||
<%= avatar_for post.user %> | ||
44 | | |
44 | <span class="fn"><%= link_to truncate(h(post.user.display_name), 32), user_path(post.user), :class => (post.user == @posts.first.user ? "admin" : nil) %></span> | |
<span class="posts"><%= pluralize post.user.posts_count, 'post' %></span> | ||
</td> | ||
<td class="body entry-content"> |
rool/rails/beast/trunk/app/views/shared/_theme.rhtml:
prev. | current | |
1 | ||
1 | -->The RISC OS Open Beast theme is based on Beast's default layout<!-- |
rool/rails/beast/trunk/app/views/topics/edit.rhtml:
prev. | current | |
<%= render :partial => "form", :object => f %> | ||
<br /> | ||
<%= submit_tag 'Save Changes', :or => link_to('Cancel', topic_path(@forum, @topic)) %> | ||
10 | ||
11 | <% end -%> | |
12 | ||
13 | <p /> | |
14 | <h5>Formatting Help</h5> | |
15 | ||
16 | <ul class="help"> | |
17 | <li>*bold* _italics_ bq. <span>(quotes)</span></li> | |
18 | <li>"IBM":http://www.ibm.com</li> | |
19 | <li>* or # <span>(lists)</span></li> | |
20 | </ul> | |
21 | ||
22 | See also the Textile reference <a href="http://hobix.com/textile/quick.html" target="_blank" onClick="quickRedReference(); return false;">here</a>. | |
23 | Don't worry about making mistakes - after adding a reply, you can edit | |
24 | your message as many times as you like. |
rool/rails/beast/trunk/app/views/topics/new.rhtml:
prev. | current | |
<%= submit_tag 'Post Topic', :or => link_to('Cancel', forum_path(@forum)) %> | ||
<% end -%> | ||
16 | <p /> | |
17 | <h5>Formatting Help</h5> | |
18 | ||
19 | <ul class="help"> | |
20 | <li>*bold* _italics_ bq. <span>(quotes)</span></li> | |
21 | <li>"IBM":http://www.ibm.com</li> | |
22 | <li>* or # <span>(lists)</span></li> | |
23 | </ul> | |
24 | ||
25 | See also the Textile reference <a href="http://hobix.com/textile/quick.html" target="_blank" onClick="quickRedReference(); return false;">here</a>. | |
26 | Don't worry about making mistakes - after adding a reply, you can edit | |
27 | your message as many times as you like. | |
28 | ||
<%= javascript_tag "$('topic_title').focus();" %> | ||
17 |
rool/rails/beast/trunk/app/views/topics/show.rhtml:
prev. | current | |
<% content_for :right do -%> | ||
6 | ||
6 | <h3>Voices</h3> | |
<ul class="flat talking"> | ||
<% @voices.each do | user | %> | ||
<li><%= link_to h(user.display_name), user_path(user) %></li> | ||
... | ... | |
<% end # right content -%> | ||
16 | ||
17 | ||
18 | ||
16 | <% if logged_in? -%> | |
17 | <% form_tag monitorships_path(@forum, @topic) + (@monitoring ? '/destroy' : ''), :style => 'margin-top:0em; float:right;' do -%> | |
<div> | ||
20 | | |
21 | | |
19 | <input id="monitor_checkbox" type="checkbox" <%= "checked='checked'" if @monitoring %> /> | |
<label id="monitor_label" for="monitor_checkbox">Watch<%= "ing" if @monitoring %> topic</label> | ||
23 | | |
<%= submit_tag :Set, :id => 'monitor_submit' %> | ||
</div> | ||
<% end -%> | ||
27 | ||
<% end -%> | ||
... | ... | |
<span>(locked)</span> | ||
<% end %> | ||
<% if logged_in? %> | ||
44 | | |
45 | | |
46 | | |
47 | | |
48 | | |
49 | | |
40 | <% if (current_user.admin? && @topic.editable_by?(current_user)) -%> | |
41 | <span id="topic_mod"> | |
42 | <%= link_to('edit', edit_topic_path(@forum, @topic), :class => "utility") %> | |
43 | <% form_for(:topic, | |
44 | { | |
45 | :html => { | |
46 | :method => :delete, | |
47 | :class => 'xdialog', | |
48 | :style => 'display:inline', | |
49 | :onsubmit => 'return confirm("Delete this topic forever?");' | |
50 | }, | |
51 | :url => topic_path(@forum, @topic) | |
52 | } | |
53 | ) do |f| -%> | |
54 | <%= submit_tag 'Delete' %> | |
55 | <% end -%> | |
56 | </span> | |
57 | <% end -%> | |
<% end %> | ||
</h1> | ||
... | ... | |
</div> | ||
<%= avatar_for post.user %> | ||
84 | | |
92 | <span class="fn"><%= link_to truncate(h(post.user.display_name), 32), user_path(post.user), :class => (post.user == @posts.first.user ? "admin" : nil) %></span> | |
<span class="posts"><%= pluralize post.user.posts_count, 'post' %></span> | ||
87 | | |
95 | <% if logged_in? && post.editable_by?(current_user) -%> | |
<p> | ||
<span class="edit"> | ||
90 | | |
91 | | |
92 | | |
93 | | |
94 | | |
98 | <%= link_to('Edit post', edit_post_path(:forum_id => @forum, :topic_id => @topic, :id => post), :class => "utility") %> | |
</span> | ||
</p> | ||
97 | | |
101 | <% end -%> | |
</td> | ||
... | ... | |
</p> | ||
<% else %> | ||
130 | ||
134 | <script language="JavaScript"> | |
135 | function quickRedReference() { | |
136 | window.open( | |
137 | "http://hobix.com/textile/quick.html", | |
138 | "redRef", | |
139 | "height=600,width=550,channelmode=0,dependent=0," + | |
140 | "directories=0,fullscreen=0,location=0,menubar=0," + | |
141 | "resizable=0,scrollbars=1,status=1,toolbar=0" | |
142 | ); | |
143 | } | |
144 | </script> | |
132 | ||
133 | ||
146 | <p /> | |
147 | <h3>Reply</h3> | |
148 | ||
149 | <p /> | |
150 | <div class="editbox container"> | |
<%= content_tag 'p', h(flash[:bad_reply]), :class => 'notice' if flash[:bad_reply] %> | ||
<% form_for :post, :url => posts_path(:forum_id => @forum, :topic_id => @topic, :page => @topic.last_page) do |f| -%> | ||
136 | | |
137 | | |
138 | | |
139 | | |
140 | | |
141 | | |
153 | <%= f.text_area :body, :rows => 8 %> | |
155 | <p /> | |
156 | <h5>Formatting Help</h5> | |
144 | | |
158 | <ul class="help"> | |
159 | <li>*bold* _italics_ bq. <span>(quotes)</span></li> | |
160 | <li>"IBM":http://www.ibm.com</li> | |
161 | <li>* or # <span>(lists)</span></li> | |
162 | </ul> | |
146 | | |
147 | | |
148 | | |
149 | | |
150 | | |
151 | | |
152 | | |
153 | | |
154 | | |
164 | See also the Textile reference <a href="http://hobix.com/textile/quick.html" target="_blank" onClick="quickRedReference(); return false;">here</a>. | |
165 | Don't worry about making mistakes - after adding a reply, you can edit | |
166 | your message as many times as you like. | |
156 | | |
157 | | |
158 | | |
159 | | |
160 | | |
161 | | |
162 | | |
163 | | |
168 | <p align="right"> | |
169 | <%= submit_tag "Save Reply" %> | |
170 | </p> | |
<% end -%> | ||
</div> | ||
166 | ||
167 | ||
<% end %> | ||
174 | <% else %> | |
175 | <p /> | |
176 | <h3>Reply</h3> | |
177 | ||
178 | <p /> | |
179 | To post replies, please first <a href="/hub/account/login">log in</a>. | |
<% end %> | ||
<div class="crumbs" style="margin-top:1.1em;"> |
rool/rails/beast/trunk/app/views/users/show.rhtml:
prev. | current | |
<% content_for :right do %> | ||
<% if admin? %> | ||
5 | ||
6 | | |
5 | <h3>Admin & Moderation</h3> | |
<% if @user.forums.any? -%> | ||
8 | <p>This user can moderate the following forums. Select one to remove it.</p> | |
10 | | |
11 | ||
12 | | |
<% @user.forums.find(:all, :select => 'forums.*, moderatorships.id as moderatorship_id').each do |forum| -%> | ||
14 | | |
15 | | |
16 | | |
17 | | |
18 | | |
11 | <div><%# form_for() calls form_tag() which for :method => :delete writes out a hidden INPUT field at the time of writing - but wraps it in an outer DIV. This broke earlier layout using <LI> items to hold the buttons. Sigh - I have so many reservations about Rails 1.2.x... Anyway, herein, a rather tragic workaround which gives up on <LI> tags but puts its own (currently redundant) DIV around the small form, to ensure line breaks work even in future Rails gets rid of its own strange little DIV. -%> | |
12 | <% form_for(:user, | |
13 | { | |
14 | :html => { | |
15 | :method => :delete, | |
16 | :class => 'xdialog', | |
17 | :onsubmit => 'return confirm("Are you sure you want to remove the user as a moderator for this forum?");' | |
18 | }, | |
19 | :url => moderator_path(@user, | |
20 | forum.moderatorship_id), | |
21 | } | |
22 | ) do |f| -%> | |
23 | <%= submit_tag forum.name %> | |
24 | <% end -%> | |
25 | </div> | |
<% end -%> | ||
20 | | |
<% end -%> | ||
<p> | ||
24 | | |
25 | | |
26 | | |
27 | | |
28 | | |
30 | <% form_for :user, :url => admin_user_path(@user), :html => {:class => "xdialog"} do |f| -%> | |
31 | <label>Add as moderator</label><br /> | |
32 | <select name="moderator"> | |
33 | <option value="-"></option> | |
34 | <%= options_from_collection_for_select(Forum.find(:all, :order => 'position') - @user.forums, "id", "name") %> | |
35 | </select></p> | |
30 | | |
37 | <p><label><%= f.check_box :admin %> User is an administrator</label></p> | |
32 | | |
39 | <p><%= submit_tag :Save %></p> | |
40 | <% end -%> | |
<% end -%> | ||
34 | ||
<% end %> | ||
<p style="float:right;"><%= avatar_for @user, 80 %></p> |
rool/rails/beast/trunk/config/routes.rb:
prev. | current | |
map.resources :users, :path_prefix => PATH_PREFIX, :member => { :admin => :post } do |user| | ||
user.resources :moderators | ||
end | ||
11 | | |
11 | ||
map.resources :forums, :path_prefix => PATH_PREFIX do |forum| | ||
forum.resources :topics do |topic| | ||
topic.resources :posts, :monitorships | ||
end | ||
end | ||
17 | ||
18 | # Fake DELETE requests to the monitorships controller result in a | |
19 | # routing error with default Beast routes. | |
20 | ||
21 | map.connect PATH_PREFIX + '/forums/:forum_id/topics/:topic_id/monitorships/destroy', :controller => 'monitorships', :action => 'destroy' | |
map.resources :posts, :name_prefix => 'all_', :path_prefix => PATH_PREFIX, :collection => { :search => :get } | ||
... | ... | |
end | ||
map.exceptions PATH_PREFIX + '/logged_exceptions/:action/:id', :controller => 'logged_exceptions', :action => 'index', :id => nil | ||
40 | ||
41 | # Old-fashioned route for backwards compatibility with RForum's | |
42 | # global feed location | |
43 | # | |
44 | map.exceptions PATH_PREFIX + '/feed/global', :controller => 'posts', :action => 'index_rss' | |
end |
rool/rails/beast/trunk/db/migrate/033_add_password_hash.rb:
prev. | current | |
# you need to edit your environment.rb and pick a non-default password salt | ||
# before you continue | ||
raise "ChangePasswordHash" if PASSWORD_SALT == '48e45be7d489cbb0ab582d26e2168621' | ||
8 | | |
9 | | |
8 | say_with_time "Hashing all your passwords in 5 seconds... this is a big deal (because it's not reversible), cancel if you aren't ready." do | |
9 | sleep 5 | |
end | ||
rename_column :users, :password, :password_hash | ||
say_with_time "Hashing passwords..." do |
rool/rails/beast/trunk/db/schema.rb:
prev. | current | |
t.column "body_html", :text | ||
end | ||
50 | | |
50 | add_index "posts", ["created_at", "forum_id"], :name => "index_posts_on_forum_id" | |
add_index "posts", ["user_id", "created_at"], :name => "index_posts_on_user_id" | ||
create_table "sessions", :force => true do |t| | ||
... | ... | |
t.column "user_id", :integer | ||
end | ||
60 | | |
60 | add_index "sessions", ["session_id"], :name => "index_sessions_on_session_id" | |
create_table "topics", :force => true do |t| | ||
t.column "forum_id", :integer | ||
... | ... | |
t.column "created_at", :datetime | ||
t.column "updated_at", :datetime | ||
t.column "hits", :integer, :default => 0 | ||
69 | | |
t.column "posts_count", :integer, :default => 0 | ||
t.column "replied_at", :datetime | ||
71 | t.column "sticky", :integer, :default => 0 | |
t.column "locked", :boolean, :default => false | ||
t.column "replied_by", :integer | ||
t.column "last_post_id", :integer | ||
end | ||
add_index "topics", ["forum_id"], :name => "index_topics_on_forum_id" | ||
78 | | |
78 | add_index "topics", ["forum_id", "replied_at", "sticky"], :name => "index_topics_on_sticky_and_replied_at" | |
create_table "users", :force => true do |t| | ||
t.column "login", :string |
rool/rails/beast/trunk/lib/authentication_system.rb:
prev. | current | |
module AuthenticationSystem | ||
2 | ||
3 | # Hub single sign-on support. The core of the old authentication system is | |
4 | # now delegated to this. | |
5 | ||
6 | require 'hub_sso_lib' | |
7 | include HubSsoLib::Core | |
8 | ||
protected | ||
# this is used to keep track of the last time a user has been seen (reading a topic) | ||
# it is used to know when topics are new or old and which should have the green | ||
... | ... | |
end | ||
def login_required | ||
23 | | |
24 | | |
30 | login_by_token unless logged_in? | |
respond_to do |format| | ||
format.html { redirect_to login_path } | ||
format.js { render(:update) { |p| p.redirect_to login_path } } | ||
... | ... | |
end | ||
def login_by_token | ||
36 | | |
37 | | |
42 | # Before doing anything else, check for stale login status. If logged out of | |
43 | # Hub but there's still an session active recorded internally, delete it. Do | |
44 | # the same if the e-mail address has changed (the user logged into a different | |
45 | # Hub account). | |
39 | | |
40 | | |
41 | | |
42 | | |
43 | | |
47 | if (logged_in?) | |
48 | if (!hubssolib_logged_in? || current_user.email != hubssolib_get_user_address) | |
49 | reset_session | |
50 | self.current_user = setup_user | |
51 | return | |
52 | end | |
53 | end | |
54 | ||
55 | # Don't confuse the local "logged_in?" session check with the notion | |
56 | # of being logged into Hub ("hubssolib_logged_in?"). | |
57 | ||
58 | self.current_user = setup_user if not logged_in? | |
end | ||
def authorized?() true end | ||
... | ... | |
end | ||
def logged_in? | ||
63 | | |
78 | current_user != 0 && hubssolib_logged_in? | |
end | ||
def admin? | ||
logged_in? && current_user.admin? | ||
end | ||
69 | ||
85 | ||
86 | # Get a unique login string from the Hub user, in abstracted form. | |
87 | # While it must be unique, its content is irrelevant in the Hub | |
88 | # integrated forum as it doesn't get displayed. We use this instead | |
89 | # of e-mail address because we want to detect an e-mail address | |
90 | # being used more than once by different users to cope with stale | |
91 | # Hub accounts or recycled e-mail addresses. | |
92 | # | |
93 | def get_hub_user_name | |
94 | Digest::SHA1.hexdigest("#{hubssolib_unique_name}") | |
95 | end | |
96 | ||
97 | # Map a Hub user's parameters to a forum User model's | |
98 | # parameters. Returns a hash appropriate for updating an | |
99 | # existing model or to create a brand new forum User. | |
100 | # | |
101 | def map_hub_user_to_forum_user | |
102 | ||
103 | return { | |
104 | :login => get_hub_user_name, | |
105 | :email => hubssolib_get_user_address, | |
106 | :admin => hub_user_is_forum_admin?, | |
107 | :display_name => hubssolib_unique_name, | |
108 | :website => '', | |
109 | :bio => '', | |
110 | :bio_html => '', | |
111 | :activated => true | |
112 | } | |
113 | end | |
114 | ||
115 | # Is the current Hub user a forum administrator, based on | |
116 | # their Hub roles? | |
117 | # | |
118 | def hub_user_is_forum_admin? | |
119 | hubssolib_get_user_roles.include?('admin,webmaster') ? true : false | |
120 | end | |
121 | ||
122 | # Filter method that sets user parameters by mapping in the | |
123 | # currently logged in Hub user to a new or updated forum user. | |
124 | # Returns the user details. It is up to the caller to record | |
125 | # or discard those details. | |
126 | # | |
127 | def setup_user | |
128 | user = nil | |
129 | ||
130 | if (hubssolib_logged_in?) | |
131 | user = User.find_by_login(get_hub_user_name) | |
132 | ||
133 | # This for now is the quick and dirty code. We either create | |
134 | # a new user on a default map of parameters from Hub to | |
135 | # forum user, or we update the Hub parts - on each and every | |
136 | # action in forum. This is, obviously, very slow. | |
137 | ||
138 | if (user) | |
139 | user.update_attributes(map_hub_user_to_forum_user) | |
140 | else | |
141 | ||
142 | # There is no user with the same unique ID, but there may be | |
143 | # a user with the same e-mail address - somebody might have | |
144 | # deleted and recreated their account, or a person may have | |
145 | # given up an e-mail address but it could have been claimed | |
146 | # by an entirely new user. In any event, a new ID with the | |
147 | # same e-mail address implies the old address is stale; Hub | |
148 | # insists on unique addreses. We don't want to delete that | |
149 | # user because their user name is associated with posts, so | |
150 | # instead, clear its email address. | |
151 | ||
152 | @other_user = User.find_by_email(hubssolib_get_user_address) | |
153 | ||
154 | if @other_user | |
155 | @other_user.email = '' | |
156 | @other_user.save! | |
157 | end | |
158 | ||
159 | # Now create the shiny new account and save it. | |
160 | ||
161 | user = User.new(map_hub_user_to_forum_user) | |
162 | user.save! | |
163 | end | |
164 | ||
165 | return user; | |
166 | else | |
167 | return nil; | |
168 | end | |
169 | end | |
170 | end |
rool/rails/beast/trunk/public/stylesheets/display.css:
prev. | current | |
@import url("/css/risc_os_open.css"); | ||
8 | div.sidebar-node p {font-size:80%;} | |
9 | div.sidebar-node form.xdialog | |
10 | { | |
11 | white-space: normal; | |
12 | } | |
13 | ||
#content form {margin-bottom:0;} | ||
#content p.subtle | ||
... | ... | |
#content p.subtitle img { vertical-align: bottom; } | ||
#content p.subtitle a { border: none; } | ||
86 | ||
92 | #content h1 { margin-bottom: 10px; font-size: 160%; } | |
#content h1 img { vertical-align:middle; } | ||
#content h1 span { font-size:0.7em; color:#999; font-weight:normal; padding-left: 1em;} | ||
... | ... | |
margin-left:1em; | ||
} | ||
99 | ||
105 | #content h5 | |
{ | ||
padding:2px 10px 3px; | ||
background:#ddd; | ||
103 | | |
104 | | |
109 | font-size: 80%; | |
} | ||
#content h6 { margin-bottom:0; } | ||
... | ... | |
#content .photo | ||
{ | ||
330 | | |
335 | background: url(/forum/images/clearbits/smile.gif) no-repeat 8px 8px; | |
} | ||
338 | #content span.fn | |
339 | { | |
340 | display:block; | |
341 | margin-left:44px; | |
342 | } | |
343 | ||
#content .smallutils | ||
{ | ||
xfloat:right; | ||
... | ... | |
#content table.forums .posts | ||
{ | ||
color:#666; | ||
415 | | |
426 | font-size:0.8em%; | |
} | ||
#content table tr th.la { text-align:left; } | ||
... | ... | |
#content .post .author .posts | ||
{ | ||
display:block; | ||
557 | | |
558 | | |
568 | font-size:80%; | |
color:#666; | ||
570 | margin-top:6px; | |
} | ||
#content .post .author a | ||
... | ... | |
float:right; | ||
} | ||
663 | ||
674 | /* Reply */ | |
#content div.editbox | ||
{ | ||
667 | | |
668 | | |
669 | | |
670 | | |
671 | | |
672 | | |
673 | | |
674 | | |
675 | | |
678 | border-bottom: 1px solid #333; | |
} | ||
678 | ||
679 | ||
680 | | |
681 | | |
682 | | |
683 | ||
684 | ||
#content div.editbox p { margin:0.5em 0;} | ||
686 | ||
682 | #content textarea | |
{ | ||
width:100%; | ||
689 | | |
690 | | |
691 | | |
} | ||
#content div.editbox .button_or a | ||
... | ... | |
#content div.editbox p.help, | ||
#content div.editbox ul.help | ||
{ | ||
724 | | |
717 | padding: 3px 20px; | |
font-size:0.75em; | ||
726 | | |
719 | color:#888; | |
} | ||
729 | ||
730 | ||
731 | ||
732 | ||
733 | | |
734 | ||
735 | | |
#content #monitor_topic a | ||
{ | ||
color: #666; |