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_issues: 0
 | 
				
			||||||
  num_closed_issues: 0
 | 
					  num_closed_issues: 0
 | 
				
			||||||
  archived_unix: 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)
 | 
							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
 | 
					// BuildLabelNamesIssueIDsCondition returns a builder where get issue ids match label names
 | 
				
			||||||
func BuildLabelNamesIssueIDsCondition(labelNames []string) *builder.Builder {
 | 
					func BuildLabelNamesIssueIDsCondition(labelNames []string) *builder.Builder {
 | 
				
			||||||
	return builder.Select("issue_label.issue_id").
 | 
						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()))
 | 
								labelIDs = append(labelIDs, int64(rv.Float()))
 | 
				
			||||||
		case reflect.String:
 | 
							case reflect.String:
 | 
				
			||||||
			labelNames = append(labelNames, rv.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 {
 | 
						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")
 | 
							return nil, nil, fmt.Errorf("invalid labels")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if len(labelNames) > 0 {
 | 
						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 {
 | 
							if err != nil {
 | 
				
			||||||
			ctx.Error(http.StatusInternalServerError, "GetLabelIDsInRepoByNames", err)
 | 
								ctx.Error(http.StatusInternalServerError, "GetLabelIDsInRepoByNames", err)
 | 
				
			||||||
			return nil, nil, 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")
 | 
						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) {
 | 
					func TestAPIAddIssueLabelsWithLabelNames(t *testing.T) {
 | 
				
			||||||
	assert.NoError(t, unittest.LoadFixtures())
 | 
						assert.NoError(t, unittest.LoadFixtures())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
 | 
						repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 3})
 | 
				
			||||||
	issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{RepoID: repo.ID})
 | 
						issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 6, RepoID: repo.ID})
 | 
				
			||||||
	owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
 | 
						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)
 | 
						user1Session := loginUser(t, "user1")
 | 
				
			||||||
	token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteIssue)
 | 
						token := getTokenForLoggedInUser(t, user1Session, auth_model.AccessTokenScopeWriteIssue)
 | 
				
			||||||
	urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/issues/%d/labels",
 | 
					
 | 
				
			||||||
		repo.OwnerName, repo.Name, issue.Index)
 | 
						// 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{
 | 
						req := NewRequestWithJSON(t, "POST", urlStr, &api.IssueLabelsOption{
 | 
				
			||||||
		Labels: []any{"label1", "label2"},
 | 
							Labels: []any{repoLabel.Name, orgLabel.Name},
 | 
				
			||||||
	}).AddTokenAuth(token)
 | 
						}).AddTokenAuth(token)
 | 
				
			||||||
	resp := MakeRequest(t, req, http.StatusOK)
 | 
						resp := MakeRequest(t, req, http.StatusOK)
 | 
				
			||||||
	var apiLabels []*api.Label
 | 
						var apiLabels []*api.Label
 | 
				
			||||||
	DecodeJSON(t, resp, &apiLabels)
 | 
						DecodeJSON(t, resp, &apiLabels)
 | 
				
			||||||
	assert.Len(t, apiLabels, unittest.GetCount(t, &issues_model.IssueLabel{IssueID: issue.ID}))
 | 
						assert.Len(t, apiLabels, unittest.GetCount(t, &issues_model.IssueLabel{IssueID: issue.ID}))
 | 
				
			||||||
 | 
					 | 
				
			||||||
	var apiLabelNames []string
 | 
						var apiLabelNames []string
 | 
				
			||||||
	for _, label := range apiLabels {
 | 
						for _, label := range apiLabels {
 | 
				
			||||||
		apiLabelNames = append(apiLabelNames, label.Name)
 | 
							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) {
 | 
					func TestAPIReplaceIssueLabels(t *testing.T) {
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user