mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-11-03 20:36:07 +01: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