fix: github apps auth can not show repos (#6380) (#6381)

Co-authored-by: abeizn <zikuan.an@merico.dev>
diff --git a/backend/plugins/github/api/remote.go b/backend/plugins/github/api/remote.go
index 2444b23..b437ee7 100644
--- a/backend/plugins/github/api/remote.go
+++ b/backend/plugins/github/api/remote.go
@@ -184,6 +184,123 @@
 	return githubRepository
 }
 
+type GithubAppRepo struct {
+	TotalCount   int `json:"total_count"`
+	Repositories []struct {
+		ID       int    `json:"id"`
+		NodeID   string `json:"node_id"`
+		Name     string `json:"name"`
+		FullName string `json:"full_name"`
+		Owner    struct {
+			Login             string `json:"login"`
+			ID                int    `json:"id"`
+			NodeID            string `json:"node_id"`
+			AvatarURL         string `json:"avatar_url"`
+			GravatarID        string `json:"gravatar_id"`
+			URL               string `json:"url"`
+			HTMLURL           string `json:"html_url"`
+			FollowersURL      string `json:"followers_url"`
+			FollowingURL      string `json:"following_url"`
+			GistsURL          string `json:"gists_url"`
+			StarredURL        string `json:"starred_url"`
+			SubscriptionsURL  string `json:"subscriptions_url"`
+			OrganizationsURL  string `json:"organizations_url"`
+			ReposURL          string `json:"repos_url"`
+			EventsURL         string `json:"events_url"`
+			ReceivedEventsURL string `json:"received_events_url"`
+			Type              string `json:"type"`
+			SiteAdmin         bool   `json:"site_admin"`
+		} `json:"owner"`
+		Private             bool      `json:"private"`
+		HTMLURL             string    `json:"html_url"`
+		Description         string    `json:"description"`
+		Fork                bool      `json:"fork"`
+		URL                 string    `json:"url"`
+		ArchiveURL          string    `json:"archive_url"`
+		AssigneesURL        string    `json:"assignees_url"`
+		BlobsURL            string    `json:"blobs_url"`
+		BranchesURL         string    `json:"branches_url"`
+		CollaboratorsURL    string    `json:"collaborators_url"`
+		CommentsURL         string    `json:"comments_url"`
+		CommitsURL          string    `json:"commits_url"`
+		CompareURL          string    `json:"compare_url"`
+		ContentsURL         string    `json:"contents_url"`
+		ContributorsURL     string    `json:"contributors_url"`
+		DeploymentsURL      string    `json:"deployments_url"`
+		DownloadsURL        string    `json:"downloads_url"`
+		EventsURL           string    `json:"events_url"`
+		ForksURL            string    `json:"forks_url"`
+		GitCommitsURL       string    `json:"git_commits_url"`
+		GitRefsURL          string    `json:"git_refs_url"`
+		GitTagsURL          string    `json:"git_tags_url"`
+		GitURL              string    `json:"git_url"`
+		IssueCommentURL     string    `json:"issue_comment_url"`
+		IssueEventsURL      string    `json:"issue_events_url"`
+		IssuesURL           string    `json:"issues_url"`
+		KeysURL             string    `json:"keys_url"`
+		LabelsURL           string    `json:"labels_url"`
+		LanguagesURL        string    `json:"languages_url"`
+		MergesURL           string    `json:"merges_url"`
+		MilestonesURL       string    `json:"milestones_url"`
+		NotificationsURL    string    `json:"notifications_url"`
+		PullsURL            string    `json:"pulls_url"`
+		ReleasesURL         string    `json:"releases_url"`
+		SSHURL              string    `json:"ssh_url"`
+		StargazersURL       string    `json:"stargazers_url"`
+		StatusesURL         string    `json:"statuses_url"`
+		SubscribersURL      string    `json:"subscribers_url"`
+		SubscriptionURL     string    `json:"subscription_url"`
+		TagsURL             string    `json:"tags_url"`
+		TeamsURL            string    `json:"teams_url"`
+		TreesURL            string    `json:"trees_url"`
+		CloneURL            string    `json:"clone_url"`
+		MirrorURL           string    `json:"mirror_url"`
+		HooksURL            string    `json:"hooks_url"`
+		SvnURL              string    `json:"svn_url"`
+		Homepage            string    `json:"homepage"`
+		Language            any       `json:"language"`
+		ForksCount          int       `json:"forks_count"`
+		StargazersCount     int       `json:"stargazers_count"`
+		WatchersCount       int       `json:"watchers_count"`
+		Size                int       `json:"size"`
+		DefaultBranch       string    `json:"default_branch"`
+		OpenIssuesCount     int       `json:"open_issues_count"`
+		IsTemplate          bool      `json:"is_template"`
+		Topics              []string  `json:"topics"`
+		HasIssues           bool      `json:"has_issues"`
+		HasProjects         bool      `json:"has_projects"`
+		HasWiki             bool      `json:"has_wiki"`
+		HasPages            bool      `json:"has_pages"`
+		HasDownloads        bool      `json:"has_downloads"`
+		Archived            bool      `json:"archived"`
+		Disabled            bool      `json:"disabled"`
+		Visibility          string    `json:"visibility"`
+		PushedAt            time.Time `json:"pushed_at"`
+		CreatedAt           time.Time `json:"created_at"`
+		UpdatedAt           time.Time `json:"updated_at"`
+		AllowRebaseMerge    bool      `json:"allow_rebase_merge"`
+		TemplateRepository  any       `json:"template_repository"`
+		TempCloneToken      string    `json:"temp_clone_token"`
+		AllowSquashMerge    bool      `json:"allow_squash_merge"`
+		AllowAutoMerge      bool      `json:"allow_auto_merge"`
+		DeleteBranchOnMerge bool      `json:"delete_branch_on_merge"`
+		AllowMergeCommit    bool      `json:"allow_merge_commit"`
+		SubscribersCount    int       `json:"subscribers_count"`
+		NetworkCount        int       `json:"network_count"`
+		License             struct {
+			Key     string `json:"key"`
+			Name    string `json:"name"`
+			URL     string `json:"url"`
+			SpdxID  string `json:"spdx_id"`
+			NodeID  string `json:"node_id"`
+			HTMLURL string `json:"html_url"`
+		} `json:"license"`
+		Forks      int `json:"forks"`
+		OpenIssues int `json:"open_issues"`
+		Watchers   int `json:"watchers"`
+	} `json:"repositories"`
+}
+
 // RemoteScopes list all available scope for users
 // @Summary list all available scope for users
 // @Description list all available scope for users
