diff options
author | Jean-Philippe Lang <jp_lang@yahoo.fr> | 2018-12-16 16:28:22 +0000 |
---|---|---|
committer | Jean-Philippe Lang <jp_lang@yahoo.fr> | 2018-12-16 16:28:22 +0000 |
commit | 2fdbcd35dd8cc2f6b98340825a57afd24ff89670 (patch) | |
tree | bf05ccb4c0ad1109229cea2b5309fab4c27f8e51 /app | |
parent | 537f162f27d91ad99fadd4be74c878adf33f0583 (diff) | |
download | redmine-2fdbcd35dd8cc2f6b98340825a57afd24ff89670.tar.gz redmine-2fdbcd35dd8cc2f6b98340825a57afd24ff89670.zip |
Adds a permission to log time for another user (#3848).
Patch by Marius BALTEANU.
git-svn-id: http://svn.redmine.org/redmine/trunk@17755 e93f8b46-1217-0410-a6f0-8f06a7374b81
Diffstat (limited to 'app')
-rw-r--r-- | app/controllers/timelog_controller.rb | 14 | ||||
-rw-r--r-- | app/helpers/timelog_helper.rb | 5 | ||||
-rw-r--r-- | app/models/time_entry.rb | 21 | ||||
-rw-r--r-- | app/models/time_entry_query.rb | 5 | ||||
-rw-r--r-- | app/views/timelog/_form.html.erb | 3 |
5 files changed, 43 insertions, 5 deletions
diff --git a/app/controllers/timelog_controller.rb b/app/controllers/timelog_controller.rb index 47dc7c4f5..f0988fad9 100644 --- a/app/controllers/timelog_controller.rb +++ b/app/controllers/timelog_controller.rb @@ -26,6 +26,8 @@ class TimelogController < ApplicationController before_action :find_optional_issue, :only => [:new, :create] before_action :find_optional_project, :only => [:index, :report] + before_action :authorize_logging_time_for_other_users, :only => [:create, :update] + accept_rss_auth :index accept_api_auth :index, :show, :create, :update, :destroy @@ -90,12 +92,12 @@ class TimelogController < ApplicationController end def new - @time_entry ||= TimeEntry.new(:project => @project, :issue => @issue, :user => User.current, :spent_on => User.current.today) + @time_entry ||= TimeEntry.new(:project => @project, :issue => @issue, :author => User.current, :spent_on => User.current.today) @time_entry.safe_attributes = params[:time_entry] end def create - @time_entry ||= TimeEntry.new(:project => @project, :issue => @issue, :user => User.current, :spent_on => User.current.today) + @time_entry ||= TimeEntry.new(:project => @project, :issue => @issue, :author => User.current, :user => User.current, :spent_on => User.current.today) @time_entry.safe_attributes = params[:time_entry] if @time_entry.project && !User.current.allowed_to?(:log_time, @time_entry.project) render_403 @@ -145,7 +147,6 @@ class TimelogController < ApplicationController def update @time_entry.safe_attributes = params[:time_entry] - call_hook(:controller_timelog_edit_before_save, { :params => params, :time_entry => @time_entry }) if @time_entry.save @@ -254,6 +255,13 @@ private end end + def authorize_logging_time_for_other_users + if !User.current.allowed_to?(:log_time_for_other_users, @project) && params['time_entry'].present? && params['time_entry']['user_id'].present? && params['time_entry']['user_id'].to_i != User.current.id + render_error :message => l(:error_not_allowed_to_log_time_for_other_users), :status => 403 + return false + end + end + def find_time_entries @time_entries = TimeEntry.where(:id => params[:id] || params[:ids]). preload(:project => :time_entry_activities). diff --git a/app/helpers/timelog_helper.rb b/app/helpers/timelog_helper.rb index 9cdfa9c13..cb79a545a 100644 --- a/app/helpers/timelog_helper.rb +++ b/app/helpers/timelog_helper.rb @@ -42,6 +42,11 @@ module TimelogHelper collection end + def user_collection_for_select_options(time_entry) + collection = time_entry.assignable_users + principals_options_for_select(collection, time_entry.user_id) + end + def select_hours(data, criteria, value) if value.to_s.empty? data.select {|row| row[criteria].blank? } diff --git a/app/models/time_entry.rb b/app/models/time_entry.rb index 095653266..f0c7b7786 100644 --- a/app/models/time_entry.rb +++ b/app/models/time_entry.rb @@ -22,6 +22,7 @@ class TimeEntry < ActiveRecord::Base belongs_to :project belongs_to :issue belongs_to :user + belongs_to :author, :class_name => 'User' belongs_to :activity, :class_name => 'TimeEntryActivity' acts_as_customizable @@ -39,13 +40,14 @@ class TimeEntry < ActiveRecord::Base :author_key => :user_id, :scope => joins(:project).preload(:project) - validates_presence_of :user_id, :activity_id, :project_id, :hours, :spent_on + validates_presence_of :author_id, :user_id, :activity_id, :project_id, :hours, :spent_on validates_presence_of :issue_id, :if => lambda { Setting.timelog_required_fields.include?('issue_id') } validates_presence_of :comments, :if => lambda { Setting.timelog_required_fields.include?('comments') } validates_numericality_of :hours, :allow_nil => true, :message => :invalid validates_length_of :comments, :maximum => 1024, :allow_nil => true validates :spent_on, :date => true before_validation :set_project_if_nil + before_validation :set_author_if_nil validate :validate_time_entry scope :visible, lambda {|*args| @@ -60,7 +62,7 @@ class TimeEntry < ActiveRecord::Base where("#{Issue.table_name}.root_id = #{issue.root_id} AND #{Issue.table_name}.lft >= #{issue.lft} AND #{Issue.table_name}.rgt <= #{issue.rgt}") } - safe_attributes 'hours', 'comments', 'project_id', 'issue_id', 'activity_id', 'spent_on', 'custom_field_values', 'custom_fields' + safe_attributes 'user_id', 'hours', 'comments', 'project_id', 'issue_id', 'activity_id', 'spent_on', 'custom_field_values', 'custom_fields' # Returns a SQL conditions string used to find all time entries visible by the specified user def self.visible_condition(user, options={}) @@ -119,6 +121,10 @@ class TimeEntry < ActiveRecord::Base self.project = issue.project if issue && project.nil? end + def set_author_if_nil + self.author = User.current if author.nil? + end + def validate_time_entry if hours errors.add :hours, :invalid if hours < 0 @@ -134,6 +140,7 @@ class TimeEntry < ActiveRecord::Base end end errors.add :project_id, :invalid if project.nil? + errors.add :user_id, :invalid if (user_id != author_id && !self.assignable_users.map(&:id).include?(user_id)) errors.add :issue_id, :invalid if (issue_id && !issue) || (issue && project!=issue.project) || @invalid_issue_id errors.add :activity_id, :inclusion if activity_id_changed? && project && !project.activities.include?(activity) if spent_on_changed? && user @@ -180,6 +187,16 @@ class TimeEntry < ActiveRecord::Base editable_custom_field_values(user).map(&:custom_field).uniq end + def assignable_users + users = [] + if project + users = project.members.active.preload(:user) + users = users.map(&:user).select{ |u| u.allowed_to?(:log_time, project) } + end + users << User.current if User.current.logged? && !users.include?(User.current) + users + end + private # Returns the hours that were logged in other time entries for the same user and the same day diff --git a/app/models/time_entry_query.rb b/app/models/time_entry_query.rb index a612ba7c5..4073b3d1a 100644 --- a/app/models/time_entry_query.rb +++ b/app/models/time_entry_query.rb @@ -25,6 +25,7 @@ class TimeEntryQuery < Query QueryColumn.new(:spent_on, :sortable => ["#{TimeEntry.table_name}.spent_on", "#{TimeEntry.table_name}.created_on"], :default_order => 'desc', :groupable => true), QueryColumn.new(:created_on, :sortable => "#{TimeEntry.table_name}.created_on", :default_order => 'desc'), QueryColumn.new(:tweek, :sortable => ["#{TimeEntry.table_name}.spent_on", "#{TimeEntry.table_name}.created_on"], :caption => :label_week), + QueryColumn.new(:author, :sortable => lambda {User.fields_for_order_statement}), QueryColumn.new(:user, :sortable => lambda {User.fields_for_order_statement}, :groupable => true), QueryColumn.new(:activity, :sortable => "#{TimeEntryActivity.table_name}.position", :groupable => true), QueryColumn.new(:issue, :sortable => "#{Issue.table_name}.id"), @@ -75,6 +76,10 @@ class TimeEntryQuery < Query :type => :list_optional, :values => lambda { author_values } ) + add_available_filter("author_id", + :type => :list_optional, :values => lambda { author_values } + ) + activities = (project ? project.activities : TimeEntryActivity.shared) add_available_filter("activity_id", :type => :list, :values => activities.map {|a| [a.name, a.id.to_s]} diff --git a/app/views/timelog/_form.html.erb b/app/views/timelog/_form.html.erb index aa62ffc78..691da9ed1 100644 --- a/app/views/timelog/_form.html.erb +++ b/app/views/timelog/_form.html.erb @@ -16,6 +16,9 @@ <%= link_to_issue(@time_entry.issue) if @time_entry.issue.try(:visible?) %> </span> </p> + <% if User.current.allowed_to?(:log_time_for_other_users, @project) %> + <p><%= f.select :user_id, user_collection_for_select_options(@time_entry), :required => true %></p> + <% end %> <p><%= f.date_field :spent_on, :size => 10, :required => true %><%= calendar_for('time_entry_spent_on') %></p> <p><%= f.hours_field :hours, :size => 6, :required => true %></p> <p><%= f.text_field :comments, :size => 100, :maxlength => 1024, :required => Setting.timelog_required_fields.include?('comments') %></p> |