UpdateWebhook updates a webhook.
(ctx context.Context, req *connect.Request[v1pb.UpdateWebhookRequest])
| 802 | |
| 803 | // UpdateWebhook updates a webhook. |
| 804 | func (s *ProjectService) UpdateWebhook(ctx context.Context, req *connect.Request[v1pb.UpdateWebhookRequest]) (*connect.Response[v1pb.Project], error) { |
| 805 | projectID, webhookID, err := common.GetProjectIDWebhookID(req.Msg.Webhook.Name) |
| 806 | if err != nil { |
| 807 | return nil, connect.NewError(connect.CodeInvalidArgument, err) |
| 808 | } |
| 809 | |
| 810 | workspaceID := common.GetWorkspaceIDFromContext(ctx) |
| 811 | project, err := s.store.GetProject(ctx, &store.FindProjectMessage{ |
| 812 | Workspace: workspaceID, |
| 813 | ResourceID: &projectID, |
| 814 | }) |
| 815 | if err != nil { |
| 816 | return nil, connect.NewError(connect.CodeInternal, err) |
| 817 | } |
| 818 | if project == nil { |
| 819 | return nil, connect.NewError(connect.CodeNotFound, errors.Errorf("project %q not found", projectID)) |
| 820 | } |
| 821 | if project.Deleted { |
| 822 | return nil, connect.NewError(connect.CodeNotFound, errors.Errorf("project %q has been deleted", projectID)) |
| 823 | } |
| 824 | |
| 825 | if _, err := utils.GetEffectiveExternalURL(ctx, s.store, s.profile, common.GetWorkspaceIDFromContext(ctx)); err != nil { |
| 826 | return nil, err |
| 827 | } |
| 828 | |
| 829 | webhook, err := s.store.GetProjectWebhook(ctx, &store.FindProjectWebhookMessage{ |
| 830 | ProjectID: &project.ResourceID, |
| 831 | ResourceID: &webhookID, |
| 832 | }) |
| 833 | if err != nil { |
| 834 | return nil, connect.NewError(connect.CodeInternal, err) |
| 835 | } |
| 836 | if webhook == nil { |
| 837 | if req.Msg.AllowMissing { |
| 838 | // When allow_missing is true and webhook doesn't exist, create a new one |
| 839 | // Call AddWebhook instead since we're creating a new webhook |
| 840 | return s.AddWebhook(ctx, connect.NewRequest(&v1pb.AddWebhookRequest{ |
| 841 | Project: fmt.Sprintf("projects/%s", project.ResourceID), |
| 842 | Webhook: req.Msg.Webhook, |
| 843 | })) |
| 844 | } |
| 845 | return nil, connect.NewError(connect.CodeNotFound, errors.Errorf("webhook %q not found", req.Msg.Webhook.Url)) |
| 846 | } |
| 847 | |
| 848 | // Start with existing webhook payload |
| 849 | // nolint:revive |
| 850 | updatedPayload := proto.Clone(webhook.Payload).(*storepb.ProjectWebhook) |
| 851 | |
| 852 | for _, path := range req.Msg.UpdateMask.Paths { |
| 853 | switch path { |
| 854 | case "type": |
| 855 | return nil, connect.NewError(connect.CodeInvalidArgument, errors.Errorf("type cannot be updated")) |
| 856 | case "title": |
| 857 | updatedPayload.Title = req.Msg.Webhook.Title |
| 858 | case "url": |
| 859 | updatedPayload.Url = req.Msg.Webhook.Url |
| 860 | // Validate webhook URL against allowed domains |
| 861 | if err := webhookplugin.ValidateWebhookURL(updatedPayload.Type, updatedPayload.Url); err != nil { |
nothing calls this directly
no test coverage detected