summaryrefslogtreecommitdiffstats
path: root/app
diff options
context:
space:
mode:
authorJean-Philippe Lang <jp_lang@yahoo.fr>2018-12-16 16:28:22 +0000
committerJean-Philippe Lang <jp_lang@yahoo.fr>2018-12-16 16:28:22 +0000
commit2fdbcd35dd8cc2f6b98340825a57afd24ff89670 (patch)
treebf05ccb4c0ad1109229cea2b5309fab4c27f8e51 /app
parent537f162f27d91ad99fadd4be74c878adf33f0583 (diff)
downloadredmine-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.rb14
-rw-r--r--app/helpers/timelog_helper.rb5
-rw-r--r--app/models/time_entry.rb21
-rw-r--r--app/models/time_entry_query.rb5
-rw-r--r--app/views/timelog/_form.html.erb3
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>