mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-10-29 10:57:44 +09:00 
			
		
		
		
	Support org labels when adding labels by label names (#32988)
Fix #32891
This commit is contained in:
		| @@ -96,3 +96,14 @@ | ||||
|   num_issues: 0 | ||||
|   num_closed_issues: 0 | ||||
|   archived_unix: 0 | ||||
|  | ||||
| - | ||||
|   id: 10 | ||||
|   repo_id: 3 | ||||
|   org_id: 0 | ||||
|   name: repo3label1 | ||||
|   color: '#112233' | ||||
|   exclusive: false | ||||
|   num_issues: 0 | ||||
|   num_closed_issues: 0 | ||||
|   archived_unix: 0 | ||||
|   | ||||
| @@ -349,6 +349,17 @@ func GetLabelIDsInRepoByNames(ctx context.Context, repoID int64, labelNames []st | ||||
| 		Find(&labelIDs) | ||||
| } | ||||
|  | ||||
| // GetLabelIDsInOrgByNames returns a list of labelIDs by names in a given org. | ||||
| func GetLabelIDsInOrgByNames(ctx context.Context, orgID int64, labelNames []string) ([]int64, error) { | ||||
| 	labelIDs := make([]int64, 0, len(labelNames)) | ||||
| 	return labelIDs, db.GetEngine(ctx).Table("label"). | ||||
| 		Where("org_id = ?", orgID). | ||||
| 		In("name", labelNames). | ||||
| 		Asc("name"). | ||||
| 		Cols("id"). | ||||
| 		Find(&labelIDs) | ||||
| } | ||||
|  | ||||
| // BuildLabelNamesIssueIDsCondition returns a builder where get issue ids match label names | ||||
| func BuildLabelNamesIssueIDsCondition(labelNames []string) *builder.Builder { | ||||
| 	return builder.Select("issue_label.issue_id"). | ||||
|   | ||||
| @@ -335,6 +335,9 @@ func prepareForReplaceOrAdd(ctx *context.APIContext, form api.IssueLabelsOption) | ||||
| 			labelIDs = append(labelIDs, int64(rv.Float())) | ||||
| 		case reflect.String: | ||||
| 			labelNames = append(labelNames, rv.String()) | ||||
| 		default: | ||||
| 			ctx.Error(http.StatusBadRequest, "InvalidLabel", "a label must be an integer or a string") | ||||
| 			return nil, nil, fmt.Errorf("invalid label") | ||||
| 		} | ||||
| 	} | ||||
| 	if len(labelIDs) > 0 && len(labelNames) > 0 { | ||||
| @@ -342,11 +345,20 @@ func prepareForReplaceOrAdd(ctx *context.APIContext, form api.IssueLabelsOption) | ||||
| 		return nil, nil, fmt.Errorf("invalid labels") | ||||
| 	} | ||||
| 	if len(labelNames) > 0 { | ||||
| 		labelIDs, err = issues_model.GetLabelIDsInRepoByNames(ctx, ctx.Repo.Repository.ID, labelNames) | ||||
| 		repoLabelIDs, err := issues_model.GetLabelIDsInRepoByNames(ctx, ctx.Repo.Repository.ID, labelNames) | ||||
| 		if err != nil { | ||||
| 			ctx.Error(http.StatusInternalServerError, "GetLabelIDsInRepoByNames", err) | ||||
| 			return nil, nil, err | ||||
| 		} | ||||
| 		labelIDs = append(labelIDs, repoLabelIDs...) | ||||
| 		if ctx.Repo.Owner.IsOrganization() { | ||||
| 			orgLabelIDs, err := issues_model.GetLabelIDsInOrgByNames(ctx, ctx.Repo.Owner.ID, labelNames) | ||||
| 			if err != nil { | ||||
| 				ctx.Error(http.StatusInternalServerError, "GetLabelIDsInOrgByNames", err) | ||||
| 				return nil, nil, err | ||||
| 			} | ||||
| 			labelIDs = append(labelIDs, orgLabelIDs...) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	labels, err := issues_model.GetLabelsByIDs(ctx, labelIDs, "id", "repo_id", "org_id", "name", "exclusive") | ||||
|   | ||||
| @@ -117,27 +117,33 @@ func TestAPIAddIssueLabels(t *testing.T) { | ||||
| func TestAPIAddIssueLabelsWithLabelNames(t *testing.T) { | ||||
| 	assert.NoError(t, unittest.LoadFixtures()) | ||||
|  | ||||
| 	repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) | ||||
| 	issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{RepoID: repo.ID}) | ||||
| 	repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 3}) | ||||
| 	issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 6, RepoID: repo.ID}) | ||||
| 	owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID}) | ||||
| 	repoLabel := unittest.AssertExistsAndLoadBean(t, &issues_model.Label{ID: 10, RepoID: repo.ID}) | ||||
| 	orgLabel := unittest.AssertExistsAndLoadBean(t, &issues_model.Label{ID: 4, OrgID: owner.ID}) | ||||
|  | ||||
| 	session := loginUser(t, owner.Name) | ||||
| 	token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteIssue) | ||||
| 	urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/issues/%d/labels", | ||||
| 		repo.OwnerName, repo.Name, issue.Index) | ||||
| 	user1Session := loginUser(t, "user1") | ||||
| 	token := getTokenForLoggedInUser(t, user1Session, auth_model.AccessTokenScopeWriteIssue) | ||||
|  | ||||
| 	// add the org label and the repo label to the issue | ||||
| 	urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/issues/%d/labels", owner.Name, repo.Name, issue.Index) | ||||
| 	req := NewRequestWithJSON(t, "POST", urlStr, &api.IssueLabelsOption{ | ||||
| 		Labels: []any{"label1", "label2"}, | ||||
| 		Labels: []any{repoLabel.Name, orgLabel.Name}, | ||||
| 	}).AddTokenAuth(token) | ||||
| 	resp := MakeRequest(t, req, http.StatusOK) | ||||
| 	var apiLabels []*api.Label | ||||
| 	DecodeJSON(t, resp, &apiLabels) | ||||
| 	assert.Len(t, apiLabels, unittest.GetCount(t, &issues_model.IssueLabel{IssueID: issue.ID})) | ||||
|  | ||||
| 	var apiLabelNames []string | ||||
| 	for _, label := range apiLabels { | ||||
| 		apiLabelNames = append(apiLabelNames, label.Name) | ||||
| 	} | ||||
| 	assert.ElementsMatch(t, apiLabelNames, []string{"label1", "label2"}) | ||||
| 	assert.ElementsMatch(t, apiLabelNames, []string{repoLabel.Name, orgLabel.Name}) | ||||
|  | ||||
| 	// delete labels | ||||
| 	req = NewRequest(t, "DELETE", urlStr).AddTokenAuth(token) | ||||
| 	MakeRequest(t, req, http.StatusNoContent) | ||||
| } | ||||
|  | ||||
| func TestAPIReplaceIssueLabels(t *testing.T) { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user