Ver Fonte

more schema changes and finish endpoint for checking oauth access for frontend

Ivan Galakhov há 4 anos atrás
pai
commit
4892d694c3

+ 20 - 0
internal/repository/gorm/auth.go

@@ -1125,6 +1125,16 @@ func (repo *GithubAppInstallationRepository) ReadGithubAppInstallationByAccountI
 	return ret, nil
 }
 
+func (repo *GithubAppInstallationRepository) ReadGithubAppInstallationByAccountIDs(accountIDs []int64) ([]*ints.GithubAppInstallation, error) {
+	ret := make([]*ints.GithubAppInstallation, 0)
+
+	if err := repo.db.Where("account_id IN ?", accountIDs).Find(&ret).Error; err != nil {
+		return nil, err
+	}
+
+	return ret, nil
+}
+
 func (repo *GithubAppInstallationRepository) DeleteGithubAppInstallationByAccountID(accountID int64) error {
 	if err := repo.db.Unscoped().Where("account_id = ?", accountID).Delete(&ints.GithubAppInstallation{}).Error; err != nil {
 		return err
@@ -1148,3 +1158,13 @@ func (repo *GithubAppOAuthIntegrationRepository) CreateGithubAppOAuthIntegration
 	}
 	return am, nil
 }
+
+func (repo *GithubAppOAuthIntegrationRepository) ReadGithubAppOauthIntegration(id uint) (*ints.GithubAppOAuthIntegration, error) {
+	ret := &ints.GithubAppOAuthIntegration{}
+
+	if err := repo.db.Where("id = ?", id).First(&ret).Error; err != nil {
+		return nil, err
+	}
+
+	return ret, nil
+}

+ 2 - 0
internal/repository/integrations.go

@@ -41,6 +41,7 @@ type OAuthIntegrationRepository interface {
 // mechanism
 type GithubAppOAuthIntegrationRepository interface {
 	CreateGithubAppOAuthIntegration(am *ints.GithubAppOAuthIntegration) (*ints.GithubAppOAuthIntegration, error)
+	ReadGithubAppOauthIntegration(id uint) (*ints.GithubAppOAuthIntegration, error)
 }
 
 // AWSIntegrationRepository represents the set of queries on the AWS auth
@@ -65,5 +66,6 @@ type GithubAppInstallationRepository interface {
 	CreateGithubAppInstallation(am *ints.GithubAppInstallation) (*ints.GithubAppInstallation, error)
 	ReadGithubAppInstallation(id uint) (*ints.GithubAppInstallation, error)
 	ReadGithubAppInstallationByAccountID(accountID int64) (*ints.GithubAppInstallation, error)
+	ReadGithubAppInstallationByAccountIDs(accountIDs []int64) ([]*ints.GithubAppInstallation, error)
 	DeleteGithubAppInstallationByAccountID(accountID int64) error
 }

+ 32 - 0
internal/repository/memory/auth.go

@@ -478,6 +478,26 @@ func (repo *GithubAppInstallationRepository) ReadGithubAppInstallationByAccountI
 	return nil, gorm.ErrRecordNotFound
 }
 
+func (repo *GithubAppInstallationRepository) ReadGithubAppInstallationByAccountIDs(accountIDs []int64) ([]*ints.GithubAppInstallation, error) {
+
+	if !repo.canQuery {
+		return nil, errors.New("cannot write database")
+	}
+
+	ret := make([]*ints.GithubAppInstallation, 0)
+
+	for _, installation := range repo.githubAppInstallations {
+		// O(n^2) can be made into O(n) if this is too slow
+		for _, id := range accountIDs {
+			if installation.AccountID == id {
+				ret = append(ret, installation)
+			}
+		}
+	}
+
+	return ret, nil
+}
+
 func (repo *GithubAppInstallationRepository) DeleteGithubAppInstallationByAccountID(accountID int64) error {
 	if !repo.canQuery {
 		return errors.New("cannot write database")
@@ -514,3 +534,15 @@ func (repo *GithubAppOAuthIntegrationRepository) CreateGithubAppOAuthIntegration
 
 	return am, nil
 }
+
+func (repo *GithubAppOAuthIntegrationRepository) ReadGithubAppOauthIntegration(id uint) (*ints.GithubAppOAuthIntegration, error) {
+	if !repo.canQuery {
+		return nil, errors.New("cannot write database")
+	}
+
+	if int(id-1) >= len(repo.githubAppOauthIntegrations) || repo.githubAppOauthIntegrations[id-1] == nil {
+		return nil, gorm.ErrRecordNotFound
+	}
+
+	return repo.githubAppOauthIntegrations[int(id-1)], nil
+}

+ 85 - 0
server/api/integration_handler.go

@@ -1,6 +1,7 @@
 package api
 
 import (
+	"context"
 	"encoding/json"
 	"github.com/google/go-github/github"
 	"github.com/porter-dev/porter/internal/oauth"
@@ -447,3 +448,87 @@ func (app *App) HandleGithubAppInstall(w http.ResponseWriter, r *http.Request) {
 
 	http.Redirect(w, r, url, 302)
 }
+
+type HandleListGithubAppAccessResp struct {
+	HasAccess bool     `json:"has_access"`
+	LoginName string   `json:"username,omitempty"`
+	Orgs      []string `json:"organizations,omitempty"`
+}
+
+func (app *App) HandleListGithubAppAccess(w http.ResponseWriter, r *http.Request) {
+	tok, err := app.getGithubUserTokenFromRequest(r)
+
+	if err != nil {
+		res := HandleListGithubAppAccessResp{
+			HasAccess: false,
+		}
+		json.NewEncoder(w).Encode(res)
+		return
+	}
+
+	client := github.NewClient(app.GithubProjectConf.Client(oauth2.NoContext, tok))
+
+	opts := &github.ListOptions{
+		PerPage: 100,
+		Page:    1,
+	}
+
+	res := HandleListGithubAppAccessResp{
+		HasAccess: true,
+	}
+
+	for {
+		orgs, pages, err := client.Organizations.List(context.Background(), "", opts)
+
+		if err != nil {
+			app.handleErrorInternal(err, w)
+			return
+		}
+
+		for _, org := range orgs {
+			res.Orgs = append(res.Orgs, *org.Login)
+		}
+
+		if pages.NextPage == 0 {
+			break
+		}
+	}
+
+	AuthUser, _, err := client.Users.Get(context.Background(), "")
+
+	if err != nil {
+		app.handleErrorInternal(err, w)
+		return
+	}
+
+	res.LoginName = *AuthUser.Login
+
+	json.NewEncoder(w).Encode(res)
+}
+
+// getGithubUserTokenFromRequest
+func (app *App) getGithubUserTokenFromRequest(r *http.Request) (*oauth2.Token, error) {
+	userID, err := app.getUserIDFromRequest(r)
+
+	if err != nil {
+		return nil, err
+	}
+
+	user, err := app.Repo.User.ReadUser(userID)
+
+	if err != nil {
+		return nil, err
+	}
+
+	oauthInt, err := app.Repo.GithubAppOAuthIntegration.ReadGithubAppOauthIntegration(user.GithubAppIntegrationID)
+
+	if err != nil {
+		return nil, err
+	}
+
+	return &oauth2.Token{
+		AccessToken:  string(oauthInt.AccessToken),
+		RefreshToken: string(oauthInt.RefreshToken),
+		TokenType:    "Bearer",
+	}, nil
+}

+ 8 - 0
server/router/router.go

@@ -188,6 +188,14 @@ func New(a *api.App) *chi.Mux {
 				requestlog.NewHandler(a.HandleGithubAppInstall, l),
 			)
 
+			r.Method(
+				"GET",
+				"/integrations/github-app/access",
+				auth.BasicAuthenticate(
+					requestlog.NewHandler(a.HandleListGithubAppAccess, l),
+				),
+			)
+
 			// /api/templates routes
 			r.Method(
 				"GET",