MCPcopy Create free account
hub / github.com/bytebase/bytebase / ApproveIssue

Method ApproveIssue

backend/api/v1/issue_service.go:580–685  ·  view source on GitHub ↗

ApproveIssue approves the approval flow of the issue.

(ctx context.Context, req *connect.Request[v1pb.ApproveIssueRequest])

Source from the content-addressed store, hash-verified

578
579// ApproveIssue approves the approval flow of the issue.
580func (s *IssueService) ApproveIssue(ctx context.Context, req *connect.Request[v1pb.ApproveIssueRequest]) (*connect.Response[v1pb.Issue], error) {
581 issue, err := s.getIssueMessage(ctx, req.Msg.Name)
582 if err != nil {
583 return nil, err
584 }
585 project, err := s.store.GetProject(ctx, &store.FindProjectMessage{Workspace: common.GetWorkspaceIDFromContext(ctx), ResourceID: &issue.ProjectID})
586 if err != nil {
587 return nil, connect.NewError(connect.CodeInternal, errors.Wrapf(err, "failed to get project"))
588 }
589 if project == nil {
590 return nil, connect.NewError(connect.CodeNotFound, errors.Errorf("project %s not found", issue.ProjectID))
591 }
592 payload := issue.Payload
593 if payload.Approval == nil {
594 return nil, connect.NewError(connect.CodeInternal, errors.Errorf("issue payload approval is nil"))
595 }
596 if !payload.Approval.ApprovalFindingDone {
597 return nil, connect.NewError(connect.CodeFailedPrecondition, errors.Errorf("approval template finding is not done"))
598 }
599 if payload.Approval.ApprovalTemplate == nil {
600 return nil, connect.NewError(connect.CodeInternal, errors.New("approval template is required"))
601 }
602
603 rejectedRole := utils.FindRejectedRole(payload.Approval)
604 if rejectedRole != "" {
605 return nil, connect.NewError(connect.CodeInvalidArgument, errors.Errorf("cannot approve because the issue has been rejected"))
606 }
607
608 role := utils.FindNextPendingRole(payload.Approval)
609 if role == "" {
610 return nil, connect.NewError(connect.CodeInvalidArgument, errors.Errorf("the issue has been approved"))
611 }
612
613 user, ok := GetUserFromContext(ctx)
614 if !ok {
615 return nil, connect.NewError(connect.CodeInternal, errors.Errorf("user not found"))
616 }
617
618 canApprove := s.isUserReviewer(ctx, issue, role, user)
619 if !canApprove {
620 return nil, connect.NewError(connect.CodePermissionDenied, errors.Errorf("cannot approve because the user does not have the required permission"))
621 }
622
623 if !project.Setting.GetAllowSelfApproval() && issue.CreatorEmail == user.Email {
624 return nil, connect.NewError(connect.CodePermissionDenied, errors.Errorf("cannot approve because self-approval is not allowed for this project"))
625 }
626
627 payload.Approval.Approvers = append(payload.Approval.Approvers, &storepb.IssuePayloadApproval_Approver{
628 Status: storepb.IssuePayloadApproval_Approver_APPROVED,
629 Principal: common.FormatUserEmail(user.Email),
630 })
631
632 approved, err := utils.CheckApprovalApproved(payload.Approval)
633 if err != nil {
634 return nil, connect.NewError(connect.CodeInternal, errors.Wrapf(err, "failed to check if the approval is approved"))
635 }
636
637 issue, err = s.store.UpdateIssue(ctx, issue.ProjectID, issue.UID, &store.UpdateIssueMessage{

Callers

nothing calls this directly

Calls 15

getIssueMessageMethod · 0.95
isUserReviewerMethod · 0.95
convertToIssueMethod · 0.95
FindRejectedRoleFunction · 0.92
FindNextPendingRoleFunction · 0.92
FormatUserEmailFunction · 0.92
CheckApprovalApprovedFunction · 0.92
BBErrorFunction · 0.92
NotifyApprovalRequestedFunction · 0.92
NotifyIssueApprovedFunction · 0.92
GetUserFromContextFunction · 0.85

Tested by

no test coverage detected