@@ -206,29 +323,57 @@
 				return nil, errors.BadInput.Wrap(err, "failed to get create apiClient")
 			}
 			query := initialQuery(queryData)
-			res, err := apiClient.Get("user/orgs", query, nil)
-			if err != nil {
-				return nil, err
-			}
-			var resBody []org
-			err = api.UnmarshalResponse(res, &resBody)
-			if err != nil {
-				return nil, err
-			}
-			res, err = apiClient.Get("user", nil, nil)
-			if err != nil {
-				return nil, err
-			}
+			result := make([]plugin.ApiGroup, 0)
 			var o owner
-			err = api.UnmarshalResponse(res, &o)
-			if err != nil {
-				return nil, err
+			var res *http.Response
+			if connection.AuthMethod == plugin.AUTH_METHOD_APPKEY {
+				resApp, err := apiClient.Get("installation/repositories", query, nil)
+				if err != nil {
+					return nil, err
+				}
+				var resAppBody GithubAppRepo
+				err = api.UnmarshalResponse(resApp, &resAppBody)
+				if err != nil {
+					return nil, err
+				}
+				var resOwner []owner
+				processedOrgs := make(map[string]struct{})
+				for _, v := range resAppBody.Repositories {
+					orgName := v.Owner.Login
+					if _, exists := processedOrgs[orgName]; !exists && orgName != "" {
+						o.ID = v.Owner.ID
+						o.Login = orgName
+						resOwner = append(resOwner, o)
+						processedOrgs[orgName] = struct{}{}
+					}
+				}
+				for _, v := range resOwner {
+					result = append(result, v)
+				}
+			} else {
+				var resBody []org
+				resToken, err := apiClient.Get("user/orgs", query, nil)
+				if err != nil {
+					return nil, err
+				}
+				err = api.UnmarshalResponse(resToken, &resBody)
+				if err != nil {
+					return nil, err
+				}
+				res, err = apiClient.Get("user", nil, nil)
+				if err != nil {
+					return nil, err
+				}
+				err = api.UnmarshalResponse(res, &o)
+				if err != nil {
+					return nil, err
+				}
+				result = append(result, o)
+				for _, v := range resBody {
+					result = append(result, v)
+				}
 			}
-			result := make([]plugin.ApiGroup, 0, len(resBody)+1)
-			for _, v := range resBody {
-				result = append(result, v)
-			}
-			result = append(result, o)
+
 			return result, err
 		},
 		func(basicRes context.BasicRes, gid string, queryData *api.RemoteQueryData, connection models.GithubConnection) ([]repo, errors.Error) {