Anonymous users can now be allowed to create, edit, comment issues, comment news and post messages in the forums.

These permissions need to be explicitly given to the Anonymous role (Admin -> Roles & Permissions -> Anonymous).

git-svn-id: http://redmine.rubyforge.org/svn/trunk@919 e93f8b46-1217-0410-a6f0-8f06a7374b81
This commit is contained in:
Jean-Philippe Lang 2007-11-20 15:40:16 +00:00
parent 99f9aea80a
commit 987a5aa221
19 changed files with 88 additions and 79 deletions

View File

@ -23,10 +23,6 @@ class ApplicationController < ActionController::Base
require_dependency "repository/#{scm.underscore}"
end
def logged_in_user
User.current.logged? ? User.current : nil
end
def current_role
@current_role ||= User.current.role_for_project(@project)
end

View File

@ -49,7 +49,7 @@ class DocumentsController < ApplicationController
@attachments = []
params[:attachments].each { |file|
next unless file.size > 0
a = Attachment.create(:container => @document, :file => file, :author => logged_in_user)
a = Attachment.create(:container => @document, :file => file, :author => User.current)
@attachments << a unless a.new_record?
} if params[:attachments] and params[:attachments].is_a? Array
Mailer.deliver_attachments_added(@attachments) if !@attachments.empty? && Setting.notified_events.include?('document_added')

View File

@ -82,7 +82,7 @@ class IssuesController < ApplicationController
def show
@custom_values = @issue.custom_values.find(:all, :include => :custom_field, :order => "#{CustomField.table_name}.position")
@journals = @issue.journals.find(:all, :include => [:user, :details], :order => "#{Journal.table_name}.created_on ASC")
@status_options = @issue.status.find_new_statuses_allowed_to(logged_in_user.role_for_project(@project), @issue.tracker) if logged_in_user
@status_options = @issue.status.find_new_statuses_allowed_to(User.current.role_for_project(@project), @issue.tracker)
respond_to do |format|
format.html { render :template => 'issues/show.rhtml' }
format.pdf { send_data(render(:template => 'issues/show.rfpdf', :layout => false), :type => 'application/pdf', :filename => "#{@project.identifier}-#{@issue.id}.pdf") }
@ -95,7 +95,7 @@ class IssuesController < ApplicationController
@custom_values = @project.custom_fields_for_issues(@issue.tracker).collect { |x| @issue.custom_values.find_by_custom_field_id(x.id) || CustomValue.new(:custom_field => x, :customized => @issue) }
else
begin
@issue.init_journal(self.logged_in_user)
@issue.init_journal(User.current)
# Retrieve custom fields and values
if params["custom_fields"]
@custom_values = @project.custom_fields_for_issues(@issue.tracker).collect { |x| CustomValue.new(:custom_field => x, :customized => @issue, :value => params["custom_fields"][x.id.to_s]) }
@ -117,7 +117,7 @@ class IssuesController < ApplicationController
journal = @issue.init_journal(User.current, params[:notes])
params[:attachments].each { |file|
next unless file.size > 0
a = Attachment.create(:container => @issue, :file => file, :author => logged_in_user)
a = Attachment.create(:container => @issue, :file => file, :author => User.current)
journal.details << JournalDetail.new(:property => 'attachment',
:prop_key => a.id,
:value => a.filename) unless a.new_record?
@ -132,17 +132,17 @@ class IssuesController < ApplicationController
end
def change_status
@status_options = @issue.status.find_new_statuses_allowed_to(logged_in_user.role_for_project(@project), @issue.tracker) if logged_in_user
@status_options = @issue.status.find_new_statuses_allowed_to(User.current.role_for_project(@project), @issue.tracker)
@new_status = IssueStatus.find(params[:new_status_id])
if params[:confirm]
begin
journal = @issue.init_journal(self.logged_in_user, params[:notes])
journal = @issue.init_journal(User.current, params[:notes])
@issue.status = @new_status
if @issue.update_attributes(params[:issue])
# Save attachments
params[:attachments].each { |file|
next unless file.size > 0
a = Attachment.create(:container => @issue, :file => file, :author => logged_in_user)
a = Attachment.create(:container => @issue, :file => file, :author => User.current)
journal.details << JournalDetail.new(:property => 'attachment',
:prop_key => a.id,
:value => a.filename) unless a.new_record?
@ -150,7 +150,7 @@ class IssuesController < ApplicationController
# Log time
if current_role.allowed_to?(:log_time)
@time_entry ||= TimeEntry.new(:project => @project, :issue => @issue, :user => logged_in_user, :spent_on => Date.today)
@time_entry ||= TimeEntry.new(:project => @project, :issue => @issue, :user => User.current, :spent_on => Date.today)
@time_entry.attributes = params[:time_entry]
@time_entry.save
end
@ -176,7 +176,7 @@ class IssuesController < ApplicationController
def destroy_attachment
a = @issue.attachments.find(params[:attachment_id])
a.destroy
journal = @issue.init_journal(self.logged_in_user)
journal = @issue.init_journal(User.current)
journal.details << JournalDetail.new(:property => 'attachment',
:prop_key => a.id,
:old_value => a.filename)
@ -225,12 +225,11 @@ private
def retrieve_query
if params[:query_id]
@query = Query.find(params[:query_id], :conditions => {:project_id => (@project ? @project.id : nil)})
@query.executed_by = logged_in_user
session[:query] = @query
else
if params[:set_filter] or !session[:query] or session[:query].project != @project
# Give it a name, required to be valid
@query = Query.new(:name => "_", :executed_by => logged_in_user)
@query = Query.new(:name => "_")
@query.project = @project
if params[:fields] and params[:fields].is_a? Array
params[:fields].each do |field|

View File

@ -31,12 +31,12 @@ class MessagesController < ApplicationController
def new
@message = Message.new(params[:message])
@message.author = logged_in_user
@message.author = User.current
@message.board = @board
if request.post? && @message.save
params[:attachments].each { |file|
next unless file.size > 0
Attachment.create(:container => @message, :file => file, :author => logged_in_user)
Attachment.create(:container => @message, :file => file, :author => User.current)
} if params[:attachments] and params[:attachments].is_a? Array
redirect_to :action => 'show', :id => @message
end
@ -44,7 +44,7 @@ class MessagesController < ApplicationController
def reply
@reply = Message.new(params[:reply])
@reply.author = logged_in_user
@reply.author = User.current
@reply.board = @board
@message.children << @reply
redirect_to :action => 'show', :id => @message

View File

@ -44,7 +44,7 @@ class MyController < ApplicationController
# Show user's page
def page
@user = self.logged_in_user
@user = User.current
@blocks = @user.pref[:my_page_layout] || DEFAULT_LAYOUT
end
@ -76,7 +76,7 @@ class MyController < ApplicationController
# Manage user's password
def password
@user = self.logged_in_user
@user = User.current
flash[:error] = l(:notice_can_t_change_password) and redirect_to :action => 'account' and return if @user.auth_source_id
if request.post?
if @user.check_password?(params[:password])
@ -102,7 +102,7 @@ class MyController < ApplicationController
# User's page layout configuration
def page_layout
@user = self.logged_in_user
@user = User.current
@blocks = @user.pref[:my_page_layout] || DEFAULT_LAYOUT.dup
session[:page_layout] = @blocks
%w(top left right).each {|f| session[:page_layout][f] ||= [] }
@ -116,7 +116,7 @@ class MyController < ApplicationController
def add_block
block = params[:block]
render(:nothing => true) and return unless block && (BLOCKS.keys.include? block)
@user = self.logged_in_user
@user = User.current
# remove if already present in a group
%w(top left right).each {|f| (session[:page_layout][f] ||= []).delete block }
# add it on top
@ -151,7 +151,7 @@ class MyController < ApplicationController
# Save user's page layout
def page_layout_save
@user = self.logged_in_user
@user = User.current
@user.pref[:my_page_layout] = session[:page_layout] if session[:page_layout]
@user.pref.save
session[:page_layout] = nil

View File

@ -45,7 +45,7 @@ class NewsController < ApplicationController
def add_comment
@comment = Comment.new(params[:comment])
@comment.author = logged_in_user
@comment.author = User.current
if @news.comments << @comment
flash[:notice] = l(:label_comment_added)
redirect_to :action => 'show', :id => @news

View File

@ -48,7 +48,7 @@ class ProjectsController < ApplicationController
# Lists visible projects
def list
projects = Project.find :all,
:conditions => Project.visible_by(logged_in_user),
:conditions => Project.visible_by(User.current),
:include => :parent
@project_tree = projects.group_by {|p| p.parent || p}
@project_tree.each_key {|p| @project_tree[p] -= [p]}
@ -176,7 +176,7 @@ class ProjectsController < ApplicationController
if request.post? and @document.save
# Save the attachments
params[:attachments].each { |a|
Attachment.create(:container => @document, :file => a, :author => logged_in_user) unless a.size == 0
Attachment.create(:container => @document, :file => a, :author => User.current) unless a.size == 0
} if params[:attachments] and params[:attachments].is_a? Array
flash[:notice] = l(:notice_successful_create)
Mailer.deliver_document_added(@document) if Setting.notified_events.include?('document_added')
@ -216,7 +216,7 @@ class ProjectsController < ApplicationController
return
end
@issue.status = default_status
@allowed_statuses = ([default_status] + default_status.find_new_statuses_allowed_to(logged_in_user.role_for_project(@project), @issue.tracker))if logged_in_user
@allowed_statuses = ([default_status] + default_status.find_new_statuses_allowed_to(User.current.role_for_project(@project), @issue.tracker))
if request.get?
@issue.start_date ||= Date.today
@ -321,10 +321,9 @@ class ProjectsController < ApplicationController
# Add a news to @project
def add_news
@news = News.new(:project => @project)
@news = News.new(:project => @project, :author => User.current)
if request.post?
@news.attributes = params[:news]
@news.author_id = self.logged_in_user.id if self.logged_in_user
if @news.save
flash[:notice] = l(:notice_successful_create)
Mailer.deliver_news_added(@news) if Setting.notified_events.include?('news_added')
@ -340,7 +339,7 @@ class ProjectsController < ApplicationController
@attachments = []
params[:attachments].each { |file|
next unless file.size > 0
a = Attachment.create(:container => @version, :file => file, :author => logged_in_user)
a = Attachment.create(:container => @version, :file => file, :author => User.current)
@attachments << a unless a.new_record?
} if params[:attachments] and params[:attachments].is_a? Array
Mailer.deliver_attachments_added(@attachments) if !@attachments.empty? && Setting.notified_events.include?('file_added')

View File

@ -22,14 +22,13 @@ class QueriesController < ApplicationController
def index
@queries = @project.queries.find(:all,
:order => "name ASC",
:conditions => ["is_public = ? or user_id = ?", true, (logged_in_user ? logged_in_user.id : 0)])
:conditions => ["is_public = ? or user_id = ?", true, (User.current.logged? ? User.current.id : 0)])
end
def new
@query = Query.new(params[:query])
@query.project = @project
@query.user = logged_in_user
@query.executed_by = logged_in_user
@query.user = User.current
@query.is_public = false unless current_role.allowed_to?(:manage_public_queries)
@query.column_names = nil if params[:default_columns]
@ -71,9 +70,8 @@ private
def find_project
if params[:id]
@query = Query.find(params[:id])
@query.executed_by = logged_in_user
@project = @query.project
render_403 unless @query.editable_by?(logged_in_user)
render_403 unless @query.editable_by?(User.current)
else
@project = Project.find(params[:project_id])
end

View File

@ -31,7 +31,7 @@ class SearchController < ApplicationController
begin; offset = params[:offset].to_time if params[:offset]; rescue; end
# quick jump to an issue
if @question.match(/^#?(\d+)$/) && Issue.find_by_id($1, :include => :project, :conditions => Project.visible_by(logged_in_user))
if @question.match(/^#?(\d+)$/) && Issue.find_by_id($1, :include => :project, :conditions => Project.visible_by(User.current))
redirect_to :controller => "issues", :action => "show", :id => $1
return
end
@ -87,7 +87,7 @@ class SearchController < ApplicationController
end
else
operator = @all_words ? ' AND ' : ' OR '
Project.with_scope(:find => {:conditions => Project.visible_by(logged_in_user)}) do
Project.with_scope(:find => {:conditions => Project.visible_by(User.current)}) do
@results += Project.find(:all, :limit => limit, :conditions => [ (["(LOWER(name) like ? OR LOWER(description) like ?)"] * like_tokens.size).join(operator), * (like_tokens * 2).sort] ) if @scope.include? 'projects'
end
# if only one project is found, user is redirected to its overview

View File

@ -107,15 +107,15 @@ class TimelogController < ApplicationController
@entries = (@issue ? @issue : @project).time_entries.find(:all, :include => [:activity, :user, {:issue => [:tracker, :assigned_to, :priority]}], :order => sort_clause)
@total_hours = @entries.inject(0) { |sum,entry| sum + entry.hours }
@owner_id = logged_in_user ? logged_in_user.id : 0
@owner_id = User.current.id
send_csv and return if 'csv' == params[:export]
render :action => 'details', :layout => false if request.xhr?
end
def edit
render_404 and return if @time_entry && @time_entry.user != logged_in_user
@time_entry ||= TimeEntry.new(:project => @project, :issue => @issue, :user => logged_in_user, :spent_on => Date.today)
render_404 and return if @time_entry && @time_entry.user != User.current
@time_entry ||= TimeEntry.new(:project => @project, :issue => @issue, :user => User.current, :spent_on => Date.today)
@time_entry.attributes = params[:time_entry]
if request.post? and @time_entry.save
flash[:notice] = l(:notice_successful_update)

View File

@ -19,7 +19,7 @@ class WelcomeController < ApplicationController
layout 'base'
def index
@news = News.latest logged_in_user
@projects = Project.latest logged_in_user
@news = News.latest User.current
@projects = Project.latest User.current
end
end

View File

@ -69,7 +69,7 @@ class WikiController < ApplicationController
#@content.text = params[:content][:text]
#@content.comments = params[:content][:comments]
@content.attributes = params[:content]
@content.author = logged_in_user
@content.author = User.current
# if page is new @page.save will also save content, but not if page isn't a new record
if (@page.new_record? ? @page.save : @content.save)
redirect_to :action => 'index', :id => @project, :page => @page.title
@ -157,7 +157,7 @@ class WikiController < ApplicationController
# Save the attachments
params[:attachments].each { |file|
next unless file.size > 0
a = Attachment.create(:container => @page, :file => file, :author => logged_in_user)
a = Attachment.create(:container => @page, :file => file, :author => User.current)
} if params[:attachments] and params[:attachments].is_a? Array
redirect_to :action => 'index', :page => @page.title
end

View File

@ -21,7 +21,7 @@ class Attachment < ActiveRecord::Base
belongs_to :container, :polymorphic => true
belongs_to :author, :class_name => "User", :foreign_key => "author_id"
validates_presence_of :container, :filename
validates_presence_of :container, :filename, :author
validates_length_of :filename, :maximum => 255
validates_length_of :disk_filename, :maximum => 255
@ -82,11 +82,6 @@ class Attachment < ActiveRecord::Base
def increment_download
increment!(:downloads)
end
# returns last created projects
def self.most_downloaded
find(:all, :limit => 5, :order => "downloads DESC")
end
def project
container.is_a?(Project) ? container : container.project

View File

@ -112,11 +112,8 @@ class Query < ActiveRecord::Base
def initialize(attributes = nil)
super attributes
self.filters ||= { 'status_id' => {:operator => "o", :values => [""]} }
end
def executed_by=(user)
@executed_by = user
set_language_if_valid(user.language) if user
@executed_by = User.current.logged? ? User.current : nil
set_language_if_valid(executed_by.language) if executed_by
end
def validate

View File

@ -19,6 +19,7 @@ require "digest/sha1"
class User < ActiveRecord::Base
# Account statuses
STATUS_ANONYMOUS = 0
STATUS_ACTIVE = 1
STATUS_REGISTERED = 2
STATUS_LOCKED = 3
@ -36,15 +37,15 @@ class User < ActiveRecord::Base
# Prevents unauthorized assignments
attr_protected :login, :admin, :password, :password_confirmation, :hashed_password
validates_presence_of :login, :firstname, :lastname, :mail
validates_presence_of :login, :firstname, :lastname, :mail, :if => Proc.new { |user| !user.is_a?(AnonymousUser) }
validates_uniqueness_of :login, :mail
# Login must contain lettres, numbers, underscores only
validates_format_of :login, :with => /^[a-z0-9_\-@\.]+$/i
validates_format_of :login, :with => /^[a-z0-9_\-@\.]*$/i
validates_length_of :login, :maximum => 30
validates_format_of :firstname, :lastname, :with => /^[\w\s\'\-]*$/i
validates_length_of :firstname, :lastname, :maximum => 30
validates_format_of :mail, :with => /^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i
validates_length_of :mail, :maximum => 60
validates_format_of :mail, :with => /^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i, :allow_nil => true
validates_length_of :mail, :maximum => 60, :allow_nil => true
# Password length between 4 and 12
validates_length_of :password, :in => 4..12, :allow_nil => true
validates_confirmation_of :password, :allow_nil => true
@ -216,11 +217,17 @@ class User < ActiveRecord::Base
end
def self.current
@current_user ||= AnonymousUser.new
@current_user ||= User.anonymous
end
def self.anonymous
AnonymousUser.new
return @anonymous_user if @anonymous_user
anonymous_user = AnonymousUser.find(:first)
if anonymous_user.nil?
anonymous_user = AnonymousUser.create(:lastname => 'Anonymous', :firstname => '', :mail => '', :login => '', :status => 0)
raise 'Unable to create the anonymous user.' if anonymous_user.new_record?
end
@anonymous_user = anonymous_user
end
private
@ -231,16 +238,17 @@ private
end
class AnonymousUser < User
def logged?
false
def validate_on_create
# There should be only one AnonymousUser in the database
errors.add_to_base 'An anonymous user already exists.' if AnonymousUser.find(:first)
end
def time_zone
nil
end
# Anonymous user has no RSS key
def rss_key
nil
end
# Overrides a few properties
def logged?; false end
def admin; false end
def name; 'Anonymous' end
def mail; nil end
def time_zone; nil end
def rss_key; nil end
end

View File

@ -26,7 +26,7 @@
<h3 class="icon22 icon22-comment"><%= l(:label_comment_plural) %></h3>
<% @news.comments.each do |comment| %>
<% next if comment.new_record? %>
<h4><%= format_time(comment.created_on) %> - <%= comment.author.name %></h4>
<h4><%= authoring comment.created_on, comment.author %></h4>
<div class="contextual">
<%= link_to_if_authorized l(:button_delete), {:controller => 'news', :action => 'destroy_comment', :id => @news, :comment_id => comment}, :confirm => l(:text_are_you_sure), :method => :post, :class => 'icon icon-del' %>
</div>

View File

@ -0,0 +1,10 @@
class AddUsersType < ActiveRecord::Migration
def self.up
add_column :users, :type, :string
User.update_all "type = 'User'"
end
def self.down
remove_column :users, :type
end
end

View File

@ -29,11 +29,11 @@ Redmine::AccessControl.map do |map|
:issues => [:index, :changes, :show, :context_menu],
:queries => :index,
:reports => :issue_report}, :public => true
map.permission :add_issues, {:projects => :add_issue}, :require => :loggedin
map.permission :add_issues, {:projects => :add_issue}
map.permission :edit_issues, {:projects => :bulk_edit_issues,
:issues => [:edit, :destroy_attachment]}, :require => :loggedin
map.permission :manage_issue_relations, {:issue_relations => [:new, :destroy]}, :require => :loggedin
map.permission :add_issue_notes, {:issues => :add_note}, :require => :loggedin
:issues => [:edit, :destroy_attachment]}
map.permission :manage_issue_relations, {:issue_relations => [:new, :destroy]}
map.permission :add_issue_notes, {:issues => :add_note}
map.permission :change_issue_status, {:issues => :change_status}, :require => :loggedin
map.permission :move_issues, {:projects => :move_issues}, :require => :loggedin
map.permission :delete_issues, {:issues => :destroy}, :require => :member
@ -53,7 +53,7 @@ Redmine::AccessControl.map do |map|
map.project_module :news do |map|
map.permission :manage_news, {:projects => :add_news, :news => [:edit, :destroy, :destroy_comment]}, :require => :member
map.permission :view_news, {:news => [:index, :show]}, :public => true
map.permission :comment_news, {:news => :add_comment}, :require => :loggedin
map.permission :comment_news, {:news => :add_comment}
end
map.project_module :documents do |map|
@ -83,7 +83,7 @@ Redmine::AccessControl.map do |map|
map.project_module :boards do |map|
map.permission :manage_boards, {:boards => [:new, :edit, :destroy]}, :require => :member
map.permission :view_messages, {:boards => [:index, :show], :messages => [:show]}, :public => true
map.permission :add_messages, {:messages => [:new, :reply]}, :require => :loggedin
map.permission :add_messages, {:messages => [:new, :reply]}
end
end

View File

@ -60,7 +60,7 @@ class UserTest < Test::Unit::TestCase
def test_validate
@admin.login = ""
assert !@admin.save
assert_equal 2, @admin.errors.count
assert_equal 1, @admin.errors.count
end
def test_password
@ -87,6 +87,13 @@ class UserTest < Test::Unit::TestCase
assert_equal nil, user
end
def test_create_anonymous
AnonymousUser.delete_all
anon = User.anonymous
assert !anon.new_record?
assert_kind_of AnonymousUser, anon
end
def test_rss_key
assert_nil @jsmith.rss_token
key = @jsmith.rss_key