Feature #13244 » 0001-Setting-to-restrict-adding-editing-deleting-log-time.patch
app/models/time_entry.rb | ||
---|---|---|
159 | 159 |
errors.add :activity_id, :inclusion if activity_id_changed? && project && !project.activities.include?(activity) |
160 | 160 |
if spent_on_changed? && user |
161 | 161 |
errors.add :base, I18n.t(:error_spent_on_future_date) if !Setting.timelog_accept_future_dates? && (spent_on > user.today) |
162 |
errors.add :base, I18n.t(:error_spent_on_old_date, :days => Setting.timelog_lock_days_older_than.to_i) if date_is_locked_for_user? |
|
162 | 163 |
end |
163 | 164 |
end |
164 | 165 | |
... | ... | |
186 | 187 | |
187 | 188 |
# Returns true if the time entry can be edited by usr, otherwise false |
188 | 189 |
def editable_by?(usr) |
189 |
visible?(usr) && ( |
|
190 |
visible?(usr) && !date_is_locked_for_user? && (
|
|
190 | 191 |
(usr == user && usr.allowed_to?(:edit_own_time_entries, project)) || usr.allowed_to?(:edit_time_entries, project) |
191 | 192 |
) |
192 | 193 |
end |
... | ... | |
231 | 232 |
0.0 |
232 | 233 |
end |
233 | 234 |
end |
235 | ||
236 |
# Returns true if time entry is logged on a locked date and the user doesn't have the permission |
|
237 |
# to manage time entries on locked dates |
|
238 |
def date_is_locked_for_user? |
|
239 |
if user && spent_on |
|
240 |
number_of_days = Setting.timelog_lock_days_older_than.to_i |
|
241 |
((user.today - spent_on).to_i > number_of_days) && !User.current.allowed_to?(:manage_time_entries_on_locked_dates, self.project) |
|
242 |
end |
|
243 |
end |
|
234 | 244 |
end |
app/views/settings/_timelog.html.erb | ||
---|---|---|
9 | 9 |
<p><%= setting_check_box :timelog_accept_0_hours %></p> |
10 | 10 | |
11 | 11 |
<p><%= setting_check_box :timelog_accept_future_dates %></p> |
12 | ||
13 |
<p><%= setting_text_field :timelog_lock_days_older_than, :size => 6 %> <%= l(:label_day_plural) %></p> |
|
14 | ||
12 | 15 |
</div> |
13 | 16 | |
14 | 17 |
<fieldset class="box"> |
config/locales/en.yml | ||
---|---|---|
233 | 233 |
error_can_not_delete_auth_source: "This authentication mode is in use and cannot be deleted." |
234 | 234 |
error_spent_on_future_date: "Cannot log time on a future date" |
235 | 235 |
error_not_allowed_to_log_time_for_other_users: "You are not allowed to log time for other users" |
236 |
error_spent_on_old_date: "Cannot log time on a date older than %{days} days" |
|
236 | 237 | |
237 | 238 |
mail_subject_lost_password: "Your %{value} password" |
238 | 239 |
mail_body_lost_password: 'To change your password, click on the following link:' |
... | ... | |
494 | 495 |
setting_timelog_accept_future_dates: Accept time logs on future dates |
495 | 496 |
setting_show_status_changes_in_mail_subject: Show status changes in issue mail notifications subject |
496 | 497 |
setting_project_list_defaults: Projects list defaults |
498 |
setting_timelog_lock_days_older_than: Lock (add/edit/delete time logs) dates older than |
|
497 | 499 | |
498 | 500 |
permission_add_project: Create project |
499 | 501 |
permission_add_subprojects: Create subprojects |
config/settings.yml | ||
---|---|---|
337 | 337 |
default: 1 |
338 | 338 |
show_status_changes_in_mail_subject: |
339 | 339 |
default: 1 |
340 |
timelog_lock_days_older_than: |
|
341 |
format: int |
|
342 |
default: 9999 |
lib/redmine.rb | ||
---|---|---|
133 | 133 |
map.permission :manage_project_activities, {:projects => :settings, :project_enumerations => [:update, :destroy]}, :require => :member |
134 | 134 |
map.permission :log_time_for_other_users, :require => :member |
135 | 135 |
map.permission :import_time_entries, {} |
136 |
map.permission :manage_time_entries_on_locked_dates, {}, :require => :loggedin |
|
137 |
map.permission :manage_project_activities, {:project_enumerations => [:update, :destroy]}, :require => :member |
|
136 | 138 |
end |
137 | 139 | |
138 | 140 |
map.project_module :news do |map| |
test/fixtures/roles.yml | ||
---|---|---|
37 | 37 |
- :edit_time_entries |
38 | 38 |
- :delete_time_entries |
39 | 39 |
- :import_time_entries |
40 |
- :manage_time_entries_on_locked_dates |
|
40 | 41 |
- :view_news |
41 | 42 |
- :manage_news |
42 | 43 |
- :comment_news |
... | ... | |
95 | 96 |
- :log_time |
96 | 97 |
- :view_time_entries |
97 | 98 |
- :edit_own_time_entries |
99 |
- :manage_time_entries_on_locked_dates |
|
98 | 100 |
- :view_news |
99 | 101 |
- :manage_news |
100 | 102 |
- :comment_news |
... | ... | |
141 | 143 |
- :view_calendar |
142 | 144 |
- :log_time |
143 | 145 |
- :view_time_entries |
146 |
- :manage_time_entries_on_locked_dates |
|
144 | 147 |
- :view_news |
145 | 148 |
- :manage_news |
146 | 149 |
- :comment_news |
... | ... | |
179 | 182 |
- :view_calendar |
180 | 183 |
- :log_time |
181 | 184 |
- :view_time_entries |
185 |
- :manage_time_entries_on_locked_dates |
|
182 | 186 |
- :view_news |
183 | 187 |
- :comment_news |
184 | 188 |
- :view_documents |
... | ... | |
206 | 210 |
- :view_gantt |
207 | 211 |
- :view_calendar |
208 | 212 |
- :view_time_entries |
213 |
- :manage_time_entries_on_locked_dates |
|
209 | 214 |
- :view_news |
210 | 215 |
- :view_documents |
211 | 216 |
- :view_wiki_pages |
test/unit/time_entry_test.rb | ||
---|---|---|
127 | 127 | |
128 | 128 |
def test_should_accept_future_dates |
129 | 129 |
entry = TimeEntry.generate |
130 |
entry.spent_on = Date.tomorrow |
|
130 | 131 |
entry.spent_on = User.current.today + 1 |
131 | 132 | |
132 | 133 |
assert entry.save |
... | ... | |
135 | 136 |
def test_should_not_accept_future_dates_if_disabled |
136 | 137 |
with_settings :timelog_accept_future_dates => '0' do |
137 | 138 |
entry = TimeEntry.generate |
139 |
entry.spent_on = Date.tomorrow |
|
138 | 140 |
entry.spent_on = User.current.today + 1 |
139 | 141 | |
140 | 142 |
assert !entry.save |
... | ... | |
142 | 144 |
end |
143 | 145 |
end |
144 | 146 | |
147 |
def test_should_allow_time_entries_on_locked_dates_for_users_with_permission |
|
148 |
User.current = User.find(2) |
|
149 | ||
150 |
with_settings :timelog_lock_days_older_than => '5' do |
|
151 |
entry = TimeEntry.generate(:project => Project.find(1)) |
|
152 |
entry.spent_on = Date.today - 6 |
|
153 | ||
154 |
assert entry.save |
|
155 |
end |
|
156 |
end |
|
157 | ||
158 |
def test_should_not_allow_time_entries_on_locked_dates_for_users_without_permission |
|
159 |
User.current = User.find(2) |
|
160 |
Role.find(1).remove_permission!(:manage_time_entries_on_locked_dates) |
|
161 | ||
162 |
with_settings :timelog_lock_days_older_than => '5' do |
|
163 |
entry = TimeEntry.generate(:project => Project.find(1)) |
|
164 |
entry.spent_on = Date.today - 6 |
|
165 | ||
166 |
assert !entry.save |
|
167 |
assert entry.errors[:base].present? |
|
168 |
end |
|
169 |
end |
|
170 | ||
171 |
def test_editable_by_should_return_true_for_time_entry_on_locked_date_and_user_with_permission |
|
172 |
user = User.find(2) |
|
173 |
User.current = user |
|
174 |
time_entry = TimeEntry.find(1) |
|
175 | ||
176 |
with_settings :timelog_lock_days_older_than => '5' do |
|
177 |
assert time_entry.editable_by?(user) |
|
178 |
end |
|
179 |
end |
|
180 | ||
181 |
def test_editable_by_should_return_false_for_time_entry_on_locked_date_and_user_without_permission |
|
182 |
user = User.find(2) |
|
183 |
User.current = user |
|
184 |
Role.find(1).remove_permission!(:manage_time_entries_on_locked_dates) |
|
185 |
time_entry = TimeEntry.find(1) |
|
186 | ||
187 |
with_settings :timelog_lock_days_older_than => '5' do |
|
188 |
assert !time_entry.editable_by?(user) |
|
189 |
end |
|
190 |
end |
|
191 | ||
145 | 192 |
def test_spent_on_with_blank |
146 | 193 |
c = TimeEntry.new |
147 | 194 |
c.spent_on = '' |