Alexander Belanger 5 gadi atpakaļ
vecāks
revīzija
78cd5b14a4

+ 2 - 2
internal/auth/sessionstore_test.go

@@ -34,7 +34,7 @@ func TestPGStore(t *testing.T) {
 	repo := test.NewRepository(true)
 
 	ss, err := sessionstore.NewStore(repo, config.ServerConf{
-		CookieSecrets: [][]byte{[]byte("secret")},
+		CookieSecret: []byte("secret"),
 	})
 
 	if err != nil {
@@ -134,7 +134,7 @@ func TestSessionOptionsAreUniquePerSession(t *testing.T) {
 	repo := test.NewRepository(true)
 
 	ss, err := sessionstore.NewStore(repo, config.ServerConf{
-		CookieSecrets: [][]byte{[]byte("secret")},
+		CookieSecret: []byte("secret"),
 	})
 
 	if err != nil {

+ 1 - 1
internal/config/config.go

@@ -18,7 +18,7 @@ type Conf struct {
 type ServerConf struct {
 	Port         int           `env:"SERVER_PORT,default=8080"`
 	CookieName   string        `env:"COOKIE_NAME,default=porter"`
-	CookieSecret []byte        `env:"COOKIE_SECRETS,default=secret"`
+	CookieSecret []byte        `env:"COOKIE_SECRET,default=secret"`
 	TimeoutRead  time.Duration `env:"SERVER_TIMEOUT_READ,default=5s"`
 	TimeoutWrite time.Duration `env:"SERVER_TIMEOUT_WRITE,default=10s"`
 	TimeoutIdle  time.Duration `env:"SERVER_TIMEOUT_IDLE,default=15s"`

+ 27 - 9
internal/forms/user.go

@@ -3,13 +3,14 @@ package forms
 import (
 	"github.com/porter-dev/porter/internal/kubernetes"
 	"github.com/porter-dev/porter/internal/models"
+	"github.com/porter-dev/porter/internal/repository"
 	"golang.org/x/crypto/bcrypt"
 	"gorm.io/gorm"
 )
 
 // WriteUserForm is a generic form for write operations to the User model
 type WriteUserForm interface {
-	ToUser() (*models.User, error)
+	ToUser(repo repository.UserRepository) (*models.User, error)
 }
 
 // CreateUserForm represents the accepted values for creating a user
@@ -20,7 +21,7 @@ type CreateUserForm struct {
 }
 
 // ToUser converts a CreateUserForm to models.User
-func (cuf *CreateUserForm) ToUser() (*models.User, error) {
+func (cuf *CreateUserForm) ToUser(_ repository.UserRepository) (*models.User, error) {
 	hashed, err := bcrypt.GenerateFromPassword([]byte(cuf.Password), 8)
 
 	if err != nil {
@@ -42,7 +43,7 @@ type LoginUserForm struct {
 }
 
 // ToUser converts a LoginUserForm to models.User
-func (luf *LoginUserForm) ToUser() (*models.User, error) {
+func (luf *LoginUserForm) ToUser(_ repository.UserRepository) (*models.User, error) {
 	hashed, err := bcrypt.GenerateFromPassword([]byte(luf.Password), 8)
 
 	if err != nil {
@@ -61,18 +62,35 @@ func (luf *LoginUserForm) ToUser() (*models.User, error) {
 type UpdateUserForm struct {
 	WriteUserForm
 	ID              uint     `form:"required"`
-	RawKubeConfig   string   `json:"rawKubeConfig" form:"required"`
+	RawKubeConfig   string   `json:"rawKubeConfig,omitempty"`
 	AllowedClusters []string `json:"allowedClusters,omitempty"`
 }
 
 // ToUser converts an UpdateUserForm to models.User by parsing the kubeconfig
 // and the allowed clusters to generate a list of ClusterConfigs.
-func (uuf *UpdateUserForm) ToUser() (*models.User, error) {
+func (uuf *UpdateUserForm) ToUser(repo repository.UserRepository) (*models.User, error) {
 	rawBytes := []byte(uuf.RawKubeConfig)
-	clusters, err := kubernetes.GetAllowedClusterConfigsFromBytes(rawBytes, uuf.AllowedClusters)
 
-	if err != nil {
-		return nil, err
+	// if the rawKubeConfig is empty, query the DB for a non-empty one
+	if uuf.RawKubeConfig == "" {
+		savedUser, err := repo.ReadUser(uuf.ID)
+
+		if err != nil {
+			return nil, err
+		}
+
+		rawBytes = savedUser.RawKubeConfig
+	}
+
+	clusters := make([]models.ClusterConfig, 0)
+	var err error
+
+	if len(rawBytes) > 0 {
+		clusters, err = kubernetes.GetAllowedClusterConfigsFromBytes(rawBytes, uuf.AllowedClusters)
+
+		if err != nil {
+			return nil, err
+		}
 	}
 
 	return &models.User{
@@ -92,7 +110,7 @@ type DeleteUserForm struct {
 }
 
 // ToUser converts a DeleteUserForm to models.User using the user ID
-func (uuf *DeleteUserForm) ToUser() (*models.User, error) {
+func (uuf *DeleteUserForm) ToUser(_ repository.UserRepository) (*models.User, error) {
 	return &models.User{
 		Model: gorm.Model{
 			ID: uuf.ID,

+ 2 - 2
server/api/user_handler.go

@@ -123,7 +123,7 @@ func (app *App) HandleLogoutUser(w http.ResponseWriter, r *http.Request) {
 	session, err := app.store.Get(r, app.cookieName)
 
 	if err != nil {
-		app.handleErrorDataRead(err, ErrUserDataRead, w)
+		app.handleErrorDataRead(err, w)
 	}
 
 	session.Values["authenticated"] = false
@@ -274,7 +274,7 @@ func (app *App) writeUser(
 	}
 
 	// convert the form to a user model -- WriteUserForm must implement ToUser
-	userModel, err := form.ToUser()
+	userModel, err := form.ToUser(app.repo.User)
 
 	if err != nil {
 		app.handleErrorFormDecoding(err, ErrUserDecode, w)

+ 46 - 8
server/api/user_handler_test.go

@@ -2,7 +2,6 @@ package api_test
 
 import (
 	"encoding/json"
-	"fmt"
 	"net/http"
 	"net/http/httptest"
 	"reflect"
@@ -96,12 +95,12 @@ func newTester(canQuery bool) *tester {
 	appConf := config.Conf{
 		Debug: true,
 		Server: config.ServerConf{
-			Port:          8080,
-			CookieName:    "porter",
-			CookieSecrets: [][]byte{[]byte("secret")},
-			TimeoutRead:   time.Second * 5,
-			TimeoutWrite:  time.Second * 10,
-			TimeoutIdle:   time.Second * 15,
+			Port:         8080,
+			CookieName:   "porter",
+			CookieSecret: []byte("secret"),
+			TimeoutRead:  time.Second * 5,
+			TimeoutWrite: time.Second * 10,
+			TimeoutIdle:  time.Second * 15,
 		},
 		// unimportant here
 		Db: config.DBConf{},
@@ -607,7 +606,46 @@ var updateUserTests = []*userTest{
 				json.Unmarshal(rr2.Body.Bytes(), gotBody)
 				json.Unmarshal([]byte(`{"id":1,"email":"belanger@getporter.dev","clusters":[{"name":"cluster-test","server":"https://localhost","context":"context-test","user":"test-admin"}],"rawKubeConfig":"apiVersion: v1\nkind: Config\npreferences: {}\ncurrent-context: context-test\nclusters:\n- cluster:\n    server: https://localhost\n  name: cluster-test\ncontexts:\n- context:\n    cluster: cluster-test\n    user: test-admin\n  name: context-test\nusers:\n- name: test-admin"}`), expBody)
 
-				fmt.Println(gotBody.Clusters[0], expBody.Clusters[0])
+				if !reflect.DeepEqual(gotBody, expBody) {
+					t.Errorf("%s, handler returned wrong body: got %v want %v",
+						"validator failed", gotBody, expBody)
+				}
+			},
+		},
+	},
+	&userTest{
+		initializers: []func(tester *tester){
+			initUserWithClusters,
+		},
+		msg:       "Update user successful without rawKubeConfig",
+		method:    "PUT",
+		endpoint:  "/api/users/1",
+		body:      `{"allowedClusters":[]}`,
+		expStatus: http.StatusNoContent,
+		expBody:   "",
+		useCookie: true,
+		validators: []func(c *userTest, tester *tester, t *testing.T){
+			func(c *userTest, tester *tester, t *testing.T) {
+				req, err := http.NewRequest(
+					"GET",
+					"/api/users/1",
+					strings.NewReader(""),
+				)
+
+				req.AddCookie(tester.cookie)
+
+				if err != nil {
+					t.Fatal(err)
+				}
+
+				rr2 := httptest.NewRecorder()
+				tester.router.ServeHTTP(rr2, req)
+
+				gotBody := &models.UserExternal{}
+				expBody := &models.UserExternal{}
+
+				json.Unmarshal(rr2.Body.Bytes(), gotBody)
+				json.Unmarshal([]byte(`{"id":1,"email":"belanger@getporter.dev","clusters":[],"rawKubeConfig":"apiVersion: v1\nkind: Config\npreferences: {}\ncurrent-context: context-test\nclusters:\n- cluster:\n    server: https://localhost\n  name: cluster-test\ncontexts:\n- context:\n    cluster: cluster-test\n    user: test-admin\n  name: context-test\nusers:\n- name: test-admin"}`), expBody)
 
 				if !reflect.DeepEqual(gotBody, expBody) {
 					t.Errorf("%s, handler returned wrong body: got %v want %v",