diff --git a/app/controllers/account_controller.rb b/app/controllers/account_controller.rb index 8ee046a0c777f62453fdd7f84846de47ea0a218e..44e4cc22100a7b345457934b9e413e56d69ac390 100644 --- a/app/controllers/account_controller.rb +++ b/app/controllers/account_controller.rb @@ -22,7 +22,6 @@ class AccountController < ApplicationController # prevents login action to be filtered by check_if_login_required application scope filter skip_before_filter :check_if_login_required, :only => [:login, :lost_password, :register] - before_filter :require_login, :only => :logout # Show user's account def show @@ -31,7 +30,7 @@ class AccountController < ApplicationController # show only public projects and private projects that the logged in user is also a member of @memberships = @user.memberships.select do |membership| - membership.project.is_public? || (logged_in_user && logged_in_user.role_for_project(membership.project)) + membership.project.is_public? || (User.current.role_for_project(membership.project)) end rescue ActiveRecord::RecordNotFound render_404 @@ -41,12 +40,12 @@ class AccountController < ApplicationController def login if request.get? # Logout user - self.logged_in_user = nil + self.logged_user = nil else # Authenticate user user = User.try_to_login(params[:login], params[:password]) if user - self.logged_in_user = user + self.logged_user = user # generate a key and set cookie if autologin if params[:autologin] && Setting.autologin? token = Token.create(:user => user, :action => 'autologin') @@ -62,8 +61,8 @@ class AccountController < ApplicationController # Log out current user and redirect to welcome page def logout cookies.delete :autologin - Token.delete_all(["user_id = ? AND action = ?", logged_in_user.id, "autologin"]) if logged_in_user - self.logged_in_user = nil + Token.delete_all(["user_id = ? AND action = ?", User.current.id, 'autologin']) if User.current.logged? + self.logged_user = nil redirect_to :controller => 'welcome' end @@ -140,4 +139,15 @@ class AccountController < ApplicationController end end end + +private + def logged_user=(user) + if user && user.is_a?(User) + User.current = user + session[:user_id] = user.id + else + User.current = User.anonymous + session[:user_id] = nil + end + end end diff --git a/app/controllers/admin_controller.rb b/app/controllers/admin_controller.rb index 95d3505c72776d52c6ba6963c3c40c0dcfe55569..78fd1aa15a60ca6cb20fb401a3061a2d2a10ad49 100644 --- a/app/controllers/admin_controller.rb +++ b/app/controllers/admin_controller.rb @@ -46,14 +46,6 @@ class AdminController < ApplicationController end def mail_options - @actions = Permission.find(:all, :conditions => ["mail_option=?", true]) || [] - if request.post? - @actions.each { |a| - a.mail_enabled = (params[:action_ids] || []).include? a.id.to_s - a.save - } - flash.now[:notice] = l(:notice_successful_update) - end end def test_email @@ -61,8 +53,8 @@ class AdminController < ApplicationController # Force ActionMailer to raise delivery errors so we can catch it ActionMailer::Base.raise_delivery_errors = true begin - @test = Mailer.deliver_test(logged_in_user) - flash[:notice] = l(:notice_email_sent, logged_in_user.mail) + @test = Mailer.deliver_test(User.current) + flash[:notice] = l(:notice_email_sent, User.current.mail) rescue Exception => e flash[:error] = l(:notice_email_error, e.message) end diff --git a/app/controllers/application.rb b/app/controllers/application.rb index 3f5a2c76fdf11942a017df5966f8749c8875d439..cac2d64644c55d2ae9f9466a0be42fd115e115c9 100644 --- a/app/controllers/application.rb +++ b/app/controllers/application.rb @@ -16,48 +16,47 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. class ApplicationController < ActionController::Base - before_filter :check_if_login_required, :set_localization + before_filter :user_setup, :check_if_login_required, :set_localization filter_parameter_logging :password REDMINE_SUPPORTED_SCM.each do |scm| require_dependency "repository/#{scm.underscore}" end - def logged_in_user=(user) - @logged_in_user = user - session[:user_id] = (user ? user.id : nil) + def logged_in_user + User.current.logged? ? User.current : nil end - def logged_in_user + def current_role + @current_role ||= User.current.role_for_project(@project) + end + + def user_setup if session[:user_id] - @logged_in_user ||= User.find(session[:user_id]) + # existing session + User.current = User.find(session[:user_id]) + elsif cookies[:autologin] && Setting.autologin? + # auto-login feature + User.current = User.find_by_autologin_key(autologin_key) + elsif params[:key] && accept_key_auth_actions.include?(params[:action]) + # RSS key authentication + User.current = User.find_by_rss_key(params[:key]) else - nil + User.current = User.anonymous end end - # Returns the role that the logged in user has on the current project - # or nil if current user is not a member of the project - def logged_in_user_membership - @user_membership ||= logged_in_user.role_for_project(@project) - end - # check if login is globally required to access the application def check_if_login_required # no check needed if user is already logged in - return true if logged_in_user - # auto-login feature - autologin_key = cookies[:autologin] - if autologin_key && Setting.autologin? - self.logged_in_user = User.find_by_autologin_key(autologin_key) - end + return true if User.current.logged? require_login if Setting.login_required? end def set_localization lang = begin - if self.logged_in_user and self.logged_in_user.language and !self.logged_in_user.language.empty? and GLoc.valid_languages.include? self.logged_in_user.language.to_sym - self.logged_in_user.language + if !User.current.language.blank? and GLoc.valid_languages.include? User.current.language.to_sym + User.current.language elsif request.env['HTTP_ACCEPT_LANGUAGE'] accept_lang = parse_qvalues(request.env['HTTP_ACCEPT_LANGUAGE']).first.split('-').first if accept_lang and !accept_lang.empty? and GLoc.valid_languages.include? accept_lang.to_sym @@ -71,7 +70,7 @@ class ApplicationController < ActionController::Base end def require_login - unless self.logged_in_user + if !User.current.logged? store_location redirect_to :controller => "account", :action => "login" return false @@ -81,34 +80,17 @@ class ApplicationController < ActionController::Base def require_admin return unless require_login - unless self.logged_in_user.admin? + if !User.current.admin? render_403 return false end true end - # authorizes the user for the requested action. + # Authorize the user for the requested action def authorize(ctrl = params[:controller], action = params[:action]) - unless @project.active? - @project = nil - render_404 - return false - end - # check if action is allowed on public projects - if @project.is_public? and Permission.allowed_to_public "%s/%s" % [ ctrl, action ] - return true - end - # if action is not public, force login - return unless require_login - # admin is always authorized - return true if self.logged_in_user.admin? - # if not admin, check membership permission - if logged_in_user_membership and Permission.allowed_to_role( "%s/%s" % [ ctrl, action ], logged_in_user_membership ) - return true - end - render_403 - false + allowed = User.current.allowed_to?({:controller => ctrl, :action => action}, @project) + allowed ? true : (User.current.logged? ? render_403 : require_login) end # make sure that the user is a member of the project (or admin) if project is private @@ -119,11 +101,8 @@ class ApplicationController < ActionController::Base render_404 return false end - return true if @project.is_public? - return false unless logged_in_user - return true if logged_in_user.admin? || logged_in_user_membership - render_403 - false + return true if @project.is_public? || User.current.member_of?(@project) || User.current.admin? + User.current.logged? ? render_403 : require_login end # store current uri in session. @@ -154,6 +133,21 @@ class ApplicationController < ActionController::Base render :template => "common/404", :layout => true, :status => 404 return false end + + def render_feed(items, options={}) + @items = items.sort {|x,y| y.event_datetime <=> x.event_datetime } + @title = options[:title] || Setting.app_title + render :template => "common/feed.atom.rxml", :layout => false, :content_type => 'application/atom+xml' + end + + def self.accept_key_auth(*actions) + actions = actions.flatten.map(&:to_s) + write_inheritable_attribute('accept_key_auth_actions', actions) + end + + def accept_key_auth_actions + self.class.read_inheritable_attribute('accept_key_auth_actions') || [] + end # qvalues http header parser # code taken from webrick @@ -173,4 +167,4 @@ class ApplicationController < ActionController::Base end return tmp end -end \ No newline at end of file +end diff --git a/app/controllers/boards_controller.rb b/app/controllers/boards_controller.rb index 0ad2645f89514d0be3a9e506370aff4e109bea5a..2a90e9857dc0f86d67c93aef3a2260aff4c1338a 100644 --- a/app/controllers/boards_controller.rb +++ b/app/controllers/boards_controller.rb @@ -17,9 +17,7 @@ class BoardsController < ApplicationController layout 'base' - before_filter :find_project - before_filter :authorize, :except => [:index, :show] - before_filter :check_project_privacy, :only => [:index, :show] + before_filter :find_project, :authorize helper :messages include MessagesHelper diff --git a/app/controllers/documents_controller.rb b/app/controllers/documents_controller.rb index 3c7e56b439949e823fded349667f8270c880e568..5659e9cedbadea1f81aab7507b5088c15876227a 100644 --- a/app/controllers/documents_controller.rb +++ b/app/controllers/documents_controller.rb @@ -52,7 +52,7 @@ class DocumentsController < ApplicationController a = Attachment.create(:container => @document, :file => file, :author => logged_in_user) @attachments << a unless a.new_record? } if params[:attachments] and params[:attachments].is_a? Array - Mailer.deliver_attachments_add(@attachments) if !@attachments.empty? and Permission.find_by_controller_and_action(params[:controller], params[:action]).mail_enabled? + Mailer.deliver_attachments_add(@attachments) if !@attachments.empty? #and Permission.find_by_controller_and_action(params[:controller], params[:action]).mail_enabled? redirect_to :action => 'show', :id => @document end diff --git a/app/controllers/issues_controller.rb b/app/controllers/issues_controller.rb index 31cc6ae7d77e7205e59b555ffcd84ec67153ea50..56a9b11ca07fea768a3c981192f7f6a2f55a233a 100644 --- a/app/controllers/issues_controller.rb +++ b/app/controllers/issues_controller.rb @@ -72,8 +72,15 @@ class IssuesController < ApplicationController unless params[:notes].empty? journal = @issue.init_journal(self.logged_in_user, params[:notes]) if @issue.save + params[:attachments].each { |file| + next unless file.size > 0 + a = Attachment.create(:container => @issue, :file => file, :author => logged_in_user) + journal.details << JournalDetail.new(:property => 'attachment', + :prop_key => a.id, + :value => a.filename) unless a.new_record? + } if params[:attachments] and params[:attachments].is_a? Array flash[:notice] = l(:notice_successful_update) - Mailer.deliver_issue_edit(journal) if Permission.find_by_controller_and_action(params[:controller], params[:action]).mail_enabled? + Mailer.deliver_issue_edit(journal) #if Permission.find_by_controller_and_action(params[:controller], params[:action]).mail_enabled? redirect_to :action => 'show', :id => @issue return end @@ -100,14 +107,14 @@ class IssuesController < ApplicationController } if params[:attachments] and params[:attachments].is_a? Array # Log time - if logged_in_user.authorized_to(@project, "timelog/edit") + 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.attributes = params[:time_entry] @time_entry.save end flash[:notice] = l(:notice_successful_update) - Mailer.deliver_issue_edit(journal) if Permission.find_by_controller_and_action(params[:controller], params[:action]).mail_enabled? + Mailer.deliver_issue_edit(journal) #if Permission.find_by_controller_and_action(params[:controller], params[:action]).mail_enabled? redirect_to :action => 'show', :id => @issue end rescue ActiveRecord::StaleObjectError @@ -124,23 +131,6 @@ class IssuesController < ApplicationController redirect_to :controller => 'projects', :action => 'list_issues', :id => @project end - def add_attachment - # Save the attachments - @attachments = [] - journal = @issue.init_journal(self.logged_in_user) - params[:attachments].each { |file| - next unless file.size > 0 - a = Attachment.create(:container => @issue, :file => file, :author => logged_in_user) - @attachments << a unless a.new_record? - journal.details << JournalDetail.new(:property => 'attachment', - :prop_key => a.id, - :value => a.filename) unless a.new_record? - } if params[:attachments] and params[:attachments].is_a? Array - journal.save if journal.details.any? - Mailer.deliver_attachments_add(@attachments) if !@attachments.empty? and Permission.find_by_controller_and_action(params[:controller], params[:action]).mail_enabled? - redirect_to :action => 'show', :id => @issue - end - def destroy_attachment a = @issue.attachments.find(params[:attachment_id]) a.destroy diff --git a/app/controllers/messages_controller.rb b/app/controllers/messages_controller.rb index 1b0d2a680c4650cab05c22cff9691fbee7edde88..74a957d6c71a53ace81c0d24caed6c4821f2f57c 100644 --- a/app/controllers/messages_controller.rb +++ b/app/controllers/messages_controller.rb @@ -17,8 +17,7 @@ class MessagesController < ApplicationController layout 'base' - before_filter :find_project, :check_project_privacy - before_filter :require_login, :only => [:new, :reply] + before_filter :find_project, :authorize verify :method => :post, :only => [ :reply, :destroy ], :redirect_to => { :action => :show } diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index 0613f9e40ec4756e350487a372bcb2e4229abfd6..2f5e24e283b6ae62a4bfe29d688fde02270a6f6c 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -22,6 +22,7 @@ class ProjectsController < ApplicationController before_filter :find_project, :except => [ :index, :list, :add ] before_filter :authorize, :except => [ :index, :list, :add, :archive, :unarchive, :destroy ] before_filter :require_admin, :only => [ :add, :archive, :unarchive, :destroy ] + accept_key_auth :activity, :calendar cache_sweeper :project_sweeper, :only => [ :add, :edit, :archive, :unarchive, :destroy ] cache_sweeper :issue_sweeper, :only => [ :add_issue ] @@ -97,8 +98,7 @@ class ProjectsController < ApplicationController @trackers = Tracker.find(:all, :order => 'position') @open_issues_by_tracker = Issue.count(:group => :tracker, :joins => "INNER JOIN #{IssueStatus.table_name} ON #{IssueStatus.table_name}.id = #{Issue.table_name}.status_id", :conditions => ["project_id=? and #{IssueStatus.table_name}.is_closed=?", @project.id, false]) @total_issues_by_tracker = Issue.count(:group => :tracker, :conditions => ["project_id=?", @project.id]) - - @key = logged_in_user.get_or_create_rss_key.value if logged_in_user + @key = User.current.rss_key end def settings @@ -224,7 +224,7 @@ class ProjectsController < ApplicationController Attachment.create(:container => @document, :file => a, :author => logged_in_user) unless a.size == 0 } if params[:attachments] and params[:attachments].is_a? Array flash[:notice] = l(:notice_successful_create) - Mailer.deliver_document_add(@document) if Permission.find_by_controller_and_action(params[:controller], params[:action]).mail_enabled? + Mailer.deliver_document_add(@document) #if Permission.find_by_controller_and_action(params[:controller], params[:action]).mail_enabled? redirect_to :action => 'list_documents', :id => @project end end @@ -268,7 +268,7 @@ class ProjectsController < ApplicationController if @issue.save @attachments.each(&:save) flash[:notice] = l(:notice_successful_create) - Mailer.deliver_issue_add(@issue) if Permission.find_by_controller_and_action(params[:controller], params[:action]).mail_enabled? + Mailer.deliver_issue_add(@issue) #if Permission.find_by_controller_and_action(params[:controller], params[:action]).mail_enabled? redirect_to :action => 'list_issues', :id => @project end end @@ -383,7 +383,7 @@ class ProjectsController < ApplicationController redirect_to :action => 'list_issues', :id => @project and return unless @issues @projects = [] # find projects to which the user is allowed to move the issue - @logged_in_user.memberships.each {|m| @projects << m.project if Permission.allowed_to_role("projects/move_issues", m.role)} + User.current.memberships.each {|m| @projects << m.project if m.role.allowed_to?(:controller => 'projects', :action => 'move_issues')} # issue can be moved to any tracker @trackers = Tracker.find(:all) if request.post? and params[:new_project_id] and params[:new_tracker_id] @@ -424,7 +424,11 @@ class ProjectsController < ApplicationController # Show news list of @project def list_news @news_pages, @news = paginate :news, :per_page => 10, :conditions => ["project_id=?", @project.id], :include => :author, :order => "#{News.table_name}.created_on DESC" - render :action => "list_news", :layout => false if request.xhr? + + respond_to do |format| + format.html { render :layout => false if request.xhr? } + format.atom { render_feed(@news, :title => "#{@project.name}: #{l(:label_news_plural)}") } + end end def add_file @@ -437,7 +441,7 @@ class ProjectsController < ApplicationController a = Attachment.create(:container => @version, :file => file, :author => logged_in_user) @attachments << a unless a.new_record? } if params[:attachments] and params[:attachments].is_a? Array - Mailer.deliver_attachments_add(@attachments) if !@attachments.empty? and Permission.find_by_controller_and_action(params[:controller], params[:action]).mail_enabled? + Mailer.deliver_attachments_add(@attachments) if !@attachments.empty? #and Permission.find_by_controller_and_action(params[:controller], params[:action]).mail_enabled? redirect_to :controller => 'projects', :action => 'list_files', :id => @project end @versions = @project.versions.sort @@ -471,80 +475,67 @@ class ProjectsController < ApplicationController @year ||= Date.today.year @month ||= Date.today.month - @date_from = Date.civil(@year, @month, 1) - @date_to = @date_from >> 1 + case params[:format] + when 'rss' + # 30 last days + @date_from = Date.today - 30 + @date_to = Date.today + 1 + else + # current month + @date_from = Date.civil(@year, @month, 1) + @date_to = @date_from >> 1 + end - @events_by_day = Hash.new { |h,k| h[k] = [] } + @event_types = %w(issues news attachments documents wiki_edits revisions) + @event_types.delete('wiki_edits') unless @project.wiki + @event_types.delete('changesets') unless @project.repository - unless params[:show_issues] == "0" - @project.issues.find(:all, :include => [:author], :conditions => ["#{Issue.table_name}.created_on BETWEEN ? AND ?", @date_from, @date_to] ).each { |i| - @events_by_day[i.created_on.to_date] << i - } - @project.issue_changes.find(:all, :include => :details, :conditions => ["(#{Journal.table_name}.created_on BETWEEN ? AND ?) AND (#{JournalDetail.table_name}.prop_key = 'status_id')", @date_from, @date_to] ).each { |i| - @events_by_day[i.created_on.to_date] << i - } - @show_issues = 1 + @scope = @event_types.select {|t| params["show_#{t}"]} + # default events if none is specified in parameters + @scope = (@event_types - %w(wiki_edits))if @scope.empty? + + @events = [] + + if @scope.include?('issues') + @events += @project.issues.find(:all, :include => [:author, :tracker], :conditions => ["#{Issue.table_name}.created_on>=? and #{Issue.table_name}.created_on<=?", @date_from, @date_to] ) end - unless params[:show_news] == "0" - @project.news.find(:all, :conditions => ["#{News.table_name}.created_on BETWEEN ? AND ?", @date_from, @date_to], :include => :author ).each { |i| - @events_by_day[i.created_on.to_date] << i - } - @show_news = 1 + if @scope.include?('news') + @events += @project.news.find(:all, :conditions => ["#{News.table_name}.created_on>=? and #{News.table_name}.created_on<=?", @date_from, @date_to], :include => :author ) end - unless params[:show_files] == "0" - Attachment.find(:all, :select => "#{Attachment.table_name}.*", - :joins => "LEFT JOIN #{Version.table_name} ON #{Version.table_name}.id = #{Attachment.table_name}.container_id", - :conditions => ["#{Attachment.table_name}.container_type='Version' and #{Version.table_name}.project_id=? and #{Attachment.table_name}.created_on BETWEEN ? AND ? ", @project.id, @date_from, @date_to], - :include => :author ).each { |i| - @events_by_day[i.created_on.to_date] << i - } - @show_files = 1 + if @scope.include?('attachments') + @events += Attachment.find(:all, :select => "#{Attachment.table_name}.*", :joins => "LEFT JOIN #{Version.table_name} ON #{Version.table_name}.id = #{Attachment.table_name}.container_id", :conditions => ["#{Attachment.table_name}.container_type='Version' and #{Version.table_name}.project_id=? and #{Attachment.table_name}.created_on>=? and #{Attachment.table_name}.created_on<=?", @project.id, @date_from, @date_to], :include => :author ) end - unless params[:show_documents] == "0" - @project.documents.find(:all, :conditions => ["#{Document.table_name}.created_on BETWEEN ? AND ?", @date_from, @date_to] ).each { |i| - @events_by_day[i.created_on.to_date] << i - } - Attachment.find(:all, :select => "attachments.*", - :joins => "LEFT JOIN #{Document.table_name} ON #{Document.table_name}.id = #{Attachment.table_name}.container_id", - :conditions => ["#{Attachment.table_name}.container_type='Document' and #{Document.table_name}.project_id=? and #{Attachment.table_name}.created_on BETWEEN ? AND ? ", @project.id, @date_from, @date_to], - :include => :author ).each { |i| - @events_by_day[i.created_on.to_date] << i - } - @show_documents = 1 + if @scope.include?('documents') + @events += @project.documents.find(:all, :conditions => ["#{Document.table_name}.created_on>=? and #{Document.table_name}.created_on<=?", @date_from, @date_to] ) + @events += Attachment.find(:all, :select => "attachments.*", :joins => "LEFT JOIN #{Document.table_name} ON #{Document.table_name}.id = #{Attachment.table_name}.container_id", :conditions => ["#{Attachment.table_name}.container_type='Document' and #{Document.table_name}.project_id=? and #{Attachment.table_name}.created_on>=? and #{Attachment.table_name}.created_on<=?", @project.id, @date_from, @date_to], :include => :author ) end - unless @project.wiki.nil? || params[:show_wiki_edits] == "0" + if @scope.include?('wiki_edits') && @project.wiki select = "#{WikiContent.versioned_table_name}.updated_on, #{WikiContent.versioned_table_name}.comments, " + - "#{WikiContent.versioned_table_name}.#{WikiContent.version_column}, #{WikiPage.table_name}.title" + "#{WikiContent.versioned_table_name}.#{WikiContent.version_column}, #{WikiPage.table_name}.title, " + + "#{WikiContent.versioned_table_name}.page_id, #{WikiContent.versioned_table_name}.author_id, " + + "#{WikiContent.versioned_table_name}.id" joins = "LEFT JOIN #{WikiPage.table_name} ON #{WikiPage.table_name}.id = #{WikiContent.versioned_table_name}.page_id " + "LEFT JOIN #{Wiki.table_name} ON #{Wiki.table_name}.id = #{WikiPage.table_name}.wiki_id " conditions = ["#{Wiki.table_name}.project_id = ? AND #{WikiContent.versioned_table_name}.updated_on BETWEEN ? AND ?", @project.id, @date_from, @date_to] - WikiContent.versioned_class.find(:all, :select => select, :joins => joins, :conditions => conditions).each { |i| - # We provide this alias so all events can be treated in the same manner - def i.created_on - self.updated_on - end - @events_by_day[i.created_on.to_date] << i - } - @show_wiki_edits = 1 + @events += WikiContent.versioned_class.find(:all, :select => select, :joins => joins, :conditions => conditions) end - unless @project.repository.nil? || params[:show_changesets] == "0" - @project.repository.changesets.find(:all, :conditions => ["#{Changeset.table_name}.committed_on BETWEEN ? AND ?", @date_from, @date_to]).each { |i| - def i.created_on - self.committed_on - end - @events_by_day[i.created_on.to_date] << i - } - @show_changesets = 1 + if @scope.include?('revisions') && @project.repository + @events += @project.repository.changesets.find(:all, :conditions => ["#{Changeset.table_name}.committed_on BETWEEN ? AND ?", @date_from, @date_to]) end - render :layout => false if request.xhr? + @events_by_day = @events.group_by(&:event_date) + + respond_to do |format| + format.html { render :layout => false if request.xhr? } + format.atom { render_feed(@events, :title => "#{@project.name}: #{l(:label_activity)}") } + end end def calendar @@ -630,7 +621,7 @@ class ProjectsController < ApplicationController def feeds @queries = @project.queries.find :all, :conditions => ["is_public=? or user_id=?", true, (logged_in_user ? logged_in_user.id : 0)] - @key = logged_in_user.get_or_create_rss_key.value if logged_in_user + @key = User.current.rss_key end private diff --git a/app/controllers/queries_controller.rb b/app/controllers/queries_controller.rb index 6318952842e056859d92ab01a2fec18d74d3f8ab..bcc23369923a9590abbe4b28f4b5b009dc236467 100644 --- a/app/controllers/queries_controller.rb +++ b/app/controllers/queries_controller.rb @@ -16,9 +16,8 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. class QueriesController < ApplicationController - layout 'base' - before_filter :require_login, :except => :index - before_filter :find_project, :check_project_privacy + layout 'base' + before_filter :find_project, :authorize def index @queries = @project.queries.find(:all, @@ -31,7 +30,7 @@ class QueriesController < ApplicationController @query.project = @project @query.user = logged_in_user @query.executed_by = logged_in_user - @query.is_public = false unless logged_in_user.authorized_to(@project, 'projects/add_query') + @query.is_public = false unless current_role.allowed_to?(:manage_pulic_queries) params[:fields].each do |field| @query.add_filter(field, params[:operators][field], params[:values][field]) @@ -52,7 +51,7 @@ class QueriesController < ApplicationController @query.add_filter(field, params[:operators][field], params[:values][field]) end if params[:fields] @query.attributes = params[:query] - @query.is_public = false unless logged_in_user.authorized_to(@project, 'projects/add_query') + @query.is_public = false unless current_role.allowed_to?(:manage_pulic_queries) if @query.save flash[:notice] = l(:notice_successful_update) diff --git a/app/controllers/repositories_controller.rb b/app/controllers/repositories_controller.rb index 5bcba8e3aed74e3a4759ee512dba8baef3bedd62..f99ea0b3589f78ceab99d8378d82bd47302c5392 100644 --- a/app/controllers/repositories_controller.rb +++ b/app/controllers/repositories_controller.rb @@ -22,8 +22,8 @@ require 'digest/sha1' class RepositoriesController < ApplicationController layout 'base' before_filter :find_project, :except => [:update_form] - before_filter :authorize, :except => [:update_form, :stats, :graph] - before_filter :check_project_privacy, :only => [:stats, :graph] + before_filter :authorize, :except => [:update_form] + accept_key_auth :revisions def show # check if new revisions have been committed in the repository @@ -57,7 +57,10 @@ class RepositoriesController < ApplicationController :limit => @changeset_pages.items_per_page, :offset => @changeset_pages.current.offset) - render :action => "revisions", :layout => false if request.xhr? + respond_to do |format| + format.html { render :layout => false if request.xhr? } + format.atom { render_feed(@changesets, :title => "#{@project.name}: #{l(:label_revision_plural)}") } + end end def entry diff --git a/app/controllers/roles_controller.rb b/app/controllers/roles_controller.rb index 6f1657675b04c87dfb1a4ea1fb1314e522f1f698..24c7a3ffea8cfb09e3c52c26647766f50ce3e24f 100644 --- a/app/controllers/roles_controller.rb +++ b/app/controllers/roles_controller.rb @@ -28,40 +28,35 @@ class RolesController < ApplicationController end def list - @role_pages, @roles = paginate :roles, :per_page => 25, :order => "position" + @role_pages, @roles = paginate :roles, :per_page => 25, :order => 'builtin, position' render :action => "list", :layout => false if request.xhr? end def new @role = Role.new(params[:role]) - if request.post? - @role.permissions = Permission.find(params[:permission_ids]) if params[:permission_ids] - if @role.save - flash[:notice] = l(:notice_successful_create) - redirect_to :action => 'list' - end + if request.post? && @role.save + flash[:notice] = l(:notice_successful_create) + redirect_to :action => 'list' end - @permissions = Permission.find(:all, :conditions => ["is_public=?", false], :order => 'sort ASC') + @permissions = @role.setable_permissions end def edit @role = Role.find(params[:id]) if request.post? and @role.update_attributes(params[:role]) - @role.permissions = Permission.find(params[:permission_ids] || []) - Permission.allowed_to_role_expired flash[:notice] = l(:notice_successful_update) redirect_to :action => 'list' end - @permissions = Permission.find(:all, :conditions => ["is_public=?", false], :order => 'sort ASC') + @permissions = @role.setable_permissions end def destroy @role = Role.find(params[:id]) - unless @role.members.empty? - flash[:error] = 'Some members have this role. Can\'t delete it.' - else + #unless @role.members.empty? + # flash[:error] = 'Some members have this role. Can\'t delete it.' + #else @role.destroy - end + #end redirect_to :action => 'list' end @@ -95,19 +90,19 @@ class RolesController < ApplicationController flash[:notice] = l(:notice_successful_update) end end - @roles = Role.find(:all, :order => 'position') + @roles = Role.find(:all, :order => 'builtin, position') @trackers = Tracker.find(:all, :order => 'position') @statuses = IssueStatus.find(:all, :include => :workflows, :order => 'position') end def report - @roles = Role.find(:all, :order => 'position') - @permissions = Permission.find :all, :conditions => ["is_public=?", false], :order => 'sort' + @roles = Role.find(:all, :order => 'builtin, position') + @permissions = Redmine::AccessControl.permissions.select { |p| !p.public? } if request.post? @roles.each do |role| - role.permissions = Permission.find(params[:permission_ids] ? (params[:permission_ids][role.id.to_s] || []) : [] ) + role.permissions = params[:permissions][role.id.to_s] + role.save end - Permission.allowed_to_role_expired flash[:notice] = l(:notice_successful_update) redirect_to :action => 'list' end diff --git a/app/controllers/timelog_controller.rb b/app/controllers/timelog_controller.rb index 01c4ddca9b73b94d6e6e8011d6ce5c4b83e3a77a..1c15fa56416f66349713e38b84a3f6f6e5a79a09 100644 --- a/app/controllers/timelog_controller.rb +++ b/app/controllers/timelog_controller.rb @@ -16,11 +16,8 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. class TimelogController < ApplicationController - layout 'base' - - before_filter :find_project - before_filter :authorize, :only => :edit - before_filter :check_project_privacy, :except => :edit + layout 'base' + before_filter :find_project, :authorize helper :sort include SortHelper diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 3e107287b93497345e400135b59c820e05ffae2d..7e3abc75cea4f6406386d241ec6754a15404d448 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -87,7 +87,7 @@ class UsersController < ApplicationController end end @auth_sources = AuthSource.find(:all) - @roles = Role.find(:all, :order => 'position') + @roles = Role.find_all_givable @projects = Project.find(:all, :order => 'name', :conditions => "status=#{Project::STATUS_ACTIVE}") - @user.projects @membership ||= Member.new end diff --git a/app/controllers/watchers_controller.rb b/app/controllers/watchers_controller.rb index f617a5b5add1e1088a4f8919e532643bdd8c85c6..206dc08430fa0088dd09677d59d1234aa4a66b8f 100644 --- a/app/controllers/watchers_controller.rb +++ b/app/controllers/watchers_controller.rb @@ -20,7 +20,7 @@ class WatchersController < ApplicationController before_filter :require_login, :find_project, :check_project_privacy def add - user = logged_in_user + user = User.current @watched.add_watcher(user) respond_to do |format| format.html { render :text => 'Watcher added.', :layout => true } @@ -29,7 +29,7 @@ class WatchersController < ApplicationController end def remove - user = logged_in_user + user = User.current @watched.remove_watcher(user) respond_to do |format| format.html { render :text => 'Watcher removed.', :layout => true } diff --git a/app/controllers/welcome_controller.rb b/app/controllers/welcome_controller.rb index 7b1c398d1c55443cabde6fb9149e5307c4be0aff..2eac2268fc4b96c99de6e4e9c75d74c4c9e8f709 100644 --- a/app/controllers/welcome_controller.rb +++ b/app/controllers/welcome_controller.rb @@ -21,7 +21,5 @@ class WelcomeController < ApplicationController def index @news = News.latest logged_in_user @projects = Project.latest logged_in_user - - @key = logged_in_user.get_or_create_rss_key.value if logged_in_user end end diff --git a/app/controllers/wiki_controller.rb b/app/controllers/wiki_controller.rb index 748821d723c9f9f05063ab58b11730591ddb7d31..e9212a1c763c2806f45f52e1f2c55800062e0c95 100644 --- a/app/controllers/wiki_controller.rb +++ b/app/controllers/wiki_controller.rb @@ -19,8 +19,7 @@ require 'diff' class WikiController < ApplicationController layout 'base' - before_filter :find_wiki, :check_project_privacy - before_filter :authorize, :only => [:destroy, :add_attachment, :destroy_attachment] + before_filter :find_wiki, :authorize verify :method => :post, :only => [:destroy, :destroy_attachment], :redirect_to => { :action => :index } diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 41becd0f28307ffc5a36dcba3d986f10357634b4..550ce3c59898476e9dde48cb51cd48efacf20d99 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -25,32 +25,18 @@ end module ApplicationHelper - # Return current logged in user or nil - def loggedin? - @logged_in_user + def current_role + @current_role ||= User.current.role_for_project(@project) end - # Return true if user is logged in and is admin, otherwise false - def admin_loggedin? - @logged_in_user and @logged_in_user.admin? - end - # Return true if user is authorized for controller/action, otherwise false - def authorize_for(controller, action) - # check if action is allowed on public projects - if @project.is_public? and Permission.allowed_to_public "%s/%s" % [ controller, action ] - return true - end - # check if user is authorized - if @logged_in_user and (@logged_in_user.admin? or Permission.allowed_to_role( "%s/%s" % [ controller, action ], @logged_in_user.role_for_project(@project) ) ) - return true - end - return false + def authorize_for(controller, action) + User.current.allowed_to?({:controller => controller, :action => action}, @project) end # Display a link if user is authorized def link_to_if_authorized(name, options = {}, html_options = nil, *parameters_for_method_reference) - link_to(name, options, html_options, *parameters_for_method_reference) if authorize_for(options[:controller], options[:action]) + link_to(name, options, html_options, *parameters_for_method_reference) if authorize_for(options[:controller] || params[:controller], options[:action]) end # Display a link to user's account page diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index abf2bcf86eca4078eb81c5ce87dff87095d354dd..da674985b7b6ca8d2bca2b436476ccca794fbe02 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -175,4 +175,12 @@ module ProjectsHelper gc.draw(imgl) imgl end if Object.const_defined?(:Magick) + + def new_issue_selector + trackers = Tracker.find(:all, :order => 'position') + form_tag({:controller => 'projects', :action => 'add_issue', :id => @project}, :method => :get) + + select_tag('tracker_id', '<option></option' + options_from_collection_for_select(trackers, 'id', 'name'), + :onchange => "if (this.value != '') {this.form.submit()}") + + end_form_tag + end end diff --git a/app/helpers/watchers_helper.rb b/app/helpers/watchers_helper.rb index 87b3810554e22e64c6022de8add70a1560b3f7c4..c83c785fc701d6adc57cb7ad1d8fff5dfd43fefd 100644 --- a/app/helpers/watchers_helper.rb +++ b/app/helpers/watchers_helper.rb @@ -21,7 +21,7 @@ module WatchersHelper end def watcher_link(object, user) - return '' unless user && object.respond_to?('watched_by?') + return '' unless user && user.logged? && object.respond_to?('watched_by?') watched = object.watched_by?(user) url = {:controller => 'watchers', :action => (watched ? 'remove' : 'add'), diff --git a/app/models/attachment.rb b/app/models/attachment.rb index 443a75babbc0e5028a071636cd6977cabe09ced4..f57038b96abe97332dccbf6b9c9f9a33a92de758 100644 --- a/app/models/attachment.rb +++ b/app/models/attachment.rb @@ -24,7 +24,11 @@ class Attachment < ActiveRecord::Base validates_presence_of :container, :filename validates_length_of :filename, :maximum => 255 validates_length_of :disk_filename, :maximum => 255 - + + acts_as_event :title => :filename, + :description => :filename, + :url => Proc.new {|o| {:controller => 'attachment', :action => 'download', :id => o.id}} + cattr_accessor :storage_path @@storage_path = "#{RAILS_ROOT}/files" diff --git a/app/models/changeset.rb b/app/models/changeset.rb index 57e2d74a49fb93cb10ba64fab7bc3b1b64752d4a..9400df869cf167e412e472085637a980db557c14 100644 --- a/app/models/changeset.rb +++ b/app/models/changeset.rb @@ -19,6 +19,12 @@ class Changeset < ActiveRecord::Base belongs_to :repository has_many :changes, :dependent => :delete_all has_and_belongs_to_many :issues + + acts_as_event :title => Proc.new {|o| "#{l(:label_revision)} #{o.revision}" + (o.comments.blank? ? '' : (': ' + o.comments))}, + :description => :comments, + :datetime => :committed_on, + :author => :committer, + :url => Proc.new {|o| {:controller => 'repositories', :action => 'revision', :id => o.repository.project_id, :rev => o.revision}} validates_presence_of :repository_id, :revision, :committed_on, :commit_date validates_numericality_of :revision, :only_integer => true diff --git a/app/models/document.rb b/app/models/document.rb index 8b5d68e87df707b91265b9e634daed03b9bc66b8..6989191ce6a72dbbf2b6b28642af7838b34946a4 100644 --- a/app/models/document.rb +++ b/app/models/document.rb @@ -20,6 +20,8 @@ class Document < ActiveRecord::Base belongs_to :category, :class_name => "Enumeration", :foreign_key => "category_id" has_many :attachments, :as => :container, :dependent => :destroy + acts_as_event :url => Proc.new {|o| {:controller => 'documents', :action => 'show', :id => o.id}} + validates_presence_of :project, :title, :category validates_length_of :title, :maximum => 60 end diff --git a/app/models/issue.rb b/app/models/issue.rb index 65b34cb92a3b9a24bb127f2df91ae03adc408683..b6eda1767459c9e7e753d288fb8c1207badbd4da 100644 --- a/app/models/issue.rb +++ b/app/models/issue.rb @@ -36,6 +36,8 @@ class Issue < ActiveRecord::Base has_many :relations_to, :class_name => 'IssueRelation', :foreign_key => 'issue_to_id', :dependent => :delete_all acts_as_watchable + acts_as_event :title => Proc.new {|o| "#{o.tracker.name} ##{o.id}: #{o.subject}"}, + :url => Proc.new {|o| {:controller => 'issues', :action => 'show', :id => o.id}} validates_presence_of :subject, :description, :priority, :tracker, :author, :status validates_length_of :subject, :maximum => 255 diff --git a/app/models/mail_handler.rb b/app/models/mail_handler.rb index 39b088bf4dbc9b127e0d8eee72039b136d532be9..7a1d7324472fb7d648306a990927f41cc073cccc 100644 --- a/app/models/mail_handler.rb +++ b/app/models/mail_handler.rb @@ -31,7 +31,7 @@ class MailHandler < ActionMailer::Base user = User.find_active(:first, :conditions => {:mail => email.from.first}) return unless user # check permission - return unless Permission.allowed_to_role("issues/add_note", user.role_for_project(issue.project)) + return unless user.allowed_to?(:add_issue_notes, issue.project) # add the note issue.init_journal(user, email.body.chomp) diff --git a/app/models/member.rb b/app/models/member.rb index 2aa26d42f3a61eed7c2f855f283bf70f4a601f7c..39703147d2bf8f53434fafc6c26339e555bff661 100644 --- a/app/models/member.rb +++ b/app/models/member.rb @@ -23,6 +23,10 @@ class Member < ActiveRecord::Base validates_presence_of :role, :user, :project validates_uniqueness_of :user_id, :scope => :project_id + def validate + errors.add :role_id, :activerecord_error_invalid if role && !role.member? + end + def name self.user.name end diff --git a/app/models/news.rb b/app/models/news.rb index e9a48846a6631541774c534d2e71defadb6d9ca4..4352363d9e5a8f4826e04ef693aeb86ee897e2d3 100644 --- a/app/models/news.rb +++ b/app/models/news.rb @@ -23,7 +23,9 @@ class News < ActiveRecord::Base validates_presence_of :title, :description validates_length_of :title, :maximum => 60 validates_length_of :summary, :maximum => 255 - + + acts_as_event :url => Proc.new {|o| {:controller => 'news', :action => 'show', :id => o.id}} + # returns latest news for projects visible by user def self.latest(user=nil, count=5) find(:all, :limit => count, :conditions => Project.visible_by(user), :include => [ :author, :project ], :order => "#{News.table_name}.created_on DESC") diff --git a/app/models/permission.rb b/app/models/permission.rb deleted file mode 100644 index bea670c4ce6fdb35ff63009cee2915e29c3e2356..0000000000000000000000000000000000000000 --- a/app/models/permission.rb +++ /dev/null @@ -1,68 +0,0 @@ -# redMine - project management software -# Copyright (C) 2006 Jean-Philippe Lang -# -# 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. - -class Permission < ActiveRecord::Base - has_and_belongs_to_many :roles - - validates_presence_of :controller, :action, :description - - GROUPS = { - 100 => :label_project, - 200 => :label_member_plural, - 300 => :label_version_plural, - 400 => :label_issue_category_plural, - 600 => :label_query_plural, - 1000 => :label_issue_plural, - 1100 => :label_news_plural, - 1200 => :label_document_plural, - 1300 => :label_attachment_plural, - 1400 => :label_repository, - 1500 => :label_time_tracking, - 1700 => :label_wiki_page_plural, - 2000 => :label_board_plural - }.freeze - - @@cached_perms_for_public = nil - @@cached_perms_for_roles = nil - - def name - self.controller + "/" + self.action - end - - def group_id - (self.sort / 100)*100 - end - - def self.allowed_to_public(action) - @@cached_perms_for_public ||= find(:all, :conditions => ["is_public=?", true]).collect {|p| "#{p.controller}/#{p.action}"} - @@cached_perms_for_public.include? action - end - - def self.allowed_to_role(action, role) - @@cached_perms_for_roles ||= - begin - perms = {} - find(:all, :include => :roles).each {|p| perms.store "#{p.controller}/#{p.action}", p.roles.collect {|r| r.id } } - perms - end - allowed_to_public(action) or (role && @@cached_perms_for_roles[action] && @@cached_perms_for_roles[action].include?(role.id)) - end - - def self.allowed_to_role_expired - @@cached_perms_for_roles = nil - end -end diff --git a/app/models/query.rb b/app/models/query.rb index 28f65ddf6430ad688dc2116ebafb98656c0d3ff5..ff519d71cfda39bc3c7afa94b3c10e884b14a100 100644 --- a/app/models/query.rb +++ b/app/models/query.rb @@ -78,7 +78,7 @@ class Query < ActiveRecord::Base def editable_by?(user) return false unless user return true if !is_public && self.user_id == user.id - is_public && user.authorized_to(project, "projects/add_query") + is_public && user.allowed_to?(:manage_pulic_queries, project) end def available_filters diff --git a/app/models/role.rb b/app/models/role.rb index 98d735e8e0aac613f6c681012b62550539890cb3..015146dc4b95672c6c4cf9237abe43e3c696e6d8 100644 --- a/app/models/role.rb +++ b/app/models/role.rb @@ -16,23 +16,93 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. class Role < ActiveRecord::Base - before_destroy :check_integrity - has_and_belongs_to_many :permissions + # Built-in roles + BUILTIN_NON_MEMBER = 1 + BUILTIN_ANONYMOUS = 2 + + before_destroy :check_deletable has_many :workflows, :dependent => :delete_all has_many :members acts_as_list + + serialize :permissions + attr_protected :builtin validates_presence_of :name validates_uniqueness_of :name validates_length_of :name, :maximum => 30 validates_format_of :name, :with => /^[\w\s\'\-]*$/i + def permissions + read_attribute(:permissions) || [] + end + + def permissions=(perms) + perms = perms.collect {|p| p.to_sym unless p.blank? }.compact if perms + write_attribute(:permissions, perms) + end + def <=>(role) position <=> role.position end + # Return true if the role is a builtin role + def builtin? + self.builtin != 0 + end + + # Return true if the role is a project member role + def member? + !self.builtin? + end + + # Return true if role is allowed to do the specified action + # action can be: + # * a parameter-like Hash (eg. :controller => 'projects', :action => 'edit') + # * a permission Symbol (eg. :edit_project) + def allowed_to?(action) + if action.is_a? Hash + allowed_actions.include? "#{action[:controller]}/#{action[:action]}" + else + allowed_permissions.include? action + end + end + + # Return all the permissions that can be given to the role + def setable_permissions + setable_permissions = Redmine::AccessControl.permissions - Redmine::AccessControl.public_permissions + setable_permissions -= Redmine::AccessControl.members_only_permissions if self.builtin == BUILTIN_NON_MEMBER + setable_permissions -= Redmine::AccessControl.loggedin_only_permissions if self.builtin == BUILTIN_ANONYMOUS + setable_permissions + end + + # Find all the roles that can be given to a project member + def self.find_all_givable + find(:all, :conditions => {:builtin => 0}, :order => 'position') + end + + # Return the builtin 'non member' role + def self.non_member + find(:first, :conditions => {:builtin => BUILTIN_NON_MEMBER}) || raise('Missing non-member builtin role.') + end + + # Return the builtin 'anonymous' role + def self.anonymous + find(:first, :conditions => {:builtin => BUILTIN_ANONYMOUS}) || raise('Missing anonymous builtin role.') + end + + private - def check_integrity - raise "Can't delete role" if Member.find(:first, :conditions =>["role_id=?", self.id]) + def allowed_permissions + @allowed_permissions ||= permissions + Redmine::AccessControl.public_permissions.collect {|p| p.name} + end + + def allowed_actions + @actions_allowed ||= allowed_permissions.inject([]) { |actions, permission| actions += Redmine::AccessControl.allowed_actions(permission) }.flatten + end + + def check_deletable + raise "Can't delete role" if members.any? + raise "Can't delete builtin role" if builtin? end end diff --git a/app/models/user.rb b/app/models/user.rb index a017b42898127047a7fe6339e9acd02ed9000cf0..4cb8da1f928c5777a881b35e3f2b4908015f30a5 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -28,7 +28,7 @@ class User < ActiveRecord::Base has_many :custom_values, :dependent => :delete_all, :as => :customized has_many :issue_categories, :foreign_key => 'assigned_to_id', :dependent => :nullify has_one :preference, :dependent => :destroy, :class_name => 'UserPreference' - has_one :rss_key, :dependent => :destroy, :class_name => 'Token', :conditions => "action='feeds'" + has_one :rss_token, :dependent => :destroy, :class_name => 'Token', :conditions => "action='feeds'" belongs_to :auth_source attr_accessor :password, :password_confirmation @@ -121,24 +121,14 @@ class User < ActiveRecord::Base User.hash_password(clear_password) == self.hashed_password end - def role_for_project(project) - return nil unless project - member = memberships.detect {|m| m.project_id == project.id} - member ? member.role : nil - end - - def authorized_to(project, action) - return true if self.admin? - role = role_for_project(project) - role && Permission.allowed_to_role(action, role) - end - def pref self.preference ||= UserPreference.new(:user => self) end - def get_or_create_rss_key - self.rss_key || Token.create(:user => self, :action => 'feeds') + # Return user's RSS key (a 40 chars long string), used to access feeds + def rss_key + token = self.rss_token || Token.create(:user => self, :action => 'feeds') + token.value end def self.find_by_rss_key(key) @@ -155,9 +145,72 @@ class User < ActiveRecord::Base lastname == user.lastname ? firstname <=> user.firstname : lastname <=> user.lastname end + def to_s + name + end + + def logged? + true + end + + # Return user's role for project + def role_for_project(project) + # No role on archived projects + return nil unless project && project.active? + # Find project membership + membership = memberships.detect {|m| m.project_id == project.id} + if membership + membership.role + elsif logged? + Role.non_member + else + Role.anonymous + end + end + + # Return true if the user is a member of project + def member_of?(project) + role_for_project(project).member? + end + + # Return true if the user is allowed to do the specified action on project + # action can be: + # * a parameter-like Hash (eg. :controller => 'projects', :action => 'edit') + # * a permission Symbol (eg. :edit_project) + def allowed_to?(action, project) + return false unless project.active? + return true if admin? + role = role_for_project(project) + return false unless role + role.allowed_to?(action) && (project.is_public? || role.member?) + end + + def self.current=(user) + @current_user = user + end + + def self.current + @current_user ||= AnonymousUser.new + end + + def self.anonymous + AnonymousUser.new + end + private # Return password digest def self.hash_password(clear_password) Digest::SHA1.hexdigest(clear_password || "") end end + +class AnonymousUser < User + def logged? + false + end + + # Anonymous user has no RSS key + def rss_key + nil + end +end diff --git a/app/models/wiki_content.rb b/app/models/wiki_content.rb index 2d0be8225c644ba0bbf367c0aa42612c1ad7d2d0..4b60a4373405e930799b506585d6caab2f745d67 100644 --- a/app/models/wiki_content.rb +++ b/app/models/wiki_content.rb @@ -28,7 +28,12 @@ class WikiContent < ActiveRecord::Base belongs_to :page, :class_name => 'WikiPage', :foreign_key => 'page_id' belongs_to :author, :class_name => 'User', :foreign_key => 'author_id' attr_protected :data - + + acts_as_event :title => Proc.new {|o| "#{l(:label_wiki_edit)}: #{o.page.title} (##{o.version})"}, + :description => :comments, + :datetime => :updated_on, + :url => Proc.new {|o| {:controller => 'wiki', :id => o.page.wiki.project_id, :page => o.page.title, :version => o.version}} + def text=(plain) case Setting.wiki_compression when 'gzip' diff --git a/app/views/admin/mail_options.rhtml b/app/views/admin/mail_options.rhtml index c7096577661645aa54bde4c609392a0c36b9befb..cab94294fbaf4c21e57ea47a5562f4fc8b2092df 100644 --- a/app/views/admin/mail_options.rhtml +++ b/app/views/admin/mail_options.rhtml @@ -1,26 +1,3 @@ <h2><%=l(:field_mail_notification)%></h2> -<% form_tag({:action => 'mail_options'}, :id => 'mail_options_form') do %> - -<div class="box"> -<p><%=l(:text_select_mail_notifications)%></p> - -<% actions = @actions.group_by {|p| p.group_id } %> -<% actions.keys.sort.each do |group_id| %> -<fieldset style="margin-top: 6px;"><legend><strong><%= l(Permission::GROUPS[group_id]) %></strong></legend> -<% actions[group_id].each do |p| %> - <div style="width:170px;float:left;"><%= check_box_tag "action_ids[]", p.id, p.mail_enabled? %> - <%= l(p.description.to_sym) %> - </div> -<% end %> -<div class="clear"></div> -</fieldset> -<% end %> -<br /> -<%= check_all_links('mail_options_form') %> -</div> - -<p><%= submit_tag l(:button_save) %></p> -<% end %> - <%= link_to l(:label_send_test_email), :action => 'test_email' %> diff --git a/app/views/boards/show.rhtml b/app/views/boards/show.rhtml index cb38cdb53bfe08284e9b6683ad67655e1faf8671..c31ec67e99be1d5069bca7530a12859adfe0d911 100644 --- a/app/views/boards/show.rhtml +++ b/app/views/boards/show.rhtml @@ -1,6 +1,6 @@ <div class="contextual"> -<%= link_to l(:label_message_new), {:controller => 'messages', :action => 'new', :board_id => @board}, :class => "icon icon-add" %> -<%= watcher_tag(@board, @logged_in_user) %> +<%= link_to_if_authorized l(:label_message_new), {:controller => 'messages', :action => 'new', :board_id => @board}, :class => "icon icon-add" %> +<%= watcher_tag(@board, User.current) %> </div> <h2><%=h @board.name %></h2> diff --git a/app/views/common/feed.atom.rxml b/app/views/common/feed.atom.rxml new file mode 100644 index 0000000000000000000000000000000000000000..fa00d754a9b477d88326993f4f9d935813959ed8 --- /dev/null +++ b/app/views/common/feed.atom.rxml @@ -0,0 +1,26 @@ +xml.instruct! +xml.feed "xmlns" => "http://www.w3.org/2005/Atom" do + xml.title @title + xml.link "rel" => "self", "href" => url_for(params.merge({:format => nil, :only_path => false})) + xml.link "rel" => "alternate", "href" => url_for(:controller => 'welcome', :only_path => false) + xml.id url_for(:controller => 'welcome', :only_path => false) + xml.updated((@items.first ? @items.first.event_datetime : Time.now).xmlschema) + xml.author { xml.name "#{Setting.app_title}" } + xml.generator(:uri => Redmine::Info.url, :version => Redmine::VERSION) { xml.text! "#{Redmine::Info.name} #{Redmine::VERSION}" } + @items.each do |item| + xml.entry do + xml.title truncate(item.event_title, 100) + xml.link "rel" => "alternate", "href" => url_for(item.event_url(:only_path => false)) + xml.id url_for(item.event_url(:only_path => false)) + xml.updated item.event_datetime.xmlschema + author = item.event_author + xml.author do + xml.name(author.is_a?(User) ? author.name : author) + xml.email(author.mail) if author.is_a?(User) + end if author + xml.content "type" => "html" do + xml.text! textilizable(item.event_description) + end + end + end +end diff --git a/app/views/issues/show.rhtml b/app/views/issues/show.rhtml index 078ecd1f562a031e52b051f17a03d72ba5aefc81..70b19d1fcab75f90752228dffb8f5e400a75fa78 100644 --- a/app/views/issues/show.rhtml +++ b/app/views/issues/show.rhtml @@ -58,7 +58,7 @@ end %> <div class="contextual"> <%= link_to_if_authorized l(:button_edit), {:controller => 'issues', :action => 'edit', :id => @issue}, :class => 'icon icon-edit' %> <%= link_to_if_authorized l(:button_log_time), {:controller => 'timelog', :action => 'edit', :issue_id => @issue}, :class => 'icon icon-time' %> -<%= watcher_tag(@issue, @logged_in_user) %> +<%= watcher_tag(@issue, User.current) %> <%= link_to_if_authorized l(:button_move), {:controller => 'projects', :action => 'move_issues', :id => @project, "issue_ids[]" => @issue.id }, :class => 'icon icon-move' %> <%= link_to_if_authorized l(:button_delete), {:controller => 'issues', :action => 'destroy', :id => @issue}, :confirm => l(:text_are_you_sure), :method => :post, :class => 'icon icon-del' %> </div> @@ -81,6 +81,13 @@ end %> </div> <% end %> +<% if @issue.attachments.any? %> +<div class="box"> +<h3><%=l(:label_attachment_plural)%></h3> +<%= link_to_attachments @issue.attachments, :delete_url => (authorize_for('issues', 'destroy_attachment') ? {:controller => 'issues', :action => 'destroy_attachment', :id => @issue} : nil) %> +</div> +<% end %> + <% if @journals.any? %> <div id="history" class="box"> <h3><%=l(:label_history)%></h3> @@ -88,26 +95,14 @@ end %> </div> <% end %> -<div class="box"> -<h3><%=l(:label_attachment_plural)%></h3> -<%= link_to_attachments @issue.attachments, :delete_url => (authorize_for('issues', 'destroy_attachment') ? {:controller => 'issues', :action => 'destroy_attachment', :id => @issue} : nil) %> - -<% if authorize_for('issues', 'add_attachment') %> -<p><%= toggle_link l(:label_attachment_new), "add_attachment_form" %></p> -<% form_tag({ :controller => 'issues', :action => 'add_attachment', :id => @issue }, :multipart => true, :class => "tabular", :id => "add_attachment_form", :style => "display:none;") do %> - <%= render :partial => 'attachments/form' %> -<%= submit_tag l(:button_add) %> -<% end %> -<% end %> -</div> - <% if authorize_for('issues', 'add_note') %> <div class="box"> <h3><%= l(:label_add_note) %></h3> - <% form_tag({:controller => 'issues', :action => 'add_note', :id => @issue}, :class => "tabular" ) do %> + <% form_tag({:controller => 'issues', :action => 'add_note', :id => @issue}, :class => "tabular", :multipart => true) do %> <p><label for="notes"><%=l(:field_notes)%></label> <%= text_area_tag 'notes', '', :cols => 60, :rows => 10, :class => 'wiki-edit' %></p> <%= wikitoolbar_for 'notes' %> + <%= render :partial => 'attachments/form' %> <%= submit_tag l(:button_add) %> <% end %> </div> diff --git a/app/views/layouts/base.rhtml b/app/views/layouts/base.rhtml index 38a2dbeb68d63a039aba3cf03084f416520a8024..9c81a313b3343996a8047bbf85fb7e623391228b 100644 --- a/app/views/layouts/base.rhtml +++ b/app/views/layouts/base.rhtml @@ -27,7 +27,7 @@ <h2><%= Setting.app_subtitle %></h2> </div> <div style="float: right; padding-right: 1em; padding-top: 0.2em;"> - <% if loggedin? %><small><%=l(:label_logged_as)%> <strong><%= @logged_in_user.login %></strong> -</small><% end %> + <% if User.current.logged? %><small><%=l(:label_logged_as)%> <strong><%= User.current.login %></strong> -</small><% end %> <small><%= toggle_link l(:label_search), 'quick-search-form', :focus => 'quick-search-input' %></small> <% form_tag({:controller => 'search', :action => 'index', :id => @project}, :method => :get, :id => 'quick-search-form', :style => "display:none;" ) do %> <%= text_field_tag 'q', @question, :size => 15, :class => 'small', :id => 'quick-search-input' %> @@ -40,27 +40,23 @@ <li><%= link_to l(:label_home), { :controller => 'welcome' }, :class => "icon icon-home" %></li> <li><%= link_to l(:label_my_page), { :controller => 'my', :action => 'page'}, :class => "icon icon-mypage" %></li> - <% if loggedin? and @logged_in_user.memberships.any? %> + <% if User.current.memberships.any? %> <li class="submenu"><%= link_to l(:label_project_plural), { :controller => 'projects' }, :class => "icon icon-projects", :onmouseover => "buttonMouseover(event, 'menuAllProjects');" %></li> <% else %> <li><%= link_to l(:label_project_plural), { :controller => 'projects' }, :class => "icon icon-projects" %></li> <% end %> - - <% unless @project.nil? || @project.id.nil? %> - <li class="submenu"><%= link_to @project.name, { :controller => 'projects', :action => 'show', :id => @project }, :class => "icon icon-projects", :onmouseover => "buttonMouseover(event, 'menuProject');" %></li> - <% end %> - <% if loggedin? %> + <% if User.current.logged? %> <li><%= link_to l(:label_my_account), { :controller => 'my', :action => 'account' }, :class => "icon icon-user" %></li> <% end %> - <% if admin_loggedin? %> + <% if User.current.admin? %> <li class="submenu"><%= link_to l(:label_administration), { :controller => 'admin' }, :class => "icon icon-admin", :onmouseover => "buttonMouseover(event, 'menuAdmin');" %></li> <% end %> <li class="right"><%= link_to l(:label_help), { :controller => 'help', :ctrl => params[:controller], :page => params[:action] }, :onclick => "window.open(this.href); return false;", :class => "icon icon-help" %></li> - <% if loggedin? %> + <% if User.current.logged? %> <li class="right"><%= link_to l(:label_logout), { :controller => 'account', :action => 'logout' }, :class => "icon icon-user" %></li> <% else %> <li class="right"><%= link_to l(:label_login), { :controller => 'account', :action => 'login' }, :class => "icon icon-user" %></li> @@ -68,71 +64,28 @@ </ul> </div> - <% if admin_loggedin? %> + <% if User.current.admin? %> <%= render :partial => 'admin/menu' %> <% end %> - - <% unless @project.nil? || @project.id.nil? %> - <div id="menuProject" class="menu" onmouseover="menuMouseover(event)"> - <%= link_to l(:label_calendar), {:controller => 'projects', :action => 'calendar', :id => @project }, :class => "menuItem" %> - <%= link_to l(:label_gantt), {:controller => 'projects', :action => 'gantt', :id => @project }, :class => "menuItem" %> - <%= link_to l(:label_issue_plural), {:controller => 'projects', :action => 'list_issues', :id => @project }, :class => "menuItem" %> - <% if @project && authorize_for('projects', 'add_issue') %> - <a class="menuItem" href="#" onmouseover="menuItemMouseover(event,'menuNewIssue');" onclick="this.blur(); return false;"><span class="menuItemText"><%= l(:label_issue_new) %></span><span class="menuItemArrow">▶</span></a> - <% end %> - <%= link_to l(:label_report_plural), {:controller => 'reports', :action => 'issue_report', :id => @project }, :class => "menuItem" %> - <%= link_to l(:label_activity), {:controller => 'projects', :action => 'activity', :id => @project }, :class => "menuItem" %> - <%= link_to l(:label_news_plural), {:controller => 'projects', :action => 'list_news', :id => @project }, :class => "menuItem" %> - <%= link_to l(:label_change_log), {:controller => 'projects', :action => 'changelog', :id => @project }, :class => "menuItem" %> - <%= link_to l(:label_roadmap), {:controller => 'projects', :action => 'roadmap', :id => @project }, :class => "menuItem" %> - <%= link_to l(:label_document_plural), {:controller => 'projects', :action => 'list_documents', :id => @project }, :class => "menuItem" %> - <%= link_to l(:label_wiki), {:controller => 'wiki', :id => @project, :page => nil }, :class => "menuItem" if @project.wiki and !@project.wiki.new_record? %> - <%= link_to l(:label_board_plural), {:controller => 'boards', :action => 'index', :project_id => @project, :id => nil }, :class => "menuItem" unless @project.boards.empty? %> - <%= link_to l(:label_attachment_plural), {:controller => 'projects', :action => 'list_files', :id => @project }, :class => "menuItem" %> - <%= link_to l(:label_search), {:controller => 'search', :action => 'index', :id => @project }, :class => "menuItem" %> - <%= link_to l(:label_repository), {:controller => 'repositories', :action => 'show', :id => @project}, :class => "menuItem" if @project.repository and !@project.repository.new_record? %> - <%= link_to_if_authorized l(:label_settings), {:controller => 'projects', :action => 'settings', :id => @project }, :class => "menuItem" %> - </div> - <% end %> - - <% if @project && authorize_for('projects', 'add_issue') %> - <div id="menuNewIssue" class="menu" onmouseover="menuMouseover(event)"> - <% Tracker.find(:all, :order => 'position').each do |tracker| %> - <%= link_to tracker.name, {:controller => 'projects', :action => 'add_issue', :id => @project, :tracker_id => tracker}, :class => "menuItem" %> - <% end %> - </div> - <% end %> - <% if loggedin? and @logged_in_user.memberships.any? %> + <% if User.current.memberships.any? %> <div id="menuAllProjects" class="menu" onmouseover="menuMouseover(event)"> <%= link_to l(:label_project_all), {:controller => 'projects' }, :class => "menuItem" %> - <% @logged_in_user.memberships.find(:all, :limit => 20).each do |membership| %> + <% User.current.memberships.find(:all, :limit => 20).each do |membership| %> <%= link_to membership.project.name, {:controller => 'projects',:action => 'show', :id => membership.project }, :class => "menuItem" %> <% end %> </div> <% end %> - <div id="subcontent"> - - <% unless @project.nil? || @project.id.nil? %> + <div id="subcontent"> + <% if @project && !@project.new_record? %> <h2><%= @project.name %></h2> <ul class="menublock"> - <li><%= link_to l(:label_overview), :controller => 'projects', :action => 'show', :id => @project %></li> - <li><%= link_to l(:label_calendar), :controller => 'projects', :action => 'calendar', :id => @project %></li> - <li><%= link_to l(:label_gantt), :controller => 'projects', :action => 'gantt', :id => @project %></li> - <li><%= link_to l(:label_issue_plural), :controller => 'projects', :action => 'list_issues', :id => @project %></li> - <li><%= link_to l(:label_report_plural), :controller => 'reports', :action => 'issue_report', :id => @project %></li> - <li><%= link_to l(:label_activity), :controller => 'projects', :action => 'activity', :id => @project %></li> - <li><%= link_to l(:label_news_plural), :controller => 'projects', :action => 'list_news', :id => @project %></li> - <li><%= link_to l(:label_change_log), :controller => 'projects', :action => 'changelog', :id => @project %></li> - <li><%= link_to l(:label_roadmap), :controller => 'projects', :action => 'roadmap', :id => @project %></li> - <li><%= link_to l(:label_document_plural), :controller => 'projects', :action => 'list_documents', :id => @project %></li> - <%= content_tag("li", link_to(l(:label_wiki), :controller => 'wiki', :id => @project, :page => nil)) if @project.wiki and !@project.wiki.new_record? %> - <%= content_tag("li", link_to(l(:label_board_plural), :controller => 'boards', :action => 'index', :project_id => @project, :id => nil)) unless @project.boards.empty? %> - <li><%= link_to l(:label_attachment_plural), :controller => 'projects', :action => 'list_files', :id => @project %></li> - <li><%= link_to l(:label_search), :controller => 'search', :action => 'index', :id => @project %></li> - <%= content_tag("li", link_to(l(:label_repository), :controller => 'repositories', :action => 'show', :id => @project)) if @project.repository and !@project.repository.new_record? %> - <li><%= link_to_if_authorized l(:label_settings), :controller => 'projects', :action => 'settings', :id => @project %></li> + <% Redmine::MenuManager.allowed_items(:project_menu, current_role).each do |item| %> + <% unless item.condition && !item.condition.call(@project) %> + <li><%= link_to l(item.name), {item.param => @project}.merge(item.url) %></li> + <% end %> + <% end %> </ul> <% end %> </div> diff --git a/app/views/messages/show.rhtml b/app/views/messages/show.rhtml index c18eb524e791ad84617b772e89828049d2cf1fcd..3e546ceea8a4d25d8ec8e836c2978626db61c388 100644 --- a/app/views/messages/show.rhtml +++ b/app/views/messages/show.rhtml @@ -13,7 +13,7 @@ <div class="wiki"><p><%= textilizable message.content %></p></div> <% end %> -<% if @logged_in_user %> +<% if authorize_for('messages', 'reply') %> <p><%= toggle_link l(:button_reply), "reply", :focus => "reply_content" %></p> <div id="reply" style="display:none;"> <%= error_messages_for 'message' %> diff --git a/app/views/projects/_form.rhtml b/app/views/projects/_form.rhtml index 585217e161350f5f0ba1a3c8bf8636eac44649b7..55527e080c4a533ee9cd009e16c48f5518e69ab2 100644 --- a/app/views/projects/_form.rhtml +++ b/app/views/projects/_form.rhtml @@ -4,7 +4,7 @@ <!--[form:project]--> <p><%= f.text_field :name, :required => true %><br /><em><%= l(:text_caracters_maximum, 30) %></em></p> -<% if admin_loggedin? and !@root_projects.empty? %> +<% if User.current.admin? and !@root_projects.empty? %> <p><%= f.select :parent_id, (@root_projects.collect {|p| [p.name, p.id]}), { :include_blank => true } %></p> <% end %> diff --git a/app/views/projects/_members.rhtml b/app/views/projects/_members.rhtml index 1924e430a0d5fbcd64dff1a51af48c45eee7e75a..affaf78542216fcbe1ab6030e1eb605b9aae0fe6 100644 --- a/app/views/projects/_members.rhtml +++ b/app/views/projects/_members.rhtml @@ -1,5 +1,5 @@ <%= error_messages_for 'member' %> -<% roles = Role.find(:all, :order => 'position') %> +<% roles = Role.find_all_givable %> <% users = User.find_active(:all) - @project.users %> <table class="list"> diff --git a/app/views/projects/activity.rhtml b/app/views/projects/activity.rhtml index d510ce08b6bc04cbef3717880adc35a01531a0c9..fd731cd8f9180d96e81bd1167341ae0ad1558890 100644 --- a/app/views/projects/activity.rhtml +++ b/app/views/projects/activity.rhtml @@ -5,14 +5,11 @@ <% form_tag do %> <p><%= select_month(@month, :prefix => "month", :discard_type => true) %> <%= select_year(@year, :prefix => "year", :discard_type => true) %></p> -<p> - <%= check_box_tag 'show_issues', 1, @show_issues %><%= hidden_field_tag 'show_issues', 0, :id => nil %> <%=l(:label_issue_plural)%><br /> - <% if @project.repository %><%= check_box_tag 'show_changesets', 1, @show_changesets %><%= hidden_field_tag 'show_changesets', 0, :id => nil %> <%=l(:label_revision_plural)%><br /><% end %> - <%= check_box_tag 'show_news', 1, @show_news %><%= hidden_field_tag 'show_news', 0, :id => nil %> <%=l(:label_news_plural)%><br /> - <%= check_box_tag 'show_files', 1, @show_files %><%= hidden_field_tag 'show_files', 0, :id => nil %> <%=l(:label_attachment_plural)%><br /> - <%= check_box_tag 'show_documents', 1, @show_documents %><%= hidden_field_tag 'show_documents', 0, :id => nil %> <%=l(:label_document_plural)%><br /> - <% if @project.wiki %><%= check_box_tag 'show_wiki_edits', 1, @show_wiki_edits %><%= hidden_field_tag 'show_wiki_edits', 0, :id => nil %> <%=l(:label_wiki_edit_plural)%><% end %> -</p> + +<p><% @event_types.each do |t| %> +<%= check_box_tag "show_#{t}", 1, @scope.include?(t) %> <%= l("label_#{t.singularize}_plural")%><br /> +<% end %></p> + <p class="textcenter"><%= submit_tag l(:button_apply), :class => 'button-small' %></p> <% end %> </div> @@ -20,33 +17,33 @@ <% @events_by_day.keys.sort {|x,y| y <=> x }.each do |day| %> <h3><%= day_name(day.cwday) %> <%= day.day %></h3> <ul> - <% @events_by_day[day].sort {|x,y| y.created_on <=> x.created_on }.each do |e| %> + <% @events_by_day[day].sort {|x,y| y.event_datetime <=> x.event_datetime }.each do |e| %> <li><p> <% if e.is_a? Issue %> - <%= e.created_on.strftime("%H:%M") %> <%= link_to_issue e %>: <%=h e.subject %><br /> + <%= e.event_datetime.strftime("%H:%M") %> <%= link_to_issue e %>: <%=h e.subject %><br /> <i><%= e.author.name %></i> <% elsif e.is_a? Journal %> <%= e.created_on.strftime("%H:%M") %> <%= link_to_issue e.journalized %> (<%=h (status = IssueStatus.find_by_id(e.details.first.value)) ? status.name : '?' %>): <%=h e.journalized.subject %><br /> <em><%=h e.user.name %><%=h ": #{truncate(e.notes, 500)}" unless e.notes.blank? %></em> <% elsif e.is_a? News %> - <%= e.created_on.strftime("%H:%M") %> <%=l(:label_news)%>: <%= link_to h(e.title), :controller => 'news', :action => 'show', :id => e %><br /> + <%= e.event_datetime.strftime("%H:%M") %> <%=l(:label_news)%>: <%= link_to h(e.title), :controller => 'news', :action => 'show', :id => e %><br /> <% unless e.summary.empty? %><%=h e.summary %><br /><% end %> <i><%= e.author.name %></i> <% elsif (e.is_a? Attachment) and (e.container.is_a? Version) %> - <%= e.created_on.strftime("%H:%M") %> <%=l(:label_attachment)%> (<%=h e.container.name %>): <%= link_to e.filename, :controller => 'projects', :action => 'list_files', :id => @project %><br /> + <%= e.event_datetime.strftime("%H:%M") %> <%=l(:label_attachment)%> (<%=h e.container.name %>): <%= link_to e.filename, :controller => 'projects', :action => 'list_files', :id => @project %><br /> <i><%= e.author.name %></i> <% elsif (e.is_a? Attachment) and (e.container.is_a? Document) %> - <%= e.created_on.strftime("%H:%M") %> <%=l(:label_attachment)%>: <%= e.filename %> (<%= link_to h(e.container.title), :controller => 'documents', :action => 'show', :id => e.container %>)<br /> + <%= e.event_datetime.strftime("%H:%M") %> <%=l(:label_attachment)%>: <%= e.filename %> (<%= link_to h(e.container.title), :controller => 'documents', :action => 'show', :id => e.container %>)<br /> <i><%= e.author.name %></i> <% elsif e.is_a? Document %> - <%= e.created_on.strftime("%H:%M") %> <%=l(:label_document)%>: <%= link_to h(e.title), :controller => 'documents', :action => 'show', :id => e %><br /> + <%= e.event_datetime.strftime("%H:%M") %> <%=l(:label_document)%>: <%= link_to h(e.title), :controller => 'documents', :action => 'show', :id => e %><br /> <% elsif e.is_a? WikiContent.versioned_class %> - <%= e.created_on.strftime("%H:%M") %> <%=l(:label_wiki_edit)%>: <%= link_to h(WikiPage.pretty_title(e.title)), :controller => 'wiki', :page => e.title %> + <%= e.event_datetime.strftime("%H:%M") %> <%=l(:label_wiki_edit)%>: <%= link_to h(WikiPage.pretty_title(e.title)), :controller => 'wiki', :page => e.title %> (<%= link_to '#' + e.version.to_s, :controller => 'wiki', :page => e.title, :version => e.version %><%= ', ' + link_to('diff', :controller => 'wiki', :action => 'diff', :page => e.title, :version => e.version) if e.version > 1 %>)<br /> <% unless e.comments.blank? %><em><%=h e.comments %></em><% end %> <% elsif e.is_a? Changeset %> - <%= e.created_on.strftime("%H:%M") %> <%=l(:label_revision)%> <%= link_to h(e.revision), :controller => 'repositories', :action => 'revision', :id => @project, :rev => e.revision %><br /> + <%= e.event_datetime.strftime("%H:%M") %> <%=l(:label_revision)%> <%= link_to h(e.revision), :controller => 'repositories', :action => 'revision', :id => @project, :rev => e.revision %><br /> <em><%=h e.committer.blank? ? "anonymous" : e.committer %><%= h(": #{truncate(e.comments, 500)}") unless e.comments.blank? %></em> <% end %> </p></li> @@ -69,3 +66,7 @@ </div> <br /> </div> + +<% content_for :header_tags do %> +<%= auto_discovery_link_tag(:atom, params.merge({:format => 'atom', :year => nil, :month => nil, :key => User.current.rss_key})) %> +<% end %> diff --git a/app/views/projects/list.rhtml b/app/views/projects/list.rhtml index 24448be489b95726ac36969abfcb51e21fdc5000..1fc3aab569443edceeb4e7014a88f9db2cd2c09d 100644 --- a/app/views/projects/list.rhtml +++ b/app/views/projects/list.rhtml @@ -10,7 +10,7 @@ <% for project in @projects %> <tr class="<%= cycle("odd", "even") %>"> <td> - <%= link_to project.name, {:action => 'show', :id => project}, :class => (@logged_in_user && @logged_in_user.role_for_project(project) ? "icon icon-fav" : "") %><br /> + <%= link_to project.name, {:action => 'show', :id => project}, :class => (User.current.member_of?(project) ? "icon icon-fav" : "") %><br /> <%= textilizable project.description, :project => project %> </td> <td><%= link_to(project.parent.name, :action => 'show', :id => project.parent) unless project.parent.nil? %></td> @@ -20,7 +20,7 @@ </tbody> </table> -<% if @logged_in_user %> +<% if User.current.logged? %> <div class="contextual"> <span class="icon icon-fav"><%= l(:label_my_projects) %></span> </div> diff --git a/app/views/projects/list_issues.rhtml b/app/views/projects/list_issues.rhtml index 1cacf0055666e6fe6fcd0981b6a923b2f31141b8..5ebc4107e32545fa7be49bb61cf3f932f6d5ca16 100644 --- a/app/views/projects/list_issues.rhtml +++ b/app/views/projects/list_issues.rhtml @@ -1,6 +1,7 @@ <% if @query.new_record? %> <div class="contextual"> <%= link_to l(:label_query_plural), :controller => 'queries', :project_id => @project %> + <% if authorize_for('projects', 'add_issues') %>| <%= l(:label_issue_new) %>: <%= new_issue_selector %><% end %> </div> <h2><%=l(:label_issue_plural)%></h2> @@ -19,7 +20,7 @@ :update => "content", }, :class => 'icon icon-reload' %> - <% if loggedin? %> + <% if current_role.allowed_to?(:save_queries) %> <%= link_to_remote l(:button_save), { :url => { :controller => 'queries', :action => 'new', :project_id => @project }, :method => 'get', @@ -33,6 +34,7 @@ <div class="contextual"> <%= link_to l(:label_query_plural), {:controller => 'queries', :project_id => @project} %> | <%= link_to l(:label_issue_view_all), {:controller => 'projects', :action => 'list_issues', :id => @project, :set_filter => 1} %> + <% if authorize_for('projects', 'add_issues') %>| <%= l(:label_issue_new) %>: <%= new_issue_selector %><% end %> </div> <h2><%= @query.name %></h2> <% end %> @@ -81,4 +83,4 @@ </p> <% end %> <% end %> -<% end %> \ No newline at end of file +<% end %> diff --git a/app/views/projects/list_news.rhtml b/app/views/projects/list_news.rhtml index 17a786260ab8ed23102004bc7728d82e6f90bdf9..4ab086d556636b830e27c18c99024278d0c4ec07 100644 --- a/app/views/projects/list_news.rhtml +++ b/app/views/projects/list_news.rhtml @@ -7,3 +7,7 @@ <% if @news.empty? %><p><i><%= l(:label_no_data) %></i></p><% end %> <%= render :partial => 'news/news', :collection => @news %> <%= pagination_links_full @news_pages %> + +<% content_for :header_tags do %> + <%= auto_discovery_link_tag(:atom, params.merge({:format => 'atom', :page => nil, :key => User.current.rss_key})) %> +<% end %> diff --git a/app/views/projects/show.rhtml b/app/views/projects/show.rhtml index 9419fb2a13298cc5812a862c271ee860c50f8b05..5f641f6a44ee7b8540d9eb4fde3df4fc767876d3 100644 --- a/app/views/projects/show.rhtml +++ b/app/views/projects/show.rhtml @@ -20,6 +20,7 @@ </ul> <div class="box"> + <div class="contextual"><% if authorize_for('projects', 'add_issues') %><%= l(:label_issue_new) %>: <%= new_issue_selector %><% end %></div> <h3 class="icon22 icon22-tracker"><%=l(:label_issue_tracking)%></h3> <ul> <% for tracker in @trackers %> @@ -49,7 +50,7 @@ </div> <% end %> - <% if @news.any? %> + <% if @news.any? && authorize_for('projects', 'list_news') %> <div class="box"> <h3><%=l(:label_news_latest)%></h3> <%= render :partial => 'news/news', :collection => @news %> diff --git a/app/views/queries/_form.rhtml b/app/views/queries/_form.rhtml index 9482bd33a7f56fccd20a3955a4f803d68373cd6d..d641fa0b5621d326f423f3ff57dbd1202ceff6d6 100644 --- a/app/views/queries/_form.rhtml +++ b/app/views/queries/_form.rhtml @@ -5,7 +5,7 @@ <p><label for="query_name"><%=l(:field_name)%></label> <%= text_field 'query', 'name', :size => 80 %></p> -<% if authorize_for('projects', 'add_query') %> +<% if current_role.allowed_to?(:manage_pulic_queries) %> <p><label for="query_is_public"><%=l(:field_is_public)%></label> <%= check_box 'query', 'is_public' %></p> <% end %> diff --git a/app/views/queries/index.rhtml b/app/views/queries/index.rhtml index 69cfb8f9886e0f13a849ab7f56afdd85876b82da..71aa374975710ba9ea48972d742270d653ec7313 100644 --- a/app/views/queries/index.rhtml +++ b/app/views/queries/index.rhtml @@ -1,7 +1,5 @@ <div class="contextual"> -<% if loggedin? %> -<%= link_to l(:label_query_new), {:controller => 'queries', :action => 'new', :project_id => @project}, :class => 'icon icon-add' %> -<% end %> +<%= link_to_if_authorized l(:label_query_new), {:controller => 'queries', :action => 'new', :project_id => @project}, :class => 'icon icon-add' %> </div> <h2><%= l(:label_query_plural) %></h2> @@ -17,7 +15,7 @@ </td> <td align="right"> <small> - <% if query.editable_by?(@logged_in_user) %> + <% if query.editable_by?(User.current) %> <%= link_to l(:button_edit), {:controller => 'queries', :action => 'edit', :id => query}, :class => 'icon icon-edit' %> <%= link_to l(:button_delete), {:controller => 'queries', :action => 'destroy', :id => query}, :confirm => l(:text_are_you_sure), :method => :post, :class => 'icon icon-del' %> </small> diff --git a/app/views/reports/issue_report.rhtml b/app/views/reports/issue_report.rhtml index bf40e79aef66c77ff3651711eaeb38dea6a5fb78..1d865acbc70e73bc5a4af7b2548db515fe9a2472 100644 --- a/app/views/reports/issue_report.rhtml +++ b/app/views/reports/issue_report.rhtml @@ -1,4 +1,4 @@ -<% if @total_hours %> +<% if @total_hours && authorize_for('timelog', 'reports') %> <div style="float:right;text-align:right;"> <strong><%= l(:label_spent_time) %></strong>: <span class="icon icon-time"><%= lwr(:label_f_hour, @total_hours) %></span><br /> <%= link_to(l(:label_details), {:controller => 'timelog', :action => 'details', :project_id => @project}) %> | diff --git a/app/views/repositories/revisions.rhtml b/app/views/repositories/revisions.rhtml index 0c2655d5f258eec3fb499b86c55bfbdb12ca9336..882d5ea4faf60555c6e5d46b782a5fcbcf86d304 100644 --- a/app/views/repositories/revisions.rhtml +++ b/app/views/repositories/revisions.rhtml @@ -14,4 +14,5 @@ <% content_for :header_tags do %> <%= stylesheet_link_tag "scm" %> +<%= auto_discovery_link_tag(:atom, params.merge({:format => 'atom', :page => nil, :key => User.current.rss_key})) %> <% end %> diff --git a/app/views/repositories/show.rhtml b/app/views/repositories/show.rhtml index fcf954473f99e03ba4d29a4ef5ae27cf0a88768f..c9f44d575ef161cec50d98b1f447f6d51c99dede 100644 --- a/app/views/repositories/show.rhtml +++ b/app/views/repositories/show.rhtml @@ -4,15 +4,18 @@ <h2><%= l(:label_repository) %> (<%= @repository.scm_name %>)</h2> -<% unless @entries.nil? %> +<% if !@entries.nil? && authorize_for('repositories', 'browse') %> <h3><%= l(:label_browse) %></h3> <%= render :partial => 'dir_list' %> <% end %> -<% unless @changesets.empty? %> +<% if !@changesets.empty? && authorize_for('repositories', 'revisions') %> <h3><%= l(:label_latest_revision_plural) %></h3> <%= render :partial => 'revisions', :locals => {:project => @project, :path => '', :revisions => @changesets, :entry => nil }%> <p><%= link_to l(:label_view_revisions), :action => 'revisions', :id => @project %></p> +<% content_for :header_tags do %> + <%= auto_discovery_link_tag(:atom, params.merge({:format => 'atom', :action => 'revisions', :id => @project, :page => nil, :key => User.current.rss_key})) %> +<% end %> <% end %> <% content_for :header_tags do %> diff --git a/app/views/roles/_form.rhtml b/app/views/roles/_form.rhtml index d69fff132df50143727932a51e852b82bc26d049..62e25e33750944fdf22c0276d3ae818d2794153c 100644 --- a/app/views/roles/_form.rhtml +++ b/app/views/roles/_form.rhtml @@ -1,23 +1,20 @@ <%= error_messages_for 'role' %> + <div class="box"> -<!--[form:role]--> -<p><%= f.text_field :name, :required => true %></p> +<p><%= f.text_field :name, :required => true, :disabled => @role.builtin? %></p> +</div> <p><%= f.check_box :assignable %></p> <div class="clear"></div> -<h3><%=l(:label_permissions)%></h3> -<% permissions = @permissions.group_by {|p| p.group_id } %> -<% permissions.keys.sort.each do |group_id| %> -<fieldset style="margin-top: 6px;"><legend><strong><%= l(Permission::GROUPS[group_id]) %></strong></legend> -<% permissions[group_id].each do |p| %> - <div style="width:170px;float:left;"><%= check_box_tag "permission_ids[]", p.id, (@role.permissions.include? p) %> - <%= l(p.description.to_sym) %> - </div> +<fieldset class="box"><legend><%=l(:label_permissions)%></legend> +<% @permissions.each do |permission| %> + <div style="width:220px;float:left;"> + <%= check_box_tag 'role[permissions][]', permission.name, (@role.permissions.include? permission.name) %> + <%= permission.name.to_s.humanize %> + </div> <% end %> +<%= hidden_field_tag 'role[permissions][]', '' %> <div class="clear"></div> -</fieldset> -<% end %> <br /> <%= check_all_links 'role_form' %> -<!--[eoform:role]--> -</div> +</fieldset> diff --git a/app/views/roles/list.rhtml b/app/views/roles/list.rhtml index e3e576ed12e320c5efce089e39d8e881d0a443d7..14ae260aa90dfba4b93ad254aa828758fc4cd513 100644 --- a/app/views/roles/list.rhtml +++ b/app/views/roles/list.rhtml @@ -13,15 +13,17 @@ <tbody> <% for role in @roles %> <tr class="<%= cycle("odd", "even") %>"> - <td><%= link_to role.name, :action => 'edit', :id => role %></td> + <td><%= content_tag(role.builtin? ? 'em' : 'span', link_to(role.name, :action => 'edit', :id => role)) %></td> <td align="center" style="width:15%;"> + <% unless role.builtin? %> <%= link_to image_tag('2uparrow.png', :alt => l(:label_sort_highest)), {:action => 'move', :id => role, :position => 'highest'}, :method => :post, :title => l(:label_sort_highest) %> <%= link_to image_tag('1uparrow.png', :alt => l(:label_sort_higher)), {:action => 'move', :id => role, :position => 'higher'}, :method => :post, :title => l(:label_sort_higher) %> - <%= link_to image_tag('1downarrow.png', :alt => l(:label_sort_lower)), {:action => 'move', :id => role, :position => 'lower'}, :method => :post, :title => l(:label_sort_lower) %> <%= link_to image_tag('2downarrow.png', :alt => l(:label_sort_lowest)), {:action => 'move', :id => role, :position => 'lowest'}, :method => :post, :title => l(:label_sort_lowest) %> + <% end %> </td> <td align="center" style="width:10%;"> - <%= button_to l(:button_delete), { :action => 'destroy', :id => role }, :confirm => l(:text_are_you_sure), :class => "button-small" %> + <%= button_to(l(:button_delete), { :action => 'destroy', :id => role }, :confirm => l(:text_are_you_sure), :class => "button-small") unless role.builtin? %> </tr> <% end %> </tbody> diff --git a/app/views/roles/report.rhtml b/app/views/roles/report.rhtml index 61e1e18e46986c23ae9f5e5e2b51734844ab0ae8..676e25f392cab60419d8e509558b71d863bb9ae9 100644 --- a/app/views/roles/report.rhtml +++ b/app/views/roles/report.rhtml @@ -1,32 +1,31 @@ <h2><%=l(:label_permissions_report)%></h2> <%= start_form_tag({:action => 'report'}, :id => 'permissions_form') %> - +<%= hidden_field_tag 'permissions[0]', '' %> <table class="list"> -<thead><tr> - <th><%=l(:label_permissions)%></th> - <th colspan="<%= @roles.length %>"><%= l(:label_role_plural) %></th> -</tr> -</thead> -<tbody> -<% permissions = @permissions.group_by {|p| p.group_id } %> -<% permissions.keys.sort.each do |group_id| %> +<thead> <tr> - <th><%= l(Permission::GROUPS[group_id]) %></th> - <% @roles.each do |role| %><th align="center"><small><%= role.name %></small></th><% end %> - </tr> - <% permissions[group_id].each do |p| %> - <tr class="<%= cycle("odd", "even") %>"> - <td><%= l(p.description.to_sym) %></td> + <th><%=l(:label_permissions)%></th> <% @roles.each do |role| %> - <td align="center"><%= check_box_tag "permission_ids[#{role.id}][]", p.id, (role.permissions.include? p) %></td> + <th><%= content_tag(role.builtin? ? 'em' : 'span', h(role.name)) %></th> <% end %> </tr> +</thead> +<tbody> +<% @permissions.each do |permission| %> + <tr class="<%= cycle('odd', 'even') %>"> + <td><%= permission.name.to_s.humanize %></td> + <% @roles.each do |role| %> + <td align="center"> + <% if role.setable_permissions.include? permission %> + <%= check_box_tag "permissions[#{role.id}][]", permission.name, (role.permissions.include? permission.name) %> <% end %> -<% reset_cycle -end %> + </td> + <% end %> + </tr> +<% end %> </tbody> </table> <p><%= check_all_links 'permissions_form' %></p> <p><%= submit_tag l(:button_save) %></p> -<%= end_form_tag %> \ No newline at end of file +<%= end_form_tag %> diff --git a/app/views/wiki/show.rhtml b/app/views/wiki/show.rhtml index c7a2985becac4d66fb90495dcfd9c8eaf5541ef0..06eca76ee6a2f47aab2bcc231f92dc7a1c6c1712 100644 --- a/app/views/wiki/show.rhtml +++ b/app/views/wiki/show.rhtml @@ -1,7 +1,7 @@ <div class="contextual"> -<%= link_to(l(:button_edit), {:action => 'edit', :page => @page.title}, :class => 'icon icon-edit') if @content.version == @page.content.version %> +<%= link_to_if_authorized(l(:button_edit), {:action => 'edit', :page => @page.title}, :class => 'icon icon-edit') if @content.version == @page.content.version %> <%= link_to_if_authorized(l(:button_delete), {:action => 'destroy', :page => @page.title}, :method => :post, :confirm => l(:text_are_you_sure), :class => 'icon icon-del') %> -<%= link_to(l(:button_rollback), {:action => 'edit', :page => @page.title, :version => @content.version }, :class => 'icon icon-cancel') if @content.version < @page.content.version %> +<%= link_to_if_authorized(l(:button_rollback), {:action => 'edit', :page => @page.title, :version => @content.version }, :class => 'icon icon-cancel') if @content.version < @page.content.version %> <%= link_to(l(:label_history), {:action => 'history', :page => @page.title}, :class => 'icon icon-history') %> <%= link_to(l(:label_page_index), {:action => 'special', :page => 'Page_index'}, :class => 'icon icon-index') %> </div> diff --git a/db/migrate/001_setup.rb b/db/migrate/001_setup.rb index c61b2c37fd39dea298b0d3fb2f8fed919d62d79a..8b299eb1eab85689824b45964eefa4a699cb021e 100644 --- a/db/migrate/001_setup.rb +++ b/db/migrate/001_setup.rb @@ -16,6 +16,10 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. class Setup < ActiveRecord::Migration + + # model removed + class Permission < ActiveRecord::Base; end + def self.up create_table "attachments", :force => true do |t| t.column "container_id", :integer, :default => 0, :null => false diff --git a/db/migrate/002_issue_move.rb b/db/migrate/002_issue_move.rb index d1acf7ee2a464041ef89e1490d28d5b0f2009884..085593e08ae641d466c56738c9722f0641dd54e3 100644 --- a/db/migrate/002_issue_move.rb +++ b/db/migrate/002_issue_move.rb @@ -1,4 +1,7 @@ class IssueMove < ActiveRecord::Migration + # model removed + class Permission < ActiveRecord::Base; end + def self.up Permission.create :controller => "projects", :action => "move_issues", :description => "button_move", :sort => 1061, :mail_option => 0, :mail_enabled => 0 end diff --git a/db/migrate/003_issue_add_note.rb b/db/migrate/003_issue_add_note.rb index 9f20039b08d694708b5726ba53259c6a5f86073f..a2ab756ee78729f5a1ce3ebb164e361cbaa65fdb 100644 --- a/db/migrate/003_issue_add_note.rb +++ b/db/migrate/003_issue_add_note.rb @@ -1,4 +1,7 @@ class IssueAddNote < ActiveRecord::Migration + # model removed + class Permission < ActiveRecord::Base; end + def self.up Permission.create :controller => "issues", :action => "add_note", :description => "label_add_note", :sort => 1057, :mail_option => 1, :mail_enabled => 0 end diff --git a/db/migrate/004_export_pdf.rb b/db/migrate/004_export_pdf.rb index 66045553ff8edd3ed927ff71a5fefdfdbfacf21b..6ccd67eae9d999359554fd606af7f955dd392c65 100644 --- a/db/migrate/004_export_pdf.rb +++ b/db/migrate/004_export_pdf.rb @@ -1,4 +1,7 @@ class ExportPdf < ActiveRecord::Migration + # model removed + class Permission < ActiveRecord::Base; end + def self.up Permission.create :controller => "projects", :action => "export_issues_pdf", :description => "label_export_pdf", :sort => 1002, :is_public => true, :mail_option => 0, :mail_enabled => 0 Permission.create :controller => "issues", :action => "export_pdf", :description => "label_export_pdf", :sort => 1015, :is_public => true, :mail_option => 0, :mail_enabled => 0 diff --git a/db/migrate/006_calendar_and_activity.rb b/db/migrate/006_calendar_and_activity.rb index 5d8474fc26cdada4601c204b8c5a7b5057315c49..1cdc91d8e73c317371d1d7197f50354aa1249fc9 100644 --- a/db/migrate/006_calendar_and_activity.rb +++ b/db/migrate/006_calendar_and_activity.rb @@ -1,4 +1,7 @@ class CalendarAndActivity < ActiveRecord::Migration + # model removed + class Permission < ActiveRecord::Base; end + def self.up Permission.create :controller => "projects", :action => "activity", :description => "label_activity", :sort => 160, :is_public => true, :mail_option => 0, :mail_enabled => 0 Permission.create :controller => "projects", :action => "calendar", :description => "label_calendar", :sort => 165, :is_public => true, :mail_option => 0, :mail_enabled => 0 diff --git a/db/migrate/007_create_journals.rb b/db/migrate/007_create_journals.rb index 6170b5bd38f864895bde0c3d671313f8e992d9b7..b00347839abec55ffe6b1dcbb5d6dde3dfa70a40 100644 --- a/db/migrate/007_create_journals.rb +++ b/db/migrate/007_create_journals.rb @@ -2,6 +2,8 @@ class CreateJournals < ActiveRecord::Migration # model removed, but needed for data migration class IssueHistory < ActiveRecord::Base; belongs_to :issue; end + # model removed + class Permission < ActiveRecord::Base; end def self.up create_table :journals, :force => true do |t| diff --git a/db/migrate/012_add_comments_permissions.rb b/db/migrate/012_add_comments_permissions.rb index 37f075082e4d6fa246604d4f13b80e60d8a8da3c..2bbf87b02744d33f20b15600d02332dd542d2069 100644 --- a/db/migrate/012_add_comments_permissions.rb +++ b/db/migrate/012_add_comments_permissions.rb @@ -1,4 +1,7 @@ class AddCommentsPermissions < ActiveRecord::Migration + # model removed + class Permission < ActiveRecord::Base; end + def self.up Permission.create :controller => "news", :action => "add_comment", :description => "label_comment_add", :sort => 1130, :is_public => false, :mail_option => 0, :mail_enabled => 0 Permission.create :controller => "news", :action => "destroy_comment", :description => "label_comment_delete", :sort => 1133, :is_public => false, :mail_option => 0, :mail_enabled => 0 diff --git a/db/migrate/014_add_queries_permissions.rb b/db/migrate/014_add_queries_permissions.rb index 27d674650a96915f67ea5c9410ac617d9b98dcc2..34eba1e26665e97353eb719036ba6478b8672d31 100644 --- a/db/migrate/014_add_queries_permissions.rb +++ b/db/migrate/014_add_queries_permissions.rb @@ -1,4 +1,7 @@ class AddQueriesPermissions < ActiveRecord::Migration + # model removed + class Permission < ActiveRecord::Base; end + def self.up Permission.create :controller => "projects", :action => "add_query", :description => "button_create", :sort => 600, :is_public => false, :mail_option => 0, :mail_enabled => 0 end diff --git a/db/migrate/016_add_repositories_permissions.rb b/db/migrate/016_add_repositories_permissions.rb index 992f8dccd1c7a13a0728b199883a717d69430f1b..341707639beeaf6929f4070684e9828a907b66a1 100644 --- a/db/migrate/016_add_repositories_permissions.rb +++ b/db/migrate/016_add_repositories_permissions.rb @@ -1,4 +1,7 @@ class AddRepositoriesPermissions < ActiveRecord::Migration + # model removed + class Permission < ActiveRecord::Base; end + def self.up Permission.create :controller => "repositories", :action => "show", :description => "button_view", :sort => 1450, :is_public => true Permission.create :controller => "repositories", :action => "browse", :description => "label_browse", :sort => 1460, :is_public => true diff --git a/db/migrate/018_set_doc_and_files_notifications.rb b/db/migrate/018_set_doc_and_files_notifications.rb index adbdd3b88a2f07f99ba5734515a5afd744f72944..8c1d054c1adbdc28b8daab729ce43e4e1462a862 100644 --- a/db/migrate/018_set_doc_and_files_notifications.rb +++ b/db/migrate/018_set_doc_and_files_notifications.rb @@ -1,4 +1,7 @@ class SetDocAndFilesNotifications < ActiveRecord::Migration + # model removed + class Permission < ActiveRecord::Base; end + def self.up Permission.find_by_controller_and_action("projects", "add_file").update_attribute(:mail_option, true) Permission.find_by_controller_and_action("projects", "add_document").update_attribute(:mail_option, true) diff --git a/db/migrate/024_add_roadmap_permission.rb b/db/migrate/024_add_roadmap_permission.rb index 5b9f3a5620576941ece0f80518f069c7d070211e..5c37beac15c288fbf242404c2df00c6ce343cd60 100644 --- a/db/migrate/024_add_roadmap_permission.rb +++ b/db/migrate/024_add_roadmap_permission.rb @@ -1,4 +1,7 @@ class AddRoadmapPermission < ActiveRecord::Migration + # model removed + class Permission < ActiveRecord::Base; end + def self.up Permission.create :controller => "projects", :action => "roadmap", :description => "label_roadmap", :sort => 107, :is_public => true, :mail_option => 0, :mail_enabled => 0 end diff --git a/db/migrate/025_add_search_permission.rb b/db/migrate/025_add_search_permission.rb index 408716eb69a71bfd81488ea14d9806143028c1a3..a942b01b35d44b52fc37c61ce61871f574a72f46 100644 --- a/db/migrate/025_add_search_permission.rb +++ b/db/migrate/025_add_search_permission.rb @@ -1,4 +1,7 @@ class AddSearchPermission < ActiveRecord::Migration + # model removed + class Permission < ActiveRecord::Base; end + def self.up Permission.create :controller => "projects", :action => "search", :description => "label_search", :sort => 130, :is_public => true, :mail_option => 0, :mail_enabled => 0 end diff --git a/db/migrate/030_add_projects_feeds_permissions.rb b/db/migrate/030_add_projects_feeds_permissions.rb index 63131001e0999c4778af4ad767f513ddc6d00911..7f97035bf198340829ec459b9cde0f470e60bbe2 100644 --- a/db/migrate/030_add_projects_feeds_permissions.rb +++ b/db/migrate/030_add_projects_feeds_permissions.rb @@ -1,4 +1,7 @@ class AddProjectsFeedsPermissions < ActiveRecord::Migration + # model removed + class Permission < ActiveRecord::Base; end + def self.up Permission.create :controller => "projects", :action => "feeds", :description => "label_feed_plural", :sort => 132, :is_public => true, :mail_option => 0, :mail_enabled => 0 end diff --git a/db/migrate/033_add_timelog_permissions.rb b/db/migrate/033_add_timelog_permissions.rb index 3b5b81ed61e4cc0d9d37a9b8af6b904e7215954f..ab9c809e647653ee524d93f85dbb9540d993398b 100644 --- a/db/migrate/033_add_timelog_permissions.rb +++ b/db/migrate/033_add_timelog_permissions.rb @@ -1,4 +1,7 @@ class AddTimelogPermissions < ActiveRecord::Migration + # model removed + class Permission < ActiveRecord::Base; end + def self.up Permission.create :controller => "timelog", :action => "edit", :description => "button_log_time", :sort => 1520, :is_public => false, :mail_option => 0, :mail_enabled => 0 end diff --git a/db/migrate/043_add_relations_permissions.rb b/db/migrate/043_add_relations_permissions.rb index 3f1da8f2775c13adf2390b3757d6cf916ff2fd9c..32d464a585ea4d507a34307e35ade33e5cb0f221 100644 --- a/db/migrate/043_add_relations_permissions.rb +++ b/db/migrate/043_add_relations_permissions.rb @@ -1,4 +1,7 @@ class AddRelationsPermissions < ActiveRecord::Migration + # model removed + class Permission < ActiveRecord::Base; end + def self.up Permission.create :controller => "issue_relations", :action => "new", :description => "label_relation_new", :sort => 1080, :is_public => false, :mail_option => 0, :mail_enabled => 0 Permission.create :controller => "issue_relations", :action => "destroy", :description => "label_relation_delete", :sort => 1085, :is_public => false, :mail_option => 0, :mail_enabled => 0 diff --git a/db/migrate/047_add_boards_permissions.rb b/db/migrate/047_add_boards_permissions.rb index cafdc1eac469d164feac55e4d95ca49b805f17e4..5b1f6f779ce9e186bf17cb964def06f007c7f80b 100644 --- a/db/migrate/047_add_boards_permissions.rb +++ b/db/migrate/047_add_boards_permissions.rb @@ -1,4 +1,7 @@ class AddBoardsPermissions < ActiveRecord::Migration + # model removed + class Permission < ActiveRecord::Base; end + def self.up Permission.create :controller => "boards", :action => "new", :description => "button_add", :sort => 2000, :is_public => false, :mail_option => 0, :mail_enabled => 0 Permission.create :controller => "boards", :action => "edit", :description => "button_edit", :sort => 2005, :is_public => false, :mail_option => 0, :mail_enabled => 0 diff --git a/db/migrate/049_add_wiki_destroy_page_permission.rb b/db/migrate/049_add_wiki_destroy_page_permission.rb index c68370f22cdb176253ad1c909523e448d7629c82..c82152388352b0761dd6022565fe8947499419b1 100644 --- a/db/migrate/049_add_wiki_destroy_page_permission.rb +++ b/db/migrate/049_add_wiki_destroy_page_permission.rb @@ -1,4 +1,7 @@ class AddWikiDestroyPagePermission < ActiveRecord::Migration + # model removed + class Permission < ActiveRecord::Base; end + def self.up Permission.create :controller => 'wiki', :action => 'destroy', :description => 'button_delete', :sort => 1740, :is_public => false, :mail_option => 0, :mail_enabled => 0 end diff --git a/db/migrate/050_add_wiki_attachments_permissions.rb b/db/migrate/050_add_wiki_attachments_permissions.rb index 6c81273a10ff8452a66d61d967270318d7bf0529..c0697be9c9b026652f4143f3866a136b8b173b57 100644 --- a/db/migrate/050_add_wiki_attachments_permissions.rb +++ b/db/migrate/050_add_wiki_attachments_permissions.rb @@ -1,4 +1,7 @@ class AddWikiAttachmentsPermissions < ActiveRecord::Migration + # model removed + class Permission < ActiveRecord::Base; end + def self.up Permission.create :controller => 'wiki', :action => 'add_attachment', :description => 'label_attachment_new', :sort => 1750, :is_public => false, :mail_option => 0, :mail_enabled => 0 Permission.create :controller => 'wiki', :action => 'destroy_attachment', :description => 'label_attachment_delete', :sort => 1755, :is_public => false, :mail_option => 0, :mail_enabled => 0 diff --git a/db/migrate/056_add_repositories_changes_permission.rb b/db/migrate/056_add_repositories_changes_permission.rb index e93514900c131eb5049ae4abaf3810f80b0593db..0d9b13b59dddc3cead7b143b85abaea93f46b166 100644 --- a/db/migrate/056_add_repositories_changes_permission.rb +++ b/db/migrate/056_add_repositories_changes_permission.rb @@ -1,4 +1,7 @@ class AddRepositoriesChangesPermission < ActiveRecord::Migration + # model removed + class Permission < ActiveRecord::Base; end + def self.up Permission.create :controller => 'repositories', :action => 'changes', :description => 'label_change_plural', :sort => 1475, :is_public => true, :mail_option => 0, :mail_enabled => 0 end diff --git a/db/migrate/061_add_roles_builtin.rb b/db/migrate/061_add_roles_builtin.rb new file mode 100644 index 0000000000000000000000000000000000000000..a8d6fe9e6a7ff243658ca31d773b1ea476ea8823 --- /dev/null +++ b/db/migrate/061_add_roles_builtin.rb @@ -0,0 +1,9 @@ +class AddRolesBuiltin < ActiveRecord::Migration + def self.up + add_column :roles, :builtin, :integer, :default => 0, :null => false + end + + def self.down + remove_column :roles, :builtin + end +end diff --git a/db/migrate/062_insert_builtin_roles.rb b/db/migrate/062_insert_builtin_roles.rb new file mode 100644 index 0000000000000000000000000000000000000000..27c7475c3219d4121ef1917ce203d8913c5a0169 --- /dev/null +++ b/db/migrate/062_insert_builtin_roles.rb @@ -0,0 +1,15 @@ +class InsertBuiltinRoles < ActiveRecord::Migration + def self.up + nonmember = Role.new(:name => 'Non member', :position => 0) + nonmember.builtin = Role::BUILTIN_NON_MEMBER + nonmember.save + + anonymous = Role.new(:name => 'Anonymous', :position => 0) + anonymous.builtin = Role::BUILTIN_ANONYMOUS + anonymous.save + end + + def self.down + Role.destroy_all 'builtin <> 0' + end +end diff --git a/db/migrate/063_add_roles_permissions.rb b/db/migrate/063_add_roles_permissions.rb new file mode 100644 index 0000000000000000000000000000000000000000..107a3af0a1d3d92a8d5cfcc830555ec0ce1ae104 --- /dev/null +++ b/db/migrate/063_add_roles_permissions.rb @@ -0,0 +1,9 @@ +class AddRolesPermissions < ActiveRecord::Migration + def self.up + add_column :roles, :permissions, :text + end + + def self.down + remove_column :roles, :permissions + end +end diff --git a/db/migrate/064_drop_permissions.rb b/db/migrate/064_drop_permissions.rb new file mode 100644 index 0000000000000000000000000000000000000000..f4ca470bfcf0d2df34a74b147be4cf549870179e --- /dev/null +++ b/db/migrate/064_drop_permissions.rb @@ -0,0 +1,10 @@ +class DropPermissions < ActiveRecord::Migration + def self.up + drop_table :permissions + drop_table :permissions_roles + end + + def self.down + raise IrreversibleMigration + end +end diff --git a/lib/redmine.rb b/lib/redmine.rb index 9fc2a103bc1de0475049ab67e006d6b693c93280..df4d0a8cf6ffc49b2ec3e84c0b2d242e8dc999d7 100644 --- a/lib/redmine.rb +++ b/lib/redmine.rb @@ -1,6 +1,9 @@ require 'redmine/version' +require 'redmine/access_control' +require 'redmine/menu_manager' require 'redmine/mime_type' require 'redmine/acts_as_watchable/init' +require 'redmine/acts_as_event/init' begin require_library_or_gem 'rmagick' unless Object.const_defined?(:Magick) @@ -9,3 +12,77 @@ rescue LoadError end REDMINE_SUPPORTED_SCM = %w( Subversion Darcs Mercurial Cvs ) + +# Permissions +Redmine::AccessControl.map do |map| + # Project + map.permission :view_project, {:projects => [:show, :activity, :changelog, :roadmap, :feeds]}, :public => true + map.permission :search_project, {:search => :index}, :public => true + map.permission :edit_project, {:projects => [:settings, :edit]}, :require => :member + map.permission :manage_members, {:projects => [:settings, :add_member], :members => [:edit, :destroy]}, :require => :member + map.permission :manage_versions, {:projects => [:settings, :add_version], :versions => [:edit, :destroy]}, :require => :member + map.permission :manage_categories, {:projects => [:settings, :add_issue_category], :issue_categories => [:edit, :destroy]}, :require => :member + + # Issues + map.permission :view_issues, {:projects => [:list_issues, :export_issues_csv, :export_issues_pdf], + :issues => [:show, :export_pdf], + :queries => :index, + :reports => :issue_report}, :public => true + map.permission :add_issues, {:projects => :add_issue}, :require => :loggedin + map.permission :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 + 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 + # Queries + map.permission :manage_pulic_queries, {:queries => [:new, :edit, :destroy]}, :require => :member + map.permission :save_queries, {:queries => [:new, :edit, :destroy]}, :require => :loggedin + # Gantt & calendar + map.permission :view_gantt, :projects => :gantt + map.permission :view_calendar, :projects => :calendar + # Time tracking + map.permission :log_time, {:timelog => :edit}, :require => :loggedin + map.permission :view_time_entries, :timelog => [:details, :report] + # News + map.permission :view_news, {:projects => :list_news, :news => :show}, :public => true + map.permission :manage_news, {:projects => :add_news, :news => [:edit, :destroy, :destroy_comment]}, :require => :member + map.permission :comment_news, {:news => :add_comment}, :require => :loggedin + # Documents + map.permission :view_documents, :projects => :list_documents, :documents => [:show, :download] + map.permission :manage_documents, {:projects => :add_document, :documents => [:edit, :destroy, :add_attachment, :destroy_attachment]}, :require => :loggedin + # Wiki + map.permission :view_wiki_pages, :wiki => [:index, :history, :diff, :special] + map.permission :edit_wiki_pages, :wiki => [:edit, :preview, :add_attachment, :destroy_attachment] + map.permission :delete_wiki_pages, {:wiki => :destroy}, :require => :member + # Message boards + map.permission :view_messages, {:boards => [:index, :show], :messages => [:show]}, :public => true + map.permission :add_messages, {:messages => [:new, :reply]}, :require => :loggedin + map.permission :manage_boards, {:boards => [:new, :edit, :destroy]}, :require => :member + # Files + map.permission :view_files, :projects => :list_files, :versions => :download + map.permission :manage_files, {:projects => :add_file, :versions => :destroy_file}, :require => :loggedin + # Repository + map.permission :browse_repository, :repositories => [:show, :browse, :entry, :changes, :diff, :stats, :graph] + map.permission :view_changesets, :repositories => [:show, :revisions, :revision] +end + +# Project menu configuration +Redmine::MenuManager.map :project_menu do |menu| + menu.push :label_overview, :controller => 'projects', :action => 'show' + menu.push :label_calendar, :controller => 'projects', :action => 'calendar' + menu.push :label_gantt, :controller => 'projects', :action => 'gantt' + menu.push :label_issue_plural, :controller => 'projects', :action => 'list_issues' + menu.push :label_report_plural, :controller => 'reports', :action => 'issue_report' + menu.push :label_activity, :controller => 'projects', :action => 'activity' + menu.push :label_news_plural, :controller => 'projects', :action => 'list_news' + menu.push :label_change_log, :controller => 'projects', :action => 'changelog' + menu.push :label_roadmap, :controller => 'projects', :action => 'roadmap' + menu.push :label_document_plural, :controller => 'projects', :action => 'list_documents' + menu.push :label_wiki, { :controller => 'wiki', :action => 'index', :page => nil }, :if => Proc.new { |p| p.wiki && !p.wiki.new_record? } + menu.push :label_board_plural, { :controller => 'boards', :action => 'index', :id => nil }, :param => :project_id, :if => Proc.new { |p| p.boards.any? } + menu.push :label_attachment_plural, :controller => 'projects', :action => 'list_files' + menu.push :label_search, :controller => 'search', :action => 'index' + menu.push :label_repository, { :controller => 'repositories', :action => 'show' }, :if => Proc.new { |p| p.repository && !p.repository.new_record? } + menu.push :label_settings, :controller => 'projects', :action => 'settings' +end diff --git a/lib/redmine/access_control.rb b/lib/redmine/access_control.rb new file mode 100644 index 0000000000000000000000000000000000000000..54b344b7e81dedc1b1d0419ea1061224b6a41c37 --- /dev/null +++ b/lib/redmine/access_control.rb @@ -0,0 +1,92 @@ +# redMine - project management software +# Copyright (C) 2006-2007 Jean-Philippe Lang +# +# 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. + +module Redmine + module AccessControl + + class << self + def map + mapper = Mapper.new + yield mapper + @permissions ||= [] + @permissions += mapper.mapped_permissions + end + + def permissions + @permissions + end + + def allowed_actions(permission_name) + perm = @permissions.detect {|p| p.name == permission_name} + perm ? perm.actions : [] + end + + def public_permissions + @public_permissions ||= @permissions.select {|p| p.public?} + end + + def members_only_permissions + @members_only_permissions ||= @permissions.select {|p| p.require_member?} + end + + def loggedin_only_permissions + @loggedin_only_permissions ||= @permissions.select {|p| p.require_loggedin?} + end + end + + class Mapper + def permission(name, hash, options={}) + @permissions ||= [] + @permissions << Permission.new(name, hash, options) + end + + def mapped_permissions + @permissions + end + end + + class Permission + attr_reader :name, :actions + + def initialize(name, hash, options) + @name = name + @actions = [] + @public = options[:public] || false + @require = options[:require] + hash.each do |controller, actions| + if actions.is_a? Array + @actions << actions.collect {|action| "#{controller}/#{action}"} + else + @actions << "#{controller}/#{actions}" + end + end + end + + def public? + @public + end + + def require_member? + @require && @require == :member + end + + def require_loggedin? + @require && (@require == :member || @require == :loggedin) + end + end + end +end diff --git a/lib/redmine/acts_as_event/init.rb b/lib/redmine/acts_as_event/init.rb new file mode 100644 index 0000000000000000000000000000000000000000..91051510adfe1a812b97f5fc31379bc8008858f6 --- /dev/null +++ b/lib/redmine/acts_as_event/init.rb @@ -0,0 +1,2 @@ +require File.dirname(__FILE__) + '/lib/acts_as_event' +ActiveRecord::Base.send(:include, Redmine::Acts::Event) diff --git a/lib/redmine/acts_as_event/lib/acts_as_event.rb b/lib/redmine/acts_as_event/lib/acts_as_event.rb new file mode 100644 index 0000000000000000000000000000000000000000..a0d1822ad0dc0dba31f4b51a687dd88aa233faed --- /dev/null +++ b/lib/redmine/acts_as_event/lib/acts_as_event.rb @@ -0,0 +1,68 @@ +# redMine - project management software +# Copyright (C) 2006-2007 Jean-Philippe Lang +# +# 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. + +module Redmine + module Acts + module Event + def self.included(base) + base.extend ClassMethods + end + + module ClassMethods + def acts_as_event(options = {}) + return if self.included_modules.include?(Redmine::Acts::Event::InstanceMethods) + options[:datetime] ||= 'created_on' + options[:title] ||= 'title' + options[:description] ||= 'description' + options[:author] ||= 'author' + options[:url] ||= {:controller => 'welcome'} + cattr_accessor :event_options + self.event_options = options + send :include, Redmine::Acts::Event::InstanceMethods + end + end + + module InstanceMethods + def self.included(base) + base.extend ClassMethods + end + + %w(datetime title description author).each do |attr| + src = <<-END_SRC + def event_#{attr} + option = event_options[:#{attr}] + option.is_a?(Proc) ? option.call(self) : send(option) + end + END_SRC + class_eval src, __FILE__, __LINE__ + end + + def event_date + event_datetime.to_date + end + + def event_url(options = {}) + option = event_options[:url] + (option.is_a?(Proc) ? option.call(self) : send(option)).merge(options) + end + + module ClassMethods + end + end + end + end +end diff --git a/lib/redmine/menu_manager.rb b/lib/redmine/menu_manager.rb new file mode 100644 index 0000000000000000000000000000000000000000..afb7699b08c4339e7b7da4ea275d96d61180e2a9 --- /dev/null +++ b/lib/redmine/menu_manager.rb @@ -0,0 +1,61 @@ +# redMine - project management software +# Copyright (C) 2006-2007 Jean-Philippe Lang +# +# 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. + +module Redmine + module MenuManager + + class << self + def map(menu_name) + mapper = Mapper.new + yield mapper + @items ||= {} + @items[menu_name.to_sym] ||= [] + @items[menu_name.to_sym] += mapper.items + end + + def items(menu_name) + @items[menu_name.to_sym] || [] + end + + def allowed_items(menu_name, role) + items(menu_name).select {|item| role && role.allowed_to?(item.url)} + end + end + + class Mapper + def push(name, url, options={}) + @items ||= [] + @items << MenuItem.new(name, url, options) + end + + def items + @items + end + end + + class MenuItem + attr_reader :name, :url, :param, :condition + + def initialize(name, url, options) + @name = name + @url = url + @condition = options[:if] + @param = options[:param] || :id + end + end + end +end diff --git a/lib/redmine/version.rb b/lib/redmine/version.rb index 5934af03eced4307f8cd68af40d457fa5ffa968f..494bb2de2cb2b58ba22578dffe317cd0f07a48c0 100644 --- a/lib/redmine/version.rb +++ b/lib/redmine/version.rb @@ -8,4 +8,11 @@ module Redmine def self.to_s; STRING end end + + module Info + class << self + def name; 'Redmine' end + def url; 'http://www.redmine.org/' end + end + end end diff --git a/lib/tasks/load_default_data.rake b/lib/tasks/load_default_data.rake index 488cd2a64af6ab40b791fafca9a5bb74b1b9d38d..e59c3c5fe632e20ac316cc6479d4e0a71fb60e95 100644 --- a/lib/tasks/load_default_data.rake +++ b/lib/tasks/load_default_data.rake @@ -19,7 +19,7 @@ task :load_default_data => :environment do begin # check that no data already exists - if Role.find(:first) + if Role.find(:first, :conditions => {:builtin => 0}) raise "Some roles are already defined." end if Tracker.find(:first) @@ -35,17 +35,78 @@ begin puts "Loading default configuration data for language: #{current_language}" # roles - manager = Role.create :name => l(:default_role_manager), :position => 1 - manager.permissions = Permission.find(:all, :conditions => ["is_public=?", false]) + manager = Role.create :name => l(:default_role_manager), + :position => 1 + manager.permissions = manager.setable_permissions.collect {|p| p.name} + manager.save - developper = Role.create :name => l(:default_role_developper), :position => 2 - perms = [150, 320, 321, 322, 420, 421, 422, 1050, 1060, 1070, 1075, 1130, 1220, 1221, 1222, 1223, 1224, 1320, 1322, 1061, 1057, 1520] - developper.permissions = Permission.find(:all, :conditions => ["sort IN (#{perms.join(',')})"]) - - reporter = Role.create :name => l(:default_role_reporter), :position => 3 - perms = [1050, 1060, 1070, 1057, 1130] - reporter.permissions = Permission.find(:all, :conditions => ["sort IN (#{perms.join(',')})"]) + developper = Role.create :name => l(:default_role_developper), + :position => 2, + :permissions => [:manage_versions, + :manage_categories, + :add_issues, + :edit_issues, + :manage_issue_relations, + :add_issue_notes, + :change_issue_status, + :save_queries, + :view_gantt, + :view_calendar, + :log_time, + :view_time_entries, + :comment_news, + :view_documents, + :view_wiki_pages, + :edit_wiki_pages, + :delete_wiki_pages, + :add_messages, + :view_files, + :manage_files, + :browse_repository, + :view_changesets] + reporter = Role.create :name => l(:default_role_reporter), + :position => 3, + :permissions => [:add_issues, + :add_issue_notes, + :change_issue_status, + :save_queries, + :view_gantt, + :view_calendar, + :log_time, + :view_time_entries, + :comment_news, + :view_documents, + :view_wiki_pages, + :add_messages, + :view_files, + :browse_repository, + :view_changesets] + + Role.non_member.update_attribute :permissions, [:add_issues, + :add_issue_notes, + :change_issue_status, + :save_queries, + :view_gantt, + :view_calendar, + :view_time_entries, + :comment_news, + :view_documents, + :view_wiki_pages, + :add_messages, + :view_files, + :browse_repository, + :view_changesets] + + Role.anonymous.update_attribute :permissions, [:view_gantt, + :view_calendar, + :view_time_entries, + :view_documents, + :view_wiki_pages, + :view_files, + :browse_repository, + :view_changesets] + # trackers Tracker.create(:name => l(:default_tracker_bug), :is_in_chlog => true, :is_in_roadmap => false, :position => 1) Tracker.create(:name => l(:default_tracker_feature), :is_in_chlog => true, :is_in_roadmap => true, :position => 2) diff --git a/test/fixtures/permissions.yml b/test/fixtures/permissions.yml deleted file mode 100644 index c8e460001555f34933ea35b40a1c476a0c2d2ab7..0000000000000000000000000000000000000000 --- a/test/fixtures/permissions.yml +++ /dev/null @@ -1,559 +0,0 @@ ---- -permissions_052: - action: destroy_comment - id: 52 - description: label_comment_delete - controller: news - mail_enabled: false - mail_option: false - sort: 1133 - is_public: false -permissions_041: - action: add_file - id: 41 - description: button_add - controller: projects - mail_enabled: false - mail_option: true - sort: 1320 - is_public: false -permissions_030: - action: destroy - id: 30 - description: button_delete - controller: news - mail_enabled: false - mail_option: false - sort: 1122 - is_public: false -permissions_019: - action: download - id: 19 - description: button_download - controller: issues - mail_enabled: false - mail_option: false - sort: 1010 - is_public: true -permissions_008: - action: edit - id: 8 - description: button_edit - controller: members - mail_enabled: false - mail_option: false - sort: 221 - is_public: false -permissions_053: - action: add_query - id: 53 - description: button_create - controller: projects - mail_enabled: false - mail_option: false - sort: 600 - is_public: false -permissions_042: - action: destroy_file - id: 42 - description: button_delete - controller: versions - mail_enabled: false - mail_option: false - sort: 1322 - is_public: false -permissions_031: - action: list_documents - id: 31 - description: button_list - controller: projects - mail_enabled: false - mail_option: false - sort: 1200 - is_public: true -permissions_020: - action: add_issue - id: 20 - description: button_add - controller: projects - mail_enabled: true - mail_option: true - sort: 1050 - is_public: false -permissions_009: - action: destroy - id: 9 - description: button_delete - controller: members - mail_enabled: false - mail_option: false - sort: 222 - is_public: false -permissions_054: - action: show - id: 54 - description: button_view - controller: repositories - mail_enabled: false - mail_option: false - sort: 1450 - is_public: true -permissions_043: - action: move_issues - id: 43 - description: button_move - controller: projects - mail_enabled: false - mail_option: false - sort: 1061 - is_public: false -permissions_032: - action: show - id: 32 - description: button_view - controller: documents - mail_enabled: false - mail_option: false - sort: 1201 - is_public: true -permissions_021: - action: edit - id: 21 - description: button_edit - controller: issues - mail_enabled: false - mail_option: false - sort: 1055 - is_public: false -permissions_010: - action: add_version - id: 10 - description: button_add - controller: projects - mail_enabled: false - mail_option: false - sort: 320 - is_public: false -permissions_055: - action: browse - id: 55 - description: label_browse - controller: repositories - mail_enabled: false - mail_option: false - sort: 1460 - is_public: true -permissions_044: - action: add_note - id: 44 - description: label_add_note - controller: issues - mail_enabled: false - mail_option: true - sort: 1057 - is_public: false -permissions_033: - action: download - id: 33 - description: button_download - controller: documents - mail_enabled: false - mail_option: false - sort: 1202 - is_public: true -permissions_022: - action: change_status - id: 22 - description: label_change_status - controller: issues - mail_enabled: true - mail_option: true - sort: 1060 - is_public: false -permissions_011: - action: edit - id: 11 - description: button_edit - controller: versions - mail_enabled: false - mail_option: false - sort: 321 - is_public: false -permissions_056: - action: entry - id: 56 - description: entry - controller: repositories - mail_enabled: false - mail_option: false - sort: 1462 - is_public: true -permissions_045: - action: export_issues_pdf - id: 45 - description: label_export_pdf - controller: projects - mail_enabled: false - mail_option: false - sort: 1002 - is_public: true -permissions_034: - action: add_document - id: 34 - description: button_add - controller: projects - mail_enabled: false - mail_option: true - sort: 1220 - is_public: false -permissions_023: - action: destroy - id: 23 - description: button_delete - controller: issues - mail_enabled: false - mail_option: false - sort: 1065 - is_public: false -permissions_012: - action: destroy - id: 12 - description: button_delete - controller: versions - mail_enabled: false - mail_option: false - sort: 322 - is_public: false -permissions_001: - action: show - id: 1 - description: label_overview - controller: projects - mail_enabled: false - mail_option: false - sort: 100 - is_public: true -permissions_057: - action: revisions - id: 57 - description: label_view_revisions - controller: repositories - mail_enabled: false - mail_option: false - sort: 1470 - is_public: true -permissions_046: - action: export_pdf - id: 46 - description: label_export_pdf - controller: issues - mail_enabled: false - mail_option: false - sort: 1015 - is_public: true -permissions_035: - action: edit - id: 35 - description: button_edit - controller: documents - mail_enabled: false - mail_option: false - sort: 1221 - is_public: false -permissions_024: - action: add_attachment - id: 24 - description: label_attachment_new - controller: issues - mail_enabled: false - mail_option: true - sort: 1070 - is_public: false -permissions_013: - action: add_issue_category - id: 13 - description: button_add - controller: projects - mail_enabled: false - mail_option: false - sort: 420 - is_public: false -permissions_002: - action: changelog - id: 2 - description: label_change_log - controller: projects - mail_enabled: false - mail_option: false - sort: 105 - is_public: true -permissions_058: - action: revision - id: 58 - description: label_view_revisions - controller: repositories - mail_enabled: false - mail_option: false - sort: 1472 - is_public: true -permissions_047: - action: activity - id: 47 - description: label_activity - controller: projects - mail_enabled: false - mail_option: false - sort: 160 - is_public: true -permissions_036: - action: destroy - id: 36 - description: button_delete - controller: documents - mail_enabled: false - mail_option: false - sort: 1222 - is_public: false -permissions_025: - action: destroy_attachment - id: 25 - description: label_attachment_delete - controller: issues - mail_enabled: false - mail_option: false - sort: 1075 - is_public: false -permissions_014: - action: edit - id: 14 - description: button_edit - controller: issue_categories - mail_enabled: false - mail_option: false - sort: 421 - is_public: false -permissions_003: - action: issue_report - id: 3 - description: label_report_plural - controller: reports - mail_enabled: false - mail_option: false - sort: 110 - is_public: true -permissions_059: - action: diff - id: 59 - description: diff - controller: repositories - mail_enabled: false - mail_option: false - sort: 1480 - is_public: true -permissions_048: - action: calendar - id: 48 - description: label_calendar - controller: projects - mail_enabled: false - mail_option: false - sort: 165 - is_public: true -permissions_037: - action: add_attachment - id: 37 - description: label_attachment_new - controller: documents - mail_enabled: false - mail_option: true - sort: 1223 - is_public: false -permissions_026: - action: list_news - id: 26 - description: button_list - controller: projects - mail_enabled: false - mail_option: false - sort: 1100 - is_public: true -permissions_015: - action: destroy - id: 15 - description: button_delete - controller: issue_categories - mail_enabled: false - mail_option: false - sort: 422 - is_public: false -permissions_004: - action: settings - id: 4 - description: label_settings - controller: projects - mail_enabled: false - mail_option: false - sort: 150 - is_public: false -permissions_060: - action: search - id: 61 - description: label_search - controller: projects - mail_enabled: false - mail_option: false - sort: 130 - is_public: true -permissions_049: - action: gantt - id: 49 - description: label_gantt - controller: projects - mail_enabled: false - mail_option: false - sort: 166 - is_public: true -permissions_038: - action: destroy_attachment - id: 38 - description: label_attachment_delete - controller: documents - mail_enabled: false - mail_option: false - sort: 1224 - is_public: false -permissions_027: - action: show - id: 27 - description: button_view - controller: news - mail_enabled: false - mail_option: false - sort: 1101 - is_public: true -permissions_016: - action: list_issues - id: 16 - description: button_list - controller: projects - mail_enabled: false - mail_option: false - sort: 1000 - is_public: true -permissions_005: - action: edit - id: 5 - description: button_edit - controller: projects - mail_enabled: false - mail_option: false - sort: 151 - is_public: false -permissions_061: - action: search - id: 62 - description: label_search - controller: projects - mail_enabled: false - mail_option: false - sort: 130 - is_public: true -permissions_062: - action: roadmap - id: 63 - description: label_roadmap - controller: projects - mail_enabled: false - mail_option: false - sort: 107 - is_public: true -permissions_050: - action: history - id: 50 - description: label_history - controller: issues - mail_enabled: false - mail_option: false - sort: 1006 - is_public: true -permissions_039: - action: list_files - id: 39 - description: button_list - controller: projects - mail_enabled: false - mail_option: false - sort: 1300 - is_public: true -permissions_028: - action: add_news - id: 28 - description: button_add - controller: projects - mail_enabled: false - mail_option: false - sort: 1120 - is_public: false -permissions_017: - action: export_issues_csv - id: 17 - description: label_export_csv - controller: projects - mail_enabled: false - mail_option: false - sort: 1001 - is_public: true -permissions_006: - action: list_members - id: 6 - description: button_list - controller: projects - mail_enabled: false - mail_option: false - sort: 200 - is_public: true -permissions_051: - action: add_comment - id: 51 - description: label_comment_add - controller: news - mail_enabled: false - mail_option: false - sort: 1130 - is_public: false -permissions_040: - action: download - id: 40 - description: button_download - controller: versions - mail_enabled: false - mail_option: false - sort: 1301 - is_public: true -permissions_029: - action: edit - id: 29 - description: button_edit - controller: news - mail_enabled: false - mail_option: false - sort: 1121 - is_public: false -permissions_018: - action: show - id: 18 - description: button_view - controller: issues - mail_enabled: false - mail_option: false - sort: 1005 - is_public: true -permissions_007: - action: add_member - id: 7 - description: button_add - controller: projects - mail_enabled: false - mail_option: false - sort: 220 - is_public: false diff --git a/test/fixtures/permissions_roles.yml b/test/fixtures/permissions_roles.yml deleted file mode 100644 index a47d0af11037a00837bd9d4e05e125ff264a73fd..0000000000000000000000000000000000000000 --- a/test/fixtures/permissions_roles.yml +++ /dev/null @@ -1,163 +0,0 @@ ---- -permissions_roles_054: - role_id: 3 - permission_id: 44 -permissions_roles_043: - role_id: 2 - permission_id: 25 -permissions_roles_032: - role_id: 1 - permission_id: 42 -permissions_roles_021: - role_id: 1 - permission_id: 22 -permissions_roles_010: - role_id: 1 - permission_id: 4 -permissions_roles_044: - role_id: 3 - permission_id: 22 -permissions_roles_033: - role_id: 2 - permission_id: 22 -permissions_roles_022: - role_id: 1 - permission_id: 38 -permissions_roles_011: - role_id: 1 - permission_id: 20 -permissions_roles_045: - role_id: 1 - permission_id: 12 -permissions_roles_034: - role_id: 2 - permission_id: 44 -permissions_roles_023: - role_id: 2 - permission_id: 15 -permissions_roles_012: - role_id: 1 - permission_id: 36 -permissions_roles_001: - role_id: 1 - permission_id: 14 -permissions_roles_046: - role_id: 1 - permission_id: 29 -permissions_roles_035: - role_id: 1 - permission_id: 10 -permissions_roles_024: - role_id: 2 - permission_id: 42 -permissions_roles_013: - role_id: 2 - permission_id: 13 -permissions_roles_002: - role_id: 1 - permission_id: 34 -permissions_roles_047: - role_id: 2 - permission_id: 4 -permissions_roles_036: - role_id: 1 - permission_id: 25 -permissions_roles_025: - role_id: 1 - permission_id: 8 -permissions_roles_014: - role_id: 2 - permission_id: 38 -permissions_roles_003: - role_id: 2 - permission_id: 11 -permissions_roles_048: - role_id: 2 - permission_id: 34 -permissions_roles_037: - role_id: 1 - permission_id: 43 -permissions_roles_026: - role_id: 1 - permission_id: 23 -permissions_roles_015: - role_id: 1 - permission_id: 5 -permissions_roles_004: - role_id: 2 - permission_id: 36 -permissions_roles_049: - role_id: 3 - permission_id: 24 -permissions_roles_038: - role_id: 2 - permission_id: 24 -permissions_roles_027: - role_id: 1 - permission_id: 41 -permissions_roles_016: - role_id: 1 - permission_id: 21 -permissions_roles_005: - role_id: 1 - permission_id: 53 -permissions_roles_050: - role_id: 1 - permission_id: 13 -permissions_roles_039: - role_id: 3 - permission_id: 20 -permissions_roles_028: - role_id: 2 - permission_id: 20 -permissions_roles_017: - role_id: 1 - permission_id: 37 -permissions_roles_006: - role_id: 1 - permission_id: 15 -permissions_roles_051: - role_id: 1 - permission_id: 30 -permissions_roles_040: - role_id: 1 - permission_id: 11 -permissions_roles_029: - role_id: 2 - permission_id: 43 -permissions_roles_018: - role_id: 2 - permission_id: 14 -permissions_roles_007: - role_id: 1 - permission_id: 35 -permissions_roles_052: - role_id: 2 - permission_id: 10 -permissions_roles_041: - role_id: 1 - permission_id: 28 -permissions_roles_030: - role_id: 1 - permission_id: 9 -permissions_roles_019: - role_id: 2 - permission_id: 41 -permissions_roles_008: - role_id: 2 - permission_id: 12 -permissions_roles_053: - role_id: 2 - permission_id: 35 -permissions_roles_042: - role_id: 1 - permission_id: 44 -permissions_roles_031: - role_id: 1 - permission_id: 24 -permissions_roles_020: - role_id: 1 - permission_id: 7 -permissions_roles_009: - role_id: 2 - permission_id: 37 diff --git a/test/fixtures/roles.yml b/test/fixtures/roles.yml index 4fc9881b444b78fb6e753dc5b63bb24d3f1a3a65..29eaba3b994f3593d59e655ca48c20cc0c27901c 100644 --- a/test/fixtures/roles.yml +++ b/test/fixtures/roles.yml @@ -1,10 +1,161 @@ --- +roles_004: + name: Non member + id: 4 + builtin: 1 + permissions: | + --- + - :add_issues + - :edit_issues + - :manage_issue_relations + - :add_issue_notes + - :change_issue_status + - :move_issues + - :save_queries + - :view_gantt + - :view_calendar + - :log_time + - :view_time_entries + - :comment_news + - :view_documents + - :manage_documents + - :view_wiki_pages + - :edit_wiki_pages + - :add_messages + - :view_files + - :manage_files + - :browse_repository + - :view_changesets + + position: 5 +roles_005: + name: Anonymous + id: 5 + builtin: 2 + permissions: | + --- + - :view_gantt + - :view_calendar + - :view_time_entries + - :view_documents + - :view_wiki_pages + - :edit_wiki_pages + - :view_files + - :browse_repository + - :view_changesets + + position: 6 roles_001: name: Manager id: 1 + builtin: 0 + permissions: | + --- + - :edit_project + - :manage_members + - :manage_versions + - :manage_categories + - :add_issues + - :edit_issues + - :manage_issue_relations + - :add_issue_notes + - :change_issue_status + - :move_issues + - :delete_issues + - :manage_pulic_queries + - :save_queries + - :view_gantt + - :view_calendar + - :log_time + - :view_time_entries + - :manage_news + - :comment_news + - :view_documents + - :manage_documents + - :view_wiki_pages + - :edit_wiki_pages + - :delete_wiki_pages + - :add_messages + - :manage_boards + - :view_files + - :manage_files + - :browse_repository + - :view_changesets + + position: 2 roles_002: name: Developer id: 2 + builtin: 0 + permissions: | + --- + - :edit_project + - :manage_members + - :manage_versions + - :manage_categories + - :add_issues + - :edit_issues + - :manage_issue_relations + - :add_issue_notes + - :change_issue_status + - :move_issues + - :delete_issues + - :manage_pulic_queries + - :save_queries + - :view_gantt + - :view_calendar + - :log_time + - :view_time_entries + - :manage_news + - :comment_news + - :view_documents + - :manage_documents + - :view_wiki_pages + - :edit_wiki_pages + - :delete_wiki_pages + - :add_messages + - :manage_boards + - :view_files + - :manage_files + - :browse_repository + - :view_changesets + + position: 3 roles_003: name: Reporter id: 3 + builtin: 0 + permissions: | + --- + - :edit_project + - :manage_members + - :manage_versions + - :manage_categories + - :add_issues + - :edit_issues + - :manage_issue_relations + - :add_issue_notes + - :change_issue_status + - :move_issues + - :delete_issues + - :manage_pulic_queries + - :save_queries + - :view_gantt + - :view_calendar + - :log_time + - :view_time_entries + - :manage_news + - :comment_news + - :view_documents + - :manage_documents + - :view_wiki_pages + - :edit_wiki_pages + - :delete_wiki_pages + - :add_messages + - :manage_boards + - :view_files + - :manage_files + - :browse_repository + - :view_changesets + + position: 4 diff --git a/test/functional/feeds_controller_test.rb b/test/functional/feeds_controller_test.rb index 279b2c1a74a42f64a8ecba66a9e691185f49ddc2..c41fa2c60d129ca3ce19519630561de6cf7bf318 100644 --- a/test/functional/feeds_controller_test.rb +++ b/test/functional/feeds_controller_test.rb @@ -58,7 +58,7 @@ class FeedsControllerTest < Test::Unit::TestCase def test_rss_key user = User.find(2) - key = user.get_or_create_rss_key.value + key = user.rss_key get :news, :project_id => 2, :key => key assert_response :success diff --git a/test/functional/projects_controller_test.rb b/test/functional/projects_controller_test.rb index 0e1ff121b109c37a83029ff70a6852274e6f1435..def7b7579751413a797d6d721a26f517eaf639a3 100644 --- a/test/functional/projects_controller_test.rb +++ b/test/functional/projects_controller_test.rb @@ -22,7 +22,7 @@ require 'projects_controller' class ProjectsController; def rescue_action(e) raise e end; end class ProjectsControllerTest < Test::Unit::TestCase - fixtures :projects, :permissions + fixtures :projects, :users, :roles def setup @controller = ProjectsController.new @@ -50,13 +50,6 @@ class ProjectsControllerTest < Test::Unit::TestCase assert_not_nil assigns(:project) end - def test_list_members - get :list_members, :id => 1 - assert_response :success - assert_template 'list_members' - assert_not_nil assigns(:members) - end - def test_list_documents get :list_documents, :id => 1 assert_response :success diff --git a/test/functional/search_controller_test.rb b/test/functional/search_controller_test.rb index 8fa2e089063dd7de734b784defa3de9b5b316ecc..69e78ac62d7e530451ed348a5b44be350a4993c8 100644 --- a/test/functional/search_controller_test.rb +++ b/test/functional/search_controller_test.rb @@ -11,6 +11,7 @@ class SearchControllerTest < Test::Unit::TestCase @controller = SearchController.new @request = ActionController::TestRequest.new @response = ActionController::TestResponse.new + User.current = nil end def test_search_for_projects diff --git a/test/integration/issues_test.rb b/test/integration/issues_test.rb index 0583b98a82b0dd0ff167553c48f31b5b61a2bb25..668bcbd1805642c67f9960d460f723e4e32e07d5 100644 --- a/test/integration/issues_test.rb +++ b/test/integration/issues_test.rb @@ -1,7 +1,7 @@ require "#{File.dirname(__FILE__)}/../test_helper" class IssuesTest < ActionController::IntegrationTest - fixtures :projects, :users, :trackers, :issue_statuses, :issues, :permissions, :permissions_roles, :enumerations + fixtures :projects, :users, :trackers, :issue_statuses, :issues, :enumerations # create an issue def test_add_issue @@ -38,7 +38,7 @@ class IssuesTest < ActionController::IntegrationTest def test_issue_attachements log_user('jsmith', 'jsmith') - post "issues/add_attachment/1", { 'attachments[]' => ActionController::TestUploadedFile.new(Test::Unit::TestCase.fixture_path + '/files/testfile.txt', 'text/plain') } + post "issues/add_note/1", { :notes => 'Some notes', 'attachments[]' => ActionController::TestUploadedFile.new(Test::Unit::TestCase.fixture_path + '/files/testfile.txt', 'text/plain') } assert_redirected_to "issues/show/1" # make sure attachment was saved diff --git a/test/integration/projects_test.rb b/test/integration/projects_test.rb index 69b16cf85345780701f1f75e66ee0e701242d675..e56bee484a1eec737a63bcd27cf09222c6928e7e 100644 --- a/test/integration/projects_test.rb +++ b/test/integration/projects_test.rb @@ -31,9 +31,9 @@ class ProjectsTest < ActionController::IntegrationTest assert !Project.find(1).active? get "projects/show", :id => 1 - assert_response :missing + assert_response 403 get "projects/show", :id => subproject.id - assert_response :missing + assert_response 403 post "projects/unarchive", :id => 1 assert_redirected_to "admin/projects" diff --git a/test/unit/mail_handler_test.rb b/test/unit/mail_handler_test.rb index 8cac2d8b91c337e70ca69c64fdca79748f6148c7..833506a16fa2f2f1293fbc51464a5d362878d3d9 100644 --- a/test/unit/mail_handler_test.rb +++ b/test/unit/mail_handler_test.rb @@ -18,7 +18,7 @@ require File.dirname(__FILE__) + '/../test_helper' class MailHandlerTest < Test::Unit::TestCase - fixtures :users, :projects, :roles, :members, :permissions, :issues, :permissions_roles, :trackers, :enumerations + fixtures :users, :projects, :roles, :members, :issues, :trackers, :enumerations FIXTURES_PATH = File.dirname(__FILE__) + '/../fixtures' CHARSET = "utf-8" diff --git a/test/unit/user_test.rb b/test/unit/user_test.rb index 66cd7247229635f9eedbf9378ebfbf44cfd39d98..52776c62f5c8117d22b16ad3e02a7a60b5c67f7e 100644 --- a/test/unit/user_test.rb +++ b/test/unit/user_test.rb @@ -88,16 +88,12 @@ class UserTest < Test::Unit::TestCase end def test_rss_key - assert_nil @jsmith.rss_key - key = @jsmith.get_or_create_rss_key - assert_kind_of Token, key - assert_equal 40, key.value.length + assert_nil @jsmith.rss_token + key = @jsmith.rss_key + assert_equal 40, key.length @jsmith.reload - assert_equal key.value, @jsmith.get_or_create_rss_key.value - - @jsmith.reload - assert_equal key.value, @jsmith.rss_key.value + assert_equal key, @jsmith.rss_key end def test_role_for_project @@ -107,6 +103,6 @@ class UserTest < Test::Unit::TestCase assert_equal "Manager", role.name # user with no role - assert_nil @dlopper.role_for_project(Project.find(2)) + assert !@dlopper.role_for_project(Project.find(2)).member? end end