1
0
mirror of https://github.com/meineerde/redmine.git synced 2026-02-01 03:57:15 +00:00

Adds webhook events for time entries (#29664).

git-svn-id: https://svn.redmine.org/redmine/trunk@24202 e93f8b46-1217-0410-a6f0-8f06a7374b81
This commit is contained in:
Marius Balteanu 2025-12-06 12:38:39 +00:00
parent 4898e01652
commit 6bc29c40fd
4 changed files with 61 additions and 2 deletions

View File

@ -58,6 +58,10 @@ class TimeEntry < ApplicationRecord
before_validation :set_author_if_nil
validate :validate_time_entry
after_create_commit ->{ Webhook.trigger('time_entry.created', self) }
after_update_commit ->{ Webhook.trigger('time_entry.updated', self) }
after_destroy_commit ->{ Webhook.trigger('time_entry.deleted', self) }
scope :visible, (lambda do |*args|
joins(:project).
where(TimeEntry.visible_condition(args.shift || User.current, *args))

View File

@ -29,7 +29,8 @@ class WebhookPayload
EVENTS = {
issue: %w[created updated deleted],
wiki_page: %w[created updated deleted]
wiki_page: %w[created updated deleted],
time_entry: %w[created updated deleted],
}
def to_h
@ -110,6 +111,25 @@ class WebhookPayload
}
end
def time_entry_payload(action)
time_entry = object
ts = case action
when 'created'
time_entry.created_on
when 'deleted'
Time.now
else
time_entry.updated_on
end
{
type: event,
timestamp: ts.iso8601,
data: {
time_entry: ApiRenderer.new("app/views/timelog/show.api.rsb", user).to_h(time_entry: time_entry)
}
}
end
# given a path to an API template (relative to RAILS_ROOT), renders it and returns the resulting hash
class ApiRenderer
include ApplicationHelper

View File

@ -1193,8 +1193,12 @@ en:
webhook_events_wiki_page_created: Wiki page created
webhook_events_wiki_page_updated: Wiki page updated
webhook_events_wiki_page_deleted: Wiki page deleted
webhook_events_time_entry: Time entries
webhook_events_time_entry_created: Time entry created
webhook_events_time_entry_updated: Time entry updated
webhook_events_time_entry_deleted: Time entry deleted
webhook_url_info: Redmine will send a POST request to this URL whenever one of the selected events occurs in one of the selected projects.
webhook_secret_info_html: If provided, Redmine will use this to create a hash signature that is sent with each delivery as the value of the X-Redmine-Signature-256 header.
webhook_secret_info_html: If provided, Redmine will use this to create a hash signature that is sent with each delivery as the value of the X-Redmine-Signature-256 header.
button_login: Login
button_submit: Submit

View File

@ -94,4 +94,35 @@ class WebhookPayloadTest < ActiveSupport::TestCase
assert_equal 'wiki_page.deleted', h[:type]
assert_equal 'Test_Page', h.dig(:data, :wiki_page, :title)
end
test "time entry created payload should contain time entry details" do
time_entry = TimeEntry.generate!
p = WebhookPayload.new('time_entry.created', time_entry, @dlopper)
assert h = p.to_h
assert_equal 'time_entry.created', h[:type]
assert_equal time_entry.hours, h.dig(:data, :time_entry, :hours)
end
test "time entry updated payload should contain updated timestamp" do
time_entry = TimeEntry.first
time_entry.hours = 2.5
time_entry.save!
p = WebhookPayload.new('time_entry.updated', time_entry, @dlopper)
h = p.to_h
assert_equal 'time_entry.updated', h[:type]
assert_equal 2.5, h.dig(:data, :time_entry, :hours)
end
test "time entry deleted payload should contain basic info" do
time_entry = TimeEntry.first
time_entry.destroy
p = WebhookPayload.new('time_entry.deleted', time_entry, @dlopper)
h = p.to_h
assert_equal 'time_entry.deleted', h[:type]
assert_equal 4.25, h.dig(:data, :time_entry, :hours)
end
end