mirror of
https://github.com/go-gitea/gitea
synced 2025-07-22 18:28:37 +00:00
Refactor error system (#33610)
This commit is contained in:
@@ -64,20 +64,20 @@ func ListPullReviews(ctx *context.APIContext) {
|
||||
pr, err := issues_model.GetPullRequestByIndex(ctx, ctx.Repo.Repository.ID, ctx.PathParamInt64("index"))
|
||||
if err != nil {
|
||||
if issues_model.IsErrPullRequestNotExist(err) {
|
||||
ctx.NotFound("GetPullRequestByIndex", err)
|
||||
ctx.APIErrorNotFound("GetPullRequestByIndex", err)
|
||||
} else {
|
||||
ctx.Error(http.StatusInternalServerError, "GetPullRequestByIndex", err)
|
||||
ctx.APIError(http.StatusInternalServerError, err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if err = pr.LoadIssue(ctx); err != nil {
|
||||
ctx.Error(http.StatusInternalServerError, "LoadIssue", err)
|
||||
ctx.APIError(http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
|
||||
if err = pr.Issue.LoadRepo(ctx); err != nil {
|
||||
ctx.Error(http.StatusInternalServerError, "LoadRepo", err)
|
||||
ctx.APIError(http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -88,19 +88,19 @@ func ListPullReviews(ctx *context.APIContext) {
|
||||
|
||||
allReviews, err := issues_model.FindReviews(ctx, opts)
|
||||
if err != nil {
|
||||
ctx.InternalServerError(err)
|
||||
ctx.APIErrorInternal(err)
|
||||
return
|
||||
}
|
||||
|
||||
count, err := issues_model.CountReviews(ctx, opts)
|
||||
if err != nil {
|
||||
ctx.InternalServerError(err)
|
||||
ctx.APIErrorInternal(err)
|
||||
return
|
||||
}
|
||||
|
||||
apiReviews, err := convert.ToPullReviewList(ctx, allReviews, ctx.Doer)
|
||||
if err != nil {
|
||||
ctx.Error(http.StatusInternalServerError, "convertToPullReviewList", err)
|
||||
ctx.APIError(http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -151,7 +151,7 @@ func GetPullReview(ctx *context.APIContext) {
|
||||
|
||||
apiReview, err := convert.ToPullReview(ctx, review, ctx.Doer)
|
||||
if err != nil {
|
||||
ctx.Error(http.StatusInternalServerError, "convertToPullReview", err)
|
||||
ctx.APIError(http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -201,7 +201,7 @@ func GetPullReviewComments(ctx *context.APIContext) {
|
||||
|
||||
apiComments, err := convert.ToPullReviewCommentList(ctx, review, ctx.Doer)
|
||||
if err != nil {
|
||||
ctx.Error(http.StatusInternalServerError, "convertToPullReviewCommentList", err)
|
||||
ctx.APIError(http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -252,16 +252,16 @@ func DeletePullReview(ctx *context.APIContext) {
|
||||
}
|
||||
|
||||
if ctx.Doer == nil {
|
||||
ctx.NotFound()
|
||||
ctx.APIErrorNotFound()
|
||||
return
|
||||
}
|
||||
if !ctx.Doer.IsAdmin && ctx.Doer.ID != review.ReviewerID {
|
||||
ctx.Error(http.StatusForbidden, "only admin and user itself can delete a review", nil)
|
||||
ctx.APIError(http.StatusForbidden, nil)
|
||||
return
|
||||
}
|
||||
|
||||
if err := issues_model.DeleteReview(ctx, review); err != nil {
|
||||
ctx.Error(http.StatusInternalServerError, "DeleteReview", fmt.Errorf("can not delete ReviewID: %d", review.ID))
|
||||
ctx.APIError(http.StatusInternalServerError, fmt.Errorf("can not delete ReviewID: %d", review.ID))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -309,9 +309,9 @@ func CreatePullReview(ctx *context.APIContext) {
|
||||
pr, err := issues_model.GetPullRequestByIndex(ctx, ctx.Repo.Repository.ID, ctx.PathParamInt64("index"))
|
||||
if err != nil {
|
||||
if issues_model.IsErrPullRequestNotExist(err) {
|
||||
ctx.NotFound("GetPullRequestByIndex", err)
|
||||
ctx.APIErrorNotFound("GetPullRequestByIndex", err)
|
||||
} else {
|
||||
ctx.Error(http.StatusInternalServerError, "GetPullRequestByIndex", err)
|
||||
ctx.APIError(http.StatusInternalServerError, err)
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -323,7 +323,7 @@ func CreatePullReview(ctx *context.APIContext) {
|
||||
}
|
||||
|
||||
if err := pr.Issue.LoadRepo(ctx); err != nil {
|
||||
ctx.Error(http.StatusInternalServerError, "pr.Issue.LoadRepo", err)
|
||||
ctx.APIError(http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -331,14 +331,14 @@ func CreatePullReview(ctx *context.APIContext) {
|
||||
if opts.CommitID == "" {
|
||||
gitRepo, closer, err := gitrepo.RepositoryFromContextOrOpen(ctx, pr.Issue.Repo)
|
||||
if err != nil {
|
||||
ctx.Error(http.StatusInternalServerError, "git.OpenRepository", err)
|
||||
ctx.APIError(http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
defer closer.Close()
|
||||
|
||||
headCommitID, err := gitRepo.GetRefCommitID(pr.GetGitRefName())
|
||||
if err != nil {
|
||||
ctx.Error(http.StatusInternalServerError, "GetRefCommitID", err)
|
||||
ctx.APIError(http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -364,7 +364,7 @@ func CreatePullReview(ctx *context.APIContext) {
|
||||
opts.CommitID,
|
||||
nil,
|
||||
); err != nil {
|
||||
ctx.Error(http.StatusInternalServerError, "CreateCodeComment", err)
|
||||
ctx.APIError(http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -373,9 +373,9 @@ func CreatePullReview(ctx *context.APIContext) {
|
||||
review, _, err := pull_service.SubmitReview(ctx, ctx.Doer, ctx.Repo.GitRepo, pr.Issue, reviewType, opts.Body, opts.CommitID, nil)
|
||||
if err != nil {
|
||||
if errors.Is(err, pull_service.ErrSubmitReviewOnClosedPR) {
|
||||
ctx.Error(http.StatusUnprocessableEntity, "", err)
|
||||
ctx.APIError(http.StatusUnprocessableEntity, err)
|
||||
} else {
|
||||
ctx.Error(http.StatusInternalServerError, "SubmitReview", err)
|
||||
ctx.APIError(http.StatusInternalServerError, err)
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -383,7 +383,7 @@ func CreatePullReview(ctx *context.APIContext) {
|
||||
// convert response
|
||||
apiReview, err := convert.ToPullReview(ctx, review, ctx.Doer)
|
||||
if err != nil {
|
||||
ctx.Error(http.StatusInternalServerError, "convertToPullReview", err)
|
||||
ctx.APIError(http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
ctx.JSON(http.StatusOK, apiReview)
|
||||
@@ -439,7 +439,7 @@ func SubmitPullReview(ctx *context.APIContext) {
|
||||
}
|
||||
|
||||
if review.Type != issues_model.ReviewTypePending {
|
||||
ctx.Error(http.StatusUnprocessableEntity, "", fmt.Errorf("only a pending review can be submitted"))
|
||||
ctx.APIError(http.StatusUnprocessableEntity, fmt.Errorf("only a pending review can be submitted"))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -451,13 +451,13 @@ func SubmitPullReview(ctx *context.APIContext) {
|
||||
|
||||
// if review stay pending return
|
||||
if reviewType == issues_model.ReviewTypePending {
|
||||
ctx.Error(http.StatusUnprocessableEntity, "", fmt.Errorf("review stay pending"))
|
||||
ctx.APIError(http.StatusUnprocessableEntity, fmt.Errorf("review stay pending"))
|
||||
return
|
||||
}
|
||||
|
||||
headCommitID, err := ctx.Repo.GitRepo.GetRefCommitID(pr.GetGitRefName())
|
||||
if err != nil {
|
||||
ctx.Error(http.StatusInternalServerError, "GitRepo: GetRefCommitID", err)
|
||||
ctx.APIError(http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -465,9 +465,9 @@ func SubmitPullReview(ctx *context.APIContext) {
|
||||
review, _, err = pull_service.SubmitReview(ctx, ctx.Doer, ctx.Repo.GitRepo, pr.Issue, reviewType, opts.Body, headCommitID, nil)
|
||||
if err != nil {
|
||||
if errors.Is(err, pull_service.ErrSubmitReviewOnClosedPR) {
|
||||
ctx.Error(http.StatusUnprocessableEntity, "", err)
|
||||
ctx.APIError(http.StatusUnprocessableEntity, err)
|
||||
} else {
|
||||
ctx.Error(http.StatusInternalServerError, "SubmitReview", err)
|
||||
ctx.APIError(http.StatusInternalServerError, err)
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -475,7 +475,7 @@ func SubmitPullReview(ctx *context.APIContext) {
|
||||
// convert response
|
||||
apiReview, err := convert.ToPullReview(ctx, review, ctx.Doer)
|
||||
if err != nil {
|
||||
ctx.Error(http.StatusInternalServerError, "convertToPullReview", err)
|
||||
ctx.APIError(http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
ctx.JSON(http.StatusOK, apiReview)
|
||||
@@ -484,7 +484,7 @@ func SubmitPullReview(ctx *context.APIContext) {
|
||||
// preparePullReviewType return ReviewType and false or nil and true if an error happen
|
||||
func preparePullReviewType(ctx *context.APIContext, pr *issues_model.PullRequest, event api.ReviewStateType, body string, hasComments bool) (issues_model.ReviewType, bool) {
|
||||
if err := pr.LoadIssue(ctx); err != nil {
|
||||
ctx.Error(http.StatusInternalServerError, "LoadIssue", err)
|
||||
ctx.APIError(http.StatusInternalServerError, err)
|
||||
return -1, true
|
||||
}
|
||||
|
||||
@@ -496,7 +496,7 @@ func preparePullReviewType(ctx *context.APIContext, pr *issues_model.PullRequest
|
||||
case api.ReviewStateApproved:
|
||||
// can not approve your own PR
|
||||
if pr.Issue.IsPoster(ctx.Doer.ID) {
|
||||
ctx.Error(http.StatusUnprocessableEntity, "", fmt.Errorf("approve your own pull is not allowed"))
|
||||
ctx.APIError(http.StatusUnprocessableEntity, fmt.Errorf("approve your own pull is not allowed"))
|
||||
return -1, true
|
||||
}
|
||||
reviewType = issues_model.ReviewTypeApprove
|
||||
@@ -505,7 +505,7 @@ func preparePullReviewType(ctx *context.APIContext, pr *issues_model.PullRequest
|
||||
case api.ReviewStateRequestChanges:
|
||||
// can not reject your own PR
|
||||
if pr.Issue.IsPoster(ctx.Doer.ID) {
|
||||
ctx.Error(http.StatusUnprocessableEntity, "", fmt.Errorf("reject your own pull is not allowed"))
|
||||
ctx.APIError(http.StatusUnprocessableEntity, fmt.Errorf("reject your own pull is not allowed"))
|
||||
return -1, true
|
||||
}
|
||||
reviewType = issues_model.ReviewTypeReject
|
||||
@@ -515,7 +515,7 @@ func preparePullReviewType(ctx *context.APIContext, pr *issues_model.PullRequest
|
||||
needsBody = false
|
||||
// if there is no body we need to ensure that there are comments
|
||||
if !hasBody && !hasComments {
|
||||
ctx.Error(http.StatusUnprocessableEntity, "", fmt.Errorf("review event %s requires a body or a comment", event))
|
||||
ctx.APIError(http.StatusUnprocessableEntity, fmt.Errorf("review event %s requires a body or a comment", event))
|
||||
return -1, true
|
||||
}
|
||||
default:
|
||||
@@ -524,7 +524,7 @@ func preparePullReviewType(ctx *context.APIContext, pr *issues_model.PullRequest
|
||||
|
||||
// reject reviews with empty body if a body is required for this call
|
||||
if needsBody && !hasBody {
|
||||
ctx.Error(http.StatusUnprocessableEntity, "", fmt.Errorf("review event %s requires a body", event))
|
||||
ctx.APIError(http.StatusUnprocessableEntity, fmt.Errorf("review event %s requires a body", event))
|
||||
return -1, true
|
||||
}
|
||||
|
||||
@@ -536,9 +536,9 @@ func prepareSingleReview(ctx *context.APIContext) (*issues_model.Review, *issues
|
||||
pr, err := issues_model.GetPullRequestByIndex(ctx, ctx.Repo.Repository.ID, ctx.PathParamInt64("index"))
|
||||
if err != nil {
|
||||
if issues_model.IsErrPullRequestNotExist(err) {
|
||||
ctx.NotFound("GetPullRequestByIndex", err)
|
||||
ctx.APIErrorNotFound("GetPullRequestByIndex", err)
|
||||
} else {
|
||||
ctx.Error(http.StatusInternalServerError, "GetPullRequestByIndex", err)
|
||||
ctx.APIError(http.StatusInternalServerError, err)
|
||||
}
|
||||
return nil, nil, true
|
||||
}
|
||||
@@ -546,27 +546,27 @@ func prepareSingleReview(ctx *context.APIContext) (*issues_model.Review, *issues
|
||||
review, err := issues_model.GetReviewByID(ctx, ctx.PathParamInt64("id"))
|
||||
if err != nil {
|
||||
if issues_model.IsErrReviewNotExist(err) {
|
||||
ctx.NotFound("GetReviewByID", err)
|
||||
ctx.APIErrorNotFound("GetReviewByID", err)
|
||||
} else {
|
||||
ctx.Error(http.StatusInternalServerError, "GetReviewByID", err)
|
||||
ctx.APIError(http.StatusInternalServerError, err)
|
||||
}
|
||||
return nil, nil, true
|
||||
}
|
||||
|
||||
// validate the review is for the given PR
|
||||
if review.IssueID != pr.IssueID {
|
||||
ctx.NotFound("ReviewNotInPR")
|
||||
ctx.APIErrorNotFound("ReviewNotInPR")
|
||||
return nil, nil, true
|
||||
}
|
||||
|
||||
// make sure that the user has access to this review if it is pending
|
||||
if review.Type == issues_model.ReviewTypePending && review.ReviewerID != ctx.Doer.ID && !ctx.Doer.IsAdmin {
|
||||
ctx.NotFound("GetReviewByID")
|
||||
ctx.APIErrorNotFound("GetReviewByID")
|
||||
return nil, nil, true
|
||||
}
|
||||
|
||||
if err := review.LoadAttributes(ctx); err != nil && !user_model.IsErrUserNotExist(err) {
|
||||
ctx.Error(http.StatusInternalServerError, "ReviewLoadAttributes", err)
|
||||
ctx.APIError(http.StatusInternalServerError, err)
|
||||
return nil, nil, true
|
||||
}
|
||||
|
||||
@@ -668,10 +668,10 @@ func parseReviewersByNames(ctx *context.APIContext, reviewerNames, teamReviewerN
|
||||
|
||||
if err != nil {
|
||||
if user_model.IsErrUserNotExist(err) {
|
||||
ctx.NotFound("UserNotExist", fmt.Sprintf("User '%s' not exist", r))
|
||||
ctx.APIErrorNotFound("UserNotExist", fmt.Sprintf("User '%s' not exist", r))
|
||||
return nil, nil
|
||||
}
|
||||
ctx.Error(http.StatusInternalServerError, "GetUser", err)
|
||||
ctx.APIError(http.StatusInternalServerError, err)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
@@ -684,10 +684,10 @@ func parseReviewersByNames(ctx *context.APIContext, reviewerNames, teamReviewerN
|
||||
teamReviewer, err = organization.GetTeam(ctx, ctx.Repo.Owner.ID, t)
|
||||
if err != nil {
|
||||
if organization.IsErrTeamNotExist(err) {
|
||||
ctx.NotFound("TeamNotExist", fmt.Sprintf("Team '%s' not exist", t))
|
||||
ctx.APIErrorNotFound("TeamNotExist", fmt.Sprintf("Team '%s' not exist", t))
|
||||
return nil, nil
|
||||
}
|
||||
ctx.Error(http.StatusInternalServerError, "ReviewRequest", err)
|
||||
ctx.APIError(http.StatusInternalServerError, err)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
@@ -701,21 +701,21 @@ func apiReviewRequest(ctx *context.APIContext, opts api.PullReviewRequestOptions
|
||||
pr, err := issues_model.GetPullRequestByIndex(ctx, ctx.Repo.Repository.ID, ctx.PathParamInt64("index"))
|
||||
if err != nil {
|
||||
if issues_model.IsErrPullRequestNotExist(err) {
|
||||
ctx.NotFound("GetPullRequestByIndex", err)
|
||||
ctx.APIErrorNotFound("GetPullRequestByIndex", err)
|
||||
} else {
|
||||
ctx.Error(http.StatusInternalServerError, "GetPullRequestByIndex", err)
|
||||
ctx.APIError(http.StatusInternalServerError, err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if err := pr.Issue.LoadRepo(ctx); err != nil {
|
||||
ctx.Error(http.StatusInternalServerError, "pr.Issue.LoadRepo", err)
|
||||
ctx.APIError(http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
|
||||
permDoer, err := access_model.GetUserRepoPermission(ctx, pr.Issue.Repo, ctx.Doer)
|
||||
if err != nil {
|
||||
ctx.Error(http.StatusInternalServerError, "GetUserRepoPermission", err)
|
||||
ctx.APIError(http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -733,20 +733,20 @@ func apiReviewRequest(ctx *context.APIContext, opts api.PullReviewRequestOptions
|
||||
comment, err := issue_service.ReviewRequest(ctx, pr.Issue, ctx.Doer, &permDoer, reviewer, isAdd)
|
||||
if err != nil {
|
||||
if issues_model.IsErrReviewRequestOnClosedPR(err) {
|
||||
ctx.Error(http.StatusForbidden, "", err)
|
||||
ctx.APIError(http.StatusForbidden, err)
|
||||
return
|
||||
}
|
||||
if issues_model.IsErrNotValidReviewRequest(err) {
|
||||
ctx.Error(http.StatusUnprocessableEntity, "", err)
|
||||
ctx.APIError(http.StatusUnprocessableEntity, err)
|
||||
return
|
||||
}
|
||||
ctx.Error(http.StatusInternalServerError, "ReviewRequest", err)
|
||||
ctx.APIError(http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
|
||||
if comment != nil && isAdd {
|
||||
if err = comment.LoadReview(ctx); err != nil {
|
||||
ctx.ServerError("ReviewRequest", err)
|
||||
ctx.APIErrorInternal(err)
|
||||
return
|
||||
}
|
||||
reviews = append(reviews, comment.Review)
|
||||
@@ -758,20 +758,20 @@ func apiReviewRequest(ctx *context.APIContext, opts api.PullReviewRequestOptions
|
||||
comment, err := issue_service.TeamReviewRequest(ctx, pr.Issue, ctx.Doer, teamReviewer, isAdd)
|
||||
if err != nil {
|
||||
if issues_model.IsErrReviewRequestOnClosedPR(err) {
|
||||
ctx.Error(http.StatusForbidden, "", err)
|
||||
ctx.APIError(http.StatusForbidden, err)
|
||||
return
|
||||
}
|
||||
if issues_model.IsErrNotValidReviewRequest(err) {
|
||||
ctx.Error(http.StatusUnprocessableEntity, "", err)
|
||||
ctx.APIError(http.StatusUnprocessableEntity, err)
|
||||
return
|
||||
}
|
||||
ctx.ServerError("TeamReviewRequest", err)
|
||||
ctx.APIErrorInternal(err)
|
||||
return
|
||||
}
|
||||
|
||||
if comment != nil && isAdd {
|
||||
if err = comment.LoadReview(ctx); err != nil {
|
||||
ctx.ServerError("ReviewRequest", err)
|
||||
ctx.APIErrorInternal(err)
|
||||
return
|
||||
}
|
||||
reviews = append(reviews, comment.Review)
|
||||
@@ -782,7 +782,7 @@ func apiReviewRequest(ctx *context.APIContext, opts api.PullReviewRequestOptions
|
||||
if isAdd {
|
||||
apiReviews, err := convert.ToPullReviewList(ctx, reviews, ctx.Doer)
|
||||
if err != nil {
|
||||
ctx.Error(http.StatusInternalServerError, "convertToPullReviewList", err)
|
||||
ctx.APIError(http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
ctx.JSON(http.StatusCreated, apiReviews)
|
||||
@@ -884,7 +884,7 @@ func UnDismissPullReview(ctx *context.APIContext) {
|
||||
|
||||
func dismissReview(ctx *context.APIContext, msg string, isDismiss, dismissPriors bool) {
|
||||
if !ctx.Repo.IsAdmin() {
|
||||
ctx.Error(http.StatusForbidden, "", "Must be repo admin")
|
||||
ctx.APIError(http.StatusForbidden, "Must be repo admin")
|
||||
return
|
||||
}
|
||||
review, _, isWrong := prepareSingleReview(ctx)
|
||||
@@ -893,29 +893,29 @@ func dismissReview(ctx *context.APIContext, msg string, isDismiss, dismissPriors
|
||||
}
|
||||
|
||||
if review.Type != issues_model.ReviewTypeApprove && review.Type != issues_model.ReviewTypeReject {
|
||||
ctx.Error(http.StatusForbidden, "", "not need to dismiss this review because it's type is not Approve or change request")
|
||||
ctx.APIError(http.StatusForbidden, "not need to dismiss this review because it's type is not Approve or change request")
|
||||
return
|
||||
}
|
||||
|
||||
_, err := pull_service.DismissReview(ctx, review.ID, ctx.Repo.Repository.ID, msg, ctx.Doer, isDismiss, dismissPriors)
|
||||
if err != nil {
|
||||
if pull_service.IsErrDismissRequestOnClosedPR(err) {
|
||||
ctx.Error(http.StatusForbidden, "", err)
|
||||
ctx.APIError(http.StatusForbidden, err)
|
||||
return
|
||||
}
|
||||
ctx.Error(http.StatusInternalServerError, "pull_service.DismissReview", err)
|
||||
ctx.APIError(http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
|
||||
if review, err = issues_model.GetReviewByID(ctx, review.ID); err != nil {
|
||||
ctx.Error(http.StatusInternalServerError, "GetReviewByID", err)
|
||||
ctx.APIError(http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
|
||||
// convert response
|
||||
apiReview, err := convert.ToPullReview(ctx, review, ctx.Doer)
|
||||
if err != nil {
|
||||
ctx.Error(http.StatusInternalServerError, "convertToPullReview", err)
|
||||
ctx.APIError(http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
ctx.JSON(http.StatusOK, apiReview)
|
||||
|
Reference in New Issue
Block a user