Added support for jwt secret creation of each user upon user login (#4719)

* Added support for jwt secret creation of each user upon logic

Signed-off-by: Saranya-jena <saranya.jena@harness.io>

* Fixed imports

Signed-off-by: Saranya-jena <saranya.jena@harness.io>

* Add fixes in dex service

Signed-off-by: Saranya-jena <saranya.jena@harness.io>

* Fixed UTs

Signed-off-by: Saranya-jena <saranya.jena@harness.io>

* resolved comments

Signed-off-by: Saranya-jena <saranya.jena@harness.io>

* updated logic

Signed-off-by: Saranya-jena <saranya.jena@harness.io>

* fixed UTs and removed unecessary test cases

Signed-off-by: Saranya-jena <saranya.jena@harness.io>

* fixed imports

Signed-off-by: Saranya-jena <saranya.jena@harness.io>

* fixed imports

Signed-off-by: Saranya-jena <saranya.jena@harness.io>

* resolved comments

Signed-off-by: Saranya-jena <saranya.jena@harness.io>

* fixed imports

Signed-off-by: Saranya-jena <saranya.jena@harness.io>

* resolved comments

Signed-off-by: Saranya-jena <saranya.jena@harness.io>

* added server endpoint in allowed origins

Signed-off-by: Saranya-jena <saranya.jena@harness.io>

* fixed imports

Signed-off-by: Saranya-jena <saranya.jena@harness.io>

* minor chnages

Signed-off-by: Saranya-jena <saranya.jena@harness.io>

* minor chnages

Signed-off-by: Saranya-jena <saranya.jena@harness.io>

* fixed imports

Signed-off-by: Saranya-jena <saranya.jena@harness.io>

---------

Signed-off-by: Saranya-jena <saranya.jena@harness.io>
This commit is contained in:
Saranya Jena 2024-07-05 15:14:07 +05:30 committed by GitHub
parent fb46bb9334
commit 9d58d8b584
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
38 changed files with 455 additions and 270 deletions

View File

@ -138,7 +138,15 @@ func DexCallback(userService services.ApplicationService) gin.HandlerFunc {
c.JSON(utils.ErrorStatusCodes[utils.ErrServerError], presenter.CreateErrorResponse(utils.ErrServerError))
return
}
jwtToken, err := userService.GetSignedJWT(signedInUser)
salt, err := userService.GetConfig("salt")
if err != nil {
log.Error(err)
c.JSON(utils.ErrorStatusCodes[utils.ErrServerError], presenter.CreateErrorResponse(utils.ErrServerError))
return
}
jwtToken, err := userService.GetSignedJWT(signedInUser, salt.Value)
if err != nil {
log.Error(err)
c.JSON(utils.ErrorStatusCodes[utils.ErrServerError], presenter.CreateErrorResponse(utils.ErrServerError))

View File

@ -5,12 +5,11 @@ import (
"strings"
"time"
"github.com/litmuschaos/litmus/chaoscenter/authentication/pkg/validations"
"github.com/litmuschaos/litmus/chaoscenter/authentication/api/presenter"
"github.com/litmuschaos/litmus/chaoscenter/authentication/pkg/entities"
"github.com/litmuschaos/litmus/chaoscenter/authentication/pkg/services"
"github.com/litmuschaos/litmus/chaoscenter/authentication/pkg/utils"
"github.com/litmuschaos/litmus/chaoscenter/authentication/pkg/validations"
"github.com/gin-gonic/gin"
"github.com/google/uuid"
@ -305,7 +304,13 @@ func LoginUser(service services.ApplicationService) gin.HandlerFunc {
return
}
token, err := service.GetSignedJWT(user)
salt, err := service.GetConfig("salt")
if err != nil {
c.JSON(utils.ErrorStatusCodes[utils.ErrServerError], presenter.CreateErrorResponse(utils.ErrServerError))
return
}
token, err := service.GetSignedJWT(user, salt.Value)
if err != nil {
log.Error(err)
c.JSON(utils.ErrorStatusCodes[utils.ErrServerError], presenter.CreateErrorResponse(utils.ErrServerError))

View File

@ -13,6 +13,8 @@ import (
"strings"
"testing"
"github.com/litmuschaos/litmus/chaoscenter/authentication/pkg/authConfig"
"go.mongodb.org/mongo-driver/bson/primitive"
"github.com/gin-gonic/gin"
@ -408,9 +410,11 @@ func TestLoginUser(t *testing.T) {
Password: "hashedPassword",
Email: "test@example.com",
}
service.On("GetConfig", "salt").Return(&authConfig.AuthConfig{}, nil)
service.On("FindUserByUsername", "testUser").Return(userFromDB, nil)
service.On("CheckPasswordHash", "hashedPassword", "testPassword").Return(nil)
service.On("GetSignedJWT", userFromDB).Return("someJWTToken", nil)
service.On("UpdateUserByQuery", mock.Anything, mock.Anything).Return(nil)
service.On("GetSignedJWT", userFromDB, mock.Anything).Return("someJWTToken", nil)
project := &entities.Project{
ID: "someProjectID",
}

View File

@ -0,0 +1,44 @@
package response
import (
"encoding/base64"
"github.com/litmuschaos/litmus/chaoscenter/authentication/pkg/authConfig"
"github.com/litmuschaos/litmus/chaoscenter/authentication/pkg/services"
"github.com/litmuschaos/litmus/chaoscenter/authentication/pkg/utils"
log "github.com/sirupsen/logrus"
"go.mongodb.org/mongo-driver/mongo"
)
func AddSalt(service services.ApplicationService) error {
// generate salt and add/update to user collection
// pass the salt in the below func which will act as jwt secret
getSalt, err := service.GetConfig("salt")
if err != nil && err != mongo.ErrNoDocuments {
log.Error(err)
return err
}
if getSalt != nil {
return nil
}
salt, err := utils.RandomString(6)
if err != nil {
log.Error(err)
return err
}
encodedSalt := base64.StdEncoding.EncodeToString([]byte(salt))
config := authConfig.AuthConfig{
Key: "salt",
Value: encodedSalt,
}
err = service.CreateConfig(config)
if err != nil {
log.Error(err)
return err
}
return nil
}

View File

@ -7,6 +7,9 @@ import (
"runtime"
"time"
response "github.com/litmuschaos/litmus/chaoscenter/authentication/api/handlers"
"github.com/litmuschaos/litmus/chaoscenter/authentication/pkg/authConfig"
grpcHandler "github.com/litmuschaos/litmus/chaoscenter/authentication/api/handlers/grpc"
"github.com/litmuschaos/litmus/chaoscenter/authentication/api/middleware"
grpcPresenter "github.com/litmuschaos/litmus/chaoscenter/authentication/api/presenter/protos"
@ -82,6 +85,12 @@ func main() {
log.Errorf("failed to create collection %s", err)
}
// Creating AuthConfig Collection
err = utils.CreateCollection(utils.AuthConfigCollection, db)
if err != nil {
log.Errorf("failed to create collection %s", err)
}
// Creating RevokedToken Collection
if err = utils.CreateCollection(utils.RevokedTokenCollection, db); err != nil {
log.Errorf("failed to create collection %s", err)
@ -108,9 +117,17 @@ func main() {
apiTokenCollection := db.Collection(utils.ApiTokenCollection)
apiTokenRepo := session.NewApiTokenRepo(apiTokenCollection)
authConfigCollection := db.Collection(utils.AuthConfigCollection)
authConfigRepo := authConfig.NewAuthConfigRepo(authConfigCollection)
miscRepo := misc.NewRepo(db, client)
applicationService := services.NewService(userRepo, projectRepo, miscRepo, revokedTokenRepo, apiTokenRepo, db)
applicationService := services.NewService(userRepo, projectRepo, miscRepo, revokedTokenRepo, apiTokenRepo, authConfigRepo, db)
err = response.AddSalt(applicationService)
if err != nil {
log.Fatal("couldn't create salt $s", err)
}
validatedAdminSetup(applicationService)
@ -163,10 +180,10 @@ func runRestServer(applicationService services.ApplicationService) {
if utils.DexEnabled {
routes.DexRouter(app, applicationService)
}
routes.CapabilitiesRouter(app)
routes.MiscRouter(app, applicationService)
routes.UserRouter(app, applicationService)
routes.ProjectRouter(app, applicationService)
routes.CapabilitiesRouter(app)
log.Infof("Listening and serving HTTP on %s", utils.Port)
err := app.Run(utils.Port)

View File

@ -3,6 +3,8 @@ package mocks
import (
"context"
"github.com/litmuschaos/litmus/chaoscenter/authentication/pkg/authConfig"
"github.com/golang-jwt/jwt"
"github.com/litmuschaos/litmus/chaoscenter/authentication/pkg/entities"
"github.com/stretchr/testify/mock"
@ -70,6 +72,11 @@ func (m *MockedApplicationService) UpdateUser(user *entities.UserDetails) error
return args.Error(0)
}
func (m *MockedApplicationService) UpdateUserByQuery(filter bson.D, updateQuery bson.D) error {
args := m.Called(filter, updateQuery)
return args.Error(0)
}
func (m *MockedApplicationService) UpdateUserState(ctx context.Context, username string, isDeactivate bool, deactivateTime int64) error {
args := m.Called(ctx, username, isDeactivate, deactivateTime)
return args.Error(0)
@ -160,8 +167,8 @@ func (m *MockedApplicationService) ValidateToken(encodedToken string) (*jwt.Toke
return args.Get(0).(*jwt.Token), args.Error(1)
}
func (m *MockedApplicationService) GetSignedJWT(user *entities.User) (string, error) {
args := m.Called(user)
func (m *MockedApplicationService) GetSignedJWT(user *entities.User, jwtSecret string) (string, error) {
args := m.Called(user, jwtSecret)
return args.String(0), args.Error(1)
}
@ -199,3 +206,18 @@ func (m *MockedApplicationService) RbacValidator(userID, resourceID string, rule
args := m.Called(userID, resourceID, rules, invitationStatus)
return args.Error(0)
}
func (m *MockedApplicationService) CreateConfig(config authConfig.AuthConfig) error {
args := m.Called(config)
return args.Error(0)
}
func (m *MockedApplicationService) GetConfig(key string) (*authConfig.AuthConfig, error) {
args := m.Called(key)
return args.Get(0).(*authConfig.AuthConfig), args.Error(1)
}
func (m *MockedApplicationService) UpdateConfig(ctx context.Context, key string, value interface{}) error {
args := m.Called(ctx, key, value)
return args.Error(0)
}

View File

@ -0,0 +1,67 @@
package authConfig
import (
"context"
"encoding/base64"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
)
type Repository interface {
CreateConfig(config AuthConfig) error
GetConfig(key string) (*AuthConfig, error)
UpdateConfig(ctx context.Context, key string, value interface{}) error
}
type repository struct {
Collection *mongo.Collection
}
func (r repository) CreateConfig(config AuthConfig) error {
_, err := r.Collection.InsertOne(context.Background(), config)
if err != nil {
return err
}
return nil
}
func (r repository) GetConfig(key string) (*AuthConfig, error) {
results := r.Collection.FindOne(context.Background(), bson.D{
{"key", key},
})
var config AuthConfig
err := results.Decode(&config)
if err != nil {
return nil, err
}
decodedValue, err := base64.URLEncoding.DecodeString(config.Value)
if err != nil {
return nil, err
}
config.Value = string(decodedValue)
return &config, nil
}
func (r repository) UpdateConfig(ctx context.Context, key string, value interface{}) error {
query := bson.D{
{"key", key},
}
update := bson.D{{"$set", bson.D{{
"value", value}},
}}
_, err := r.Collection.UpdateOne(ctx, query, update)
if err != nil {
return err
}
return nil
}
// NewAuthConfigRepo creates a new instance of this repository
func NewAuthConfigRepo(collection *mongo.Collection) Repository {
return &repository{
Collection: collection,
}
}

View File

@ -0,0 +1,6 @@
package authConfig
type AuthConfig struct {
Key string `bson:"key"`
Value string `bson:"value"`
}

View File

@ -21,6 +21,7 @@ type User struct {
ID string `bson:"_id,omitempty" json:"userID"`
Username string `bson:"username,omitempty" json:"username"`
Password string `bson:"password,omitempty" json:"password,omitempty"`
Salt string `bson:"salt" json:"salt"`
Email string `bson:"email,omitempty" json:"email,omitempty"`
Name string `bson:"name,omitempty" json:"name,omitempty"`
Role Role `bson:"role,omitempty" json:"role"`

View File

@ -1,6 +1,7 @@
package services
import (
authConfig2 "github.com/litmuschaos/litmus/chaoscenter/authentication/pkg/authConfig"
"github.com/litmuschaos/litmus/chaoscenter/authentication/pkg/misc"
"github.com/litmuschaos/litmus/chaoscenter/authentication/pkg/project"
"github.com/litmuschaos/litmus/chaoscenter/authentication/pkg/session"
@ -14,6 +15,7 @@ type ApplicationService interface {
transactionService
miscService
sessionService
authConfigService
}
type applicationService struct {
@ -22,17 +24,19 @@ type applicationService struct {
miscRepository misc.Repository
revokedTokenRepository session.RevokedTokenRepository
apiTokenRepository session.ApiTokenRepository
authConfigRepo authConfig2.Repository
db *mongo.Database
}
// NewService creates a new instance of this service
func NewService(userRepo user.Repository, projectRepo project.Repository, miscRepo misc.Repository, revokedTokenRepo session.RevokedTokenRepository, apiTokenRepo session.ApiTokenRepository, db *mongo.Database) ApplicationService {
func NewService(userRepo user.Repository, projectRepo project.Repository, miscRepo misc.Repository, revokedTokenRepo session.RevokedTokenRepository, apiTokenRepo session.ApiTokenRepository, authConfigRepo authConfig2.Repository, db *mongo.Database) ApplicationService {
return &applicationService{
userRepository: userRepo,
projectRepository: projectRepo,
revokedTokenRepository: revokedTokenRepo,
apiTokenRepository: apiTokenRepo,
db: db,
authConfigRepo: authConfigRepo,
miscRepository: miscRepo,
}
}

View File

@ -0,0 +1,25 @@
package services
import (
"context"
"github.com/litmuschaos/litmus/chaoscenter/authentication/pkg/authConfig"
)
type authConfigService interface {
CreateConfig(config authConfig.AuthConfig) error
GetConfig(key string) (*authConfig.AuthConfig, error)
UpdateConfig(ctx context.Context, key string, value interface{}) error
}
func (a applicationService) CreateConfig(config authConfig.AuthConfig) error {
return a.authConfigRepo.CreateConfig(config)
}
func (a applicationService) GetConfig(key string) (*authConfig.AuthConfig, error) {
return a.authConfigRepo.GetConfig(key)
}
func (a applicationService) UpdateConfig(ctx context.Context, key string, value interface{}) error {
return a.authConfigRepo.UpdateConfig(ctx, key, value)
}

View File

@ -14,7 +14,7 @@ import (
type sessionService interface {
RevokeToken(tokenString string) error
ValidateToken(encodedToken string) (*jwt.Token, error)
GetSignedJWT(user *entities.User) (string, error)
GetSignedJWT(user *entities.User, jwtSecret string) (string, error)
CreateApiToken(user *entities.User, request entities.ApiTokenInput) (string, error)
GetApiTokensByUserID(userID string) ([]entities.ApiToken, error)
DeleteApiToken(token string) error
@ -58,12 +58,17 @@ func (a applicationService) parseToken(encodedToken string) (*jwt.Token, error)
if _, isValid := token.Method.(*jwt.SigningMethodHMAC); !isValid {
return nil, fmt.Errorf("invalid token %s", token.Header["alg"])
}
return []byte(utils.JwtSecret), nil
salt, err := a.GetConfig("salt")
if err != nil {
log.Error(err)
return nil, fmt.Errorf("couldn't fetch jwt secret %v", err)
}
return []byte(salt.Value), nil
})
}
// GetSignedJWT generates the JWT Token for the user object
func (a applicationService) GetSignedJWT(user *entities.User) (string, error) {
func (a applicationService) GetSignedJWT(user *entities.User, jwtSecret string) (string, error) {
token := jwt.New(jwt.SigningMethodHS512)
claims := token.Claims.(jwt.MapClaims)
claims["uid"] = user.ID
@ -71,7 +76,7 @@ func (a applicationService) GetSignedJWT(user *entities.User) (string, error) {
claims["username"] = user.Username
claims["exp"] = time.Now().Add(time.Minute * time.Duration(utils.JWTExpiryDuration)).Unix()
tokenString, err := token.SignedString([]byte(utils.JwtSecret))
tokenString, err := token.SignedString([]byte(jwtSecret))
if err != nil {
log.Error(err)
return "", err
@ -90,7 +95,12 @@ func (a applicationService) CreateApiToken(user *entities.User, request entities
claims["username"] = user.Username
claims["exp"] = expiresAt
tokenString, err := token.SignedString([]byte(utils.JwtSecret))
salt, err := a.GetConfig("salt")
if err != nil {
log.Error(err)
return "", fmt.Errorf("couldn't fetch jwt secret %v", err)
}
tokenString, err := token.SignedString([]byte(salt.Value))
if err != nil {
log.Error(err)
return "", err

View File

@ -3,6 +3,8 @@ package services
import (
"context"
"go.mongodb.org/mongo-driver/bson"
"github.com/litmuschaos/litmus/chaoscenter/authentication/pkg/entities"
)
@ -17,6 +19,7 @@ type userService interface {
UpdatePassword(userPassword *entities.UserPassword, isAdminBeingReset bool) error
CreateUser(user *entities.User) (*entities.User, error)
UpdateUser(user *entities.UserDetails) error
UpdateUserByQuery(filter bson.D, updateQuery bson.D) error
IsAdministrator(user *entities.User) error
UpdateUserState(ctx context.Context, username string, isDeactivate bool, deactivateTime int64) error
InviteUsers(invitedUsers []string) (*[]entities.User, error)
@ -67,6 +70,11 @@ func (a applicationService) UpdateUser(user *entities.UserDetails) error {
return a.userRepository.UpdateUser(user)
}
// UpdateUserByQuery updates user details in the database
func (a applicationService) UpdateUserByQuery(filter bson.D, updateQuery bson.D) error {
return a.userRepository.UpdateUserByQuery(filter, updateQuery)
}
// IsAdministrator verifies if the passed user is an administrator
func (a applicationService) IsAdministrator(user *entities.User) error {
return a.userRepository.IsAdministrator(user)

View File

@ -26,6 +26,7 @@ type Repository interface {
UpdatePassword(userPassword *entities.UserPassword, isAdminBeingReset bool) error
CreateUser(user *entities.User) (*entities.User, error)
UpdateUser(user *entities.UserDetails) error
UpdateUserByQuery(filter bson.D, updateQuery bson.D) error
IsAdministrator(user *entities.User) error
UpdateUserState(ctx context.Context, username string, isDeactivate bool, deactivateTime int64) error
InviteUsers(invitedUsers []string) (*[]entities.User, error)
@ -222,10 +223,20 @@ func (r repository) CreateUser(user *entities.User) (*entities.User, error) {
return user.SanitizedUser(), nil
}
// UpdateUserByQuery updates user details in the database
func (r repository) UpdateUserByQuery(filter bson.D, updateQuery bson.D) error {
_, err := r.Collection.UpdateOne(context.Background(), filter, updateQuery)
if err != nil {
return err
}
return nil
}
// UpdateUser updates user details in the database
func (r repository) UpdateUser(user *entities.UserDetails) error {
data, _ := toDoc(user)
_, err := r.Collection.UpdateOne(context.Background(), bson.M{"_id": user.ID}, bson.M{"$set": data})
_, err := r.Collection.UpdateMany(context.Background(), bson.M{"_id": user.ID}, bson.M{"$set": data})
if err != nil {
return err
}

View File

@ -6,7 +6,6 @@ import (
)
var (
JwtSecret = os.Getenv("JWT_SECRET")
AdminName = os.Getenv("ADMIN_USERNAME")
AdminPassword = os.Getenv("ADMIN_PASSWORD")
DBUrl = os.Getenv("DB_SERVER")
@ -26,6 +25,7 @@ var (
GrpcPort = ":3030"
UserCollection = "users"
ProjectCollection = "project"
AuthConfigCollection = "auth-config"
RevokedTokenCollection = "revoked-token"
ApiTokenCollection = "api-token"
UsernameField = "username"

View File

@ -1,6 +1,8 @@
package utils
import (
crypto "crypto/rand"
"encoding/base64"
"fmt"
"regexp"
"strings"
@ -47,6 +49,20 @@ func ValidateStrictPassword(input string) error {
return nil
}
// RandomString generates random strings, can be used to create ids
func RandomString(n int) (string, error) {
if n > 0 {
b := make([]byte, n)
_, err := crypto.Read(b)
if err != nil {
return "", err
}
return base64.URLEncoding.EncodeToString(b), nil
}
return "", fmt.Errorf("length should be greater than 0")
}
// Username must start with a letter - ^[a-zA-Z]
// Allow letters, digits, underscores, and hyphens - [a-zA-Z0-9_-]
// Ensure the length of the username is between 3 and 16 characters (1 character is already matched above) - {2,15}$

View File

@ -5,6 +5,10 @@ import (
"regexp"
"strings"
"github.com/sirupsen/logrus"
"github.com/litmuschaos/litmus/chaoscenter/graphql/server/pkg/chaos_infrastructure"
"github.com/gin-gonic/gin"
"github.com/litmuschaos/litmus/chaoscenter/graphql/server/utils"
)
@ -25,6 +29,13 @@ func ValidateCors() gin.HandlerFunc {
}
validOrigin := false
endpoint, err := chaos_infrastructure.GetEndpoint("external")
if err != nil {
logrus.Error(err)
} else if endpoint != "" {
allowedOrigins = append(allowedOrigins, endpoint)
}
for _, allowedOrigin := range allowedOrigins {
match, err := regexp.MatchString(allowedOrigin, origin)
if err == nil && match {

View File

@ -30,7 +30,7 @@ func (r *mutationResolver) CreateChaosExperiment(ctx context.Context, request mo
return nil, err
}
uiResponse, err := r.chaosExperimentHandler.CreateChaosExperiment(ctx, &request, projectID)
uiResponse, err := r.chaosExperimentHandler.CreateChaosExperiment(ctx, &request, projectID, ctx.Value("username").(string))
if err != nil {
return nil, errors.New("could not create experiment, error: " + err.Error())
}
@ -83,7 +83,7 @@ func (r *mutationResolver) SaveChaosExperiment(ctx context.Context, request mode
var uiResponse string
uiResponse, err = r.chaosExperimentHandler.SaveChaosExperiment(ctx, request, projectID, data_store.Store)
uiResponse, err = r.chaosExperimentHandler.SaveChaosExperiment(ctx, request, projectID, ctx.Value(authorization.AuthKey).(string))
if err != nil {
logrus.WithFields(logFields).Error(err)
return "", err
@ -107,7 +107,7 @@ func (r *mutationResolver) UpdateChaosExperiment(ctx context.Context, request mo
return nil, err
}
uiResponse, err := r.chaosExperimentHandler.UpdateChaosExperiment(ctx, request, projectID, data_store.Store)
uiResponse, err := r.chaosExperimentHandler.UpdateChaosExperiment(ctx, request, projectID, data_store.Store, ctx.Value(authorization.AuthKey).(string))
if err != nil {
logrus.WithFields(logFields).Error(err)
return nil, err
@ -132,7 +132,7 @@ func (r *mutationResolver) DeleteChaosExperiment(ctx context.Context, experiment
return false, err
}
uiResponse, err := r.chaosExperimentHandler.DeleteChaosExperiment(ctx, projectID, experimentID, experimentRunID, data_store.Store)
uiResponse, err := r.chaosExperimentHandler.DeleteChaosExperiment(ctx, projectID, experimentID, experimentRunID, data_store.Store, ctx.Value(authorization.AuthKey).(string))
if err != nil {
logrus.WithFields(logFields).Error(err)
return false, err
@ -156,7 +156,7 @@ func (r *mutationResolver) UpdateCronExperimentState(ctx context.Context, experi
return false, err
}
uiResponse, err := r.chaosExperimentHandler.UpdateCronExperimentState(ctx, experimentID, disable, projectID, data_store.Store)
uiResponse, err := r.chaosExperimentHandler.UpdateCronExperimentState(ctx, experimentID, disable, projectID, data_store.Store, ctx.Value(authorization.AuthKey).(string))
if err != nil {
logrus.WithFields(logFields).Error(err)
return false, err

View File

@ -73,7 +73,7 @@ func (r *mutationResolver) StopExperimentRuns(ctx context.Context, projectID str
return false, err
}
uiResponse, err := r.chaosExperimentHandler.StopExperimentRuns(ctx, projectID, experimentID, experimentRunID, data_store.Store)
uiResponse, err := r.chaosExperimentHandler.StopExperimentRuns(ctx, projectID, experimentID, experimentRunID, data_store.Store, "")
if err != nil {
logrus.WithFields(logFields).Error(err)
return false, err

View File

@ -24,7 +24,8 @@ func (r *mutationResolver) CreateEnvironment(ctx context.Context, projectID stri
if err != nil {
return nil, err
}
return r.environmentService.CreateEnvironment(ctx, projectID, request)
return r.environmentService.CreateEnvironment(ctx, projectID, request, ctx.Value(authorization.AuthKey).(string))
}
// UpdateEnvironment is the resolver for the updateEnvironment field.
@ -40,7 +41,8 @@ func (r *mutationResolver) UpdateEnvironment(ctx context.Context, projectID stri
if err != nil {
return "", err
}
return r.environmentService.UpdateEnvironment(ctx, projectID, request)
return r.environmentService.UpdateEnvironment(ctx, projectID, request, ctx.Value(authorization.AuthKey).(string))
}
// DeleteEnvironment is the resolver for the deleteEnvironment field.
@ -56,7 +58,8 @@ func (r *mutationResolver) DeleteEnvironment(ctx context.Context, projectID stri
if err != nil {
return "", err
}
return r.environmentService.DeleteEnvironment(ctx, projectID, environmentID)
return r.environmentService.DeleteEnvironment(ctx, projectID, environmentID, ctx.Value(authorization.AuthKey).(string))
}
// GetEnvironment is the resolver for the getEnvironment field.

View File

@ -3,6 +3,8 @@ package graph
import (
"context"
"github.com/litmuschaos/litmus/chaoscenter/graphql/server/pkg/database/mongodb/authConfig"
chaos_experiment2 "github.com/litmuschaos/litmus/chaoscenter/graphql/server/pkg/chaos_experiment/ops"
"github.com/99designs/gqlgen/graphql"
@ -84,11 +86,17 @@ func NewConfig(mongodbOperator mongodb.MongoOperator) generated.Config {
config.Directives.Authorized = func(ctx context.Context, obj interface{}, next graphql.Resolver) (interface{}, error) {
token := ctx.Value(authorization.AuthKey).(string)
user, err := authorization.UserValidateJWT(token)
salt, err := authConfig.NewAuthConfigOperator(mongodb.Operator).GetAuthConfig(context.Background())
if err != nil {
return "", err
}
user, err := authorization.UserValidateJWT(token, salt.Value)
if err != nil {
return nil, err
}
newCtx := context.WithValue(ctx, authorization.UserClaim, user)
newCtx = context.WithValue(ctx, "username", user["username"])
return next(newCtx)
}

View File

@ -1,14 +1,12 @@
package authorization
import (
"encoding/base64"
"fmt"
"testing"
"time"
fuzz "github.com/AdaLogics/go-fuzz-headers"
"github.com/golang-jwt/jwt"
"github.com/litmuschaos/litmus/chaoscenter/graphql/server/utils"
)
// generateExpiredFakeJWTToken generates a fake JWT token with expiration time set to the past
@ -37,59 +35,11 @@ func generateFakeJWTToken(username string) string {
"username": username,
"exp": time.Now().Add(time.Hour * 24).Unix(), // Set expiration time to 24 hours from now
})
signedToken, _ := token.SignedString([]byte(utils.Config.JwtSecret)) // No signature is needed for testing
fakeSecret := ""
signedToken, _ := token.SignedString([]byte(fakeSecret)) // No signature is needed for testing
return signedToken
}
func FuzzGetUsername(f *testing.F) {
f.Fuzz(func(t *testing.T, input string) {
// Create a fake JWT token with predefined claims
// Invalid token format check
_, err := GetUsername(input)
if err == nil {
t.Error("Expected error for invalid token format")
}
// Generating fake jwt token for testing
token := generateFakeJWTToken(base64.StdEncoding.EncodeToString([]byte(input)))
// Run the test with the fake JWT token
username, err := GetUsername(token)
if err != nil {
t.Errorf("Error encountered: %v", err)
}
// Decode the username back from base64
decodedUsername, err := base64.StdEncoding.DecodeString(username)
if err != nil {
t.Errorf("Error decoding username: %v", err)
}
// Check if the decoded username matches the input string
if string(decodedUsername) != input {
t.Errorf("Expected username: %s, got: %s", input, username)
}
// Additional checks
// Expiration check
expiredToken := generateExpiredFakeJWTToken(input)
_, err = GetUsername(expiredToken)
if err == nil {
t.Error("Expected error for expired token")
}
// Token signature check (invalid secret key)
invalidSignatureToken := generateFakeJWTTokenWithInvalidSignature(input)
_, err = GetUsername(invalidSignatureToken)
if err == nil {
t.Error("Expected error for token with invalid signature")
}
})
}
// generateJWTToken generates a JWT token with the given claims
func generateJWTTokenFromClaims(claims jwt.MapClaims) (string, error) {
// Set expiration time to 24 hours from now
@ -99,7 +49,7 @@ func generateJWTTokenFromClaims(claims jwt.MapClaims) (string, error) {
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
// Sign the token with a secret key
tokenString, err := token.SignedString([]byte(utils.Config.JwtSecret))
tokenString, err := token.SignedString([]byte(""))
if err != nil {
return "", fmt.Errorf("failed to sign JWT token: %v", err)
}
@ -122,7 +72,7 @@ func FuzzUserValidateJWT(f *testing.F) {
}
// Run the test with the generated JWT token
claims, err := UserValidateJWT(tokenString)
claims, err := UserValidateJWT(tokenString, "")
if err != nil {
t.Errorf("Error encountered: %v", err)
}

View File

@ -1,22 +1,24 @@
package authorization
import (
"context"
"errors"
"fmt"
"log"
"github.com/litmuschaos/litmus/chaoscenter/graphql/server/utils"
"github.com/litmuschaos/litmus/chaoscenter/graphql/server/pkg/database/mongodb"
"github.com/litmuschaos/litmus/chaoscenter/graphql/server/pkg/database/mongodb/authConfig"
"github.com/golang-jwt/jwt"
)
// UserValidateJWT validates the cluster jwt
func UserValidateJWT(token string) (jwt.MapClaims, error) {
func UserValidateJWT(token string, salt string) (jwt.MapClaims, error) {
tkn, err := jwt.Parse(token, func(token *jwt.Token) (interface{}, error) {
if _, isValid := token.Method.(*jwt.SigningMethodHMAC); !isValid {
return nil, fmt.Errorf("invalid token %s", token.Header["alg"])
}
return []byte(utils.Config.JwtSecret), nil
return []byte(salt), nil
})
if err != nil {
@ -38,8 +40,12 @@ func UserValidateJWT(token string) (jwt.MapClaims, error) {
// GetUsername returns the username from the jwt token
func GetUsername(token string) (string, error) {
salt, err := authConfig.NewAuthConfigOperator(mongodb.Operator).GetAuthConfig(context.Background())
if err != nil {
return "", err
}
tkn, err := jwt.Parse(token, func(token *jwt.Token) (interface{}, error) {
return []byte(utils.Config.JwtSecret), nil
return []byte(salt.Value), nil
})
if err != nil {

View File

@ -12,16 +12,13 @@ import (
dbGitOpsMocks "github.com/litmuschaos/litmus/chaoscenter/graphql/server/pkg/gitops/model/mocks"
fuzz "github.com/AdaLogics/go-fuzz-headers"
"github.com/golang-jwt/jwt"
"github.com/google/uuid"
"github.com/litmuschaos/litmus/chaoscenter/graphql/server/graph/model"
"github.com/litmuschaos/litmus/chaoscenter/graphql/server/pkg/authorization"
store "github.com/litmuschaos/litmus/chaoscenter/graphql/server/pkg/data-store"
"github.com/litmuschaos/litmus/chaoscenter/graphql/server/pkg/database/mongodb"
dbChaosExperiment "github.com/litmuschaos/litmus/chaoscenter/graphql/server/pkg/database/mongodb/chaos_experiment"
dbChaosExperimentRun "github.com/litmuschaos/litmus/chaoscenter/graphql/server/pkg/database/mongodb/chaos_experiment_run"
dbChoasInfra "github.com/litmuschaos/litmus/chaoscenter/graphql/server/pkg/database/mongodb/chaos_infrastructure"
"github.com/litmuschaos/litmus/chaoscenter/graphql/server/utils"
"github.com/sirupsen/logrus"
"github.com/stretchr/testify/mock"
"go.mongodb.org/mongo-driver/bson"
@ -75,9 +72,7 @@ func FuzzSaveChaosExperiment(f *testing.F) {
if err != nil {
return
}
username, _ := jwt.NewWithClaims(jwt.SigningMethodHS512, jwt.MapClaims{"username": "test"}).SignedString([]byte(utils.Config.JwtSecret))
ctx := context.Background()
ctx = context.WithValue(ctx, authorization.AuthKey, username)
findResult := []interface{}{bson.D{
{Key: "experiment_id", Value: targetStruct.request.ID},
}}
@ -93,8 +88,7 @@ func FuzzSaveChaosExperiment(f *testing.F) {
mockServices.ChaosExperimentService.On("ProcessExperimentUpdate", mock.Anything, mock.Anything, mock.Anything, mock.Anything, false, mock.Anything, mock.Anything).Return(nil).Once()
mockServices.GitOpsService.On("UpsertExperimentToGit", ctx, mock.Anything, mock.Anything).Return(nil).Once()
store := store.NewStore()
res, err := mockServices.ChaosExperimentHandler.SaveChaosExperiment(ctx, targetStruct.request, targetStruct.projectID, store)
res, err := mockServices.ChaosExperimentHandler.SaveChaosExperiment(ctx, targetStruct.request, targetStruct.projectID, "")
if err != nil {
t.Errorf("ChaosExperimentHandler.SaveChaosExperiment() error = %v", err)
return
@ -119,9 +113,7 @@ func FuzzDeleteChaosExperiment(f *testing.F) {
return
}
logrus.Info("here", targetStruct)
username, _ := jwt.NewWithClaims(jwt.SigningMethodHS512, jwt.MapClaims{"username": "test"}).SignedString([]byte(utils.Config.JwtSecret))
ctx := context.Background()
ctx = context.WithValue(ctx, authorization.AuthKey, username)
findResult := []interface{}{bson.D{
{Key: "experiment_id", Value: targetStruct.experimentId},
{Key: "experiment_runs", Value: []*dbChaosExperimentRun.ChaosExperimentRun{
@ -137,7 +129,7 @@ func FuzzDeleteChaosExperiment(f *testing.F) {
mockServices.ChaosExperimentRunService.On("ProcessExperimentRunDelete", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil).Once()
store := store.NewStore()
res, err := mockServices.ChaosExperimentHandler.DeleteChaosExperiment(ctx, targetStruct.projectID, targetStruct.experimentId, &targetStruct.experimentRunID, store)
res, err := mockServices.ChaosExperimentHandler.DeleteChaosExperiment(ctx, targetStruct.projectID, targetStruct.experimentId, &targetStruct.experimentRunID, store, "")
if err != nil {
t.Errorf("ChaosExperimentHandler.DeleteChaosExperiment() error = %v", err)
return
@ -161,9 +153,7 @@ func FuzzUpdateChaosExperiment(f *testing.F) {
return
}
experimentType := dbChaosExperiment.NonCronExperiment
username, _ := jwt.NewWithClaims(jwt.SigningMethodHS512, jwt.MapClaims{"username": "test"}).SignedString([]byte(utils.Config.JwtSecret))
ctx := context.Background()
ctx = context.WithValue(ctx, authorization.AuthKey, username)
mockServices := NewMockServices()
mockServices.MongodbOperator.On("CountDocuments", ctx, mongodb.ChaosExperimentCollection, mock.Anything, mock.Anything).Return(int64(0), nil).Once()
mockServices.ChaosExperimentService.On("ProcessExperiment", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(&model.ChaosExperimentRequest{
@ -174,7 +164,7 @@ func FuzzUpdateChaosExperiment(f *testing.F) {
mockServices.ChaosExperimentService.On("ProcessExperimentUpdate", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil).Once()
mockServices.GitOpsService.On("UpsertExperimentToGit", ctx, mock.Anything, mock.Anything).Return(nil).Once()
store := store.NewStore()
res, err := mockServices.ChaosExperimentHandler.UpdateChaosExperiment(ctx, targetStruct.experiment, targetStruct.projectID, store)
res, err := mockServices.ChaosExperimentHandler.UpdateChaosExperiment(ctx, targetStruct.experiment, targetStruct.projectID, store, "")
if err != nil {
t.Errorf("ChaosExperimentHandler.UpdateChaosExperiment() error = %v", err)
return
@ -197,9 +187,7 @@ func FuzzGetExperiment(f *testing.F) {
if err != nil {
return
}
username, _ := jwt.NewWithClaims(jwt.SigningMethodHS512, jwt.MapClaims{"username": "test"}).SignedString([]byte(utils.Config.JwtSecret))
ctx := context.Background()
ctx = context.WithValue(ctx, authorization.AuthKey, username)
mockServices := NewMockServices()
findResult := []interface{}{bson.D{
{Key: "project_id", Value: targetStruct.projectID},
@ -244,9 +232,6 @@ func FuzzListExperiment(f *testing.F) {
if err != nil {
return
}
username, _ := jwt.NewWithClaims(jwt.SigningMethodHS512, jwt.MapClaims{"username": "test"}).SignedString([]byte(utils.Config.JwtSecret))
ctx := context.Background()
ctx = context.WithValue(ctx, authorization.AuthKey, username)
mockServices := NewMockServices()
findResult := []interface{}{
bson.D{
@ -282,13 +267,8 @@ func FuzzDisableCronExperiment(f *testing.F) {
if len(targetStruct.request.Revision) < 1 {
return
}
username, _ := jwt.NewWithClaims(jwt.SigningMethodHS512, jwt.MapClaims{"username": "test"}).SignedString([]byte(utils.Config.JwtSecret))
ctx := context.Background()
ctx = context.WithValue(ctx, authorization.AuthKey, username)
mockServices := NewMockServices()
mockServices.ChaosExperimentService.On("ProcessExperimentUpdate", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil).Once()
err = mockServices.ChaosExperimentHandler.DisableCronExperiment(username, targetStruct.request, targetStruct.projectID, store.NewStore())
if err != nil {
t.Errorf("ChaosExperimentHandler.DisableCronExperiment() error = %v", err)
return
@ -309,9 +289,7 @@ func FuzzGetExperimentStats(f *testing.F) {
return
}
username, _ := jwt.NewWithClaims(jwt.SigningMethodHS512, jwt.MapClaims{"username": "test"}).SignedString([]byte(utils.Config.JwtSecret))
ctx := context.Background()
ctx = context.WithValue(ctx, authorization.AuthKey, username)
mockServices := NewMockServices()
findResult := []interface{}{
bson.D{

View File

@ -18,7 +18,6 @@ import (
dbSchemaProbe "github.com/litmuschaos/litmus/chaoscenter/graphql/server/pkg/database/mongodb/probe"
"github.com/litmuschaos/litmus/chaoscenter/graphql/server/pkg/authorization"
"github.com/litmuschaos/litmus/chaoscenter/graphql/server/pkg/chaos_infrastructure"
"github.com/litmuschaos/litmus/chaoscenter/graphql/server/pkg/gitops"
@ -73,7 +72,7 @@ func NewChaosExperimentHandler(
}
}
func (c *ChaosExperimentHandler) SaveChaosExperiment(ctx context.Context, request model.SaveChaosExperimentRequest, projectID string, r *store.StateData) (string, error) {
func (c *ChaosExperimentHandler) SaveChaosExperiment(ctx context.Context, request model.SaveChaosExperimentRequest, projectID string, username string) (string, error) {
var revID = uuid.New().String()
@ -106,11 +105,6 @@ func (c *ChaosExperimentHandler) SaveChaosExperiment(ctx context.Context, reques
if err != nil {
return "", err
}
tkn := ctx.Value(authorization.AuthKey).(string)
username, err := authorization.GetUsername(tkn)
if err != nil {
return "", err
}
// Updating the existing experiment
if wfDetails.ExperimentID == request.ID {
@ -159,7 +153,7 @@ func (c *ChaosExperimentHandler) SaveChaosExperiment(ctx context.Context, reques
return "experiment saved successfully", nil
}
func (c *ChaosExperimentHandler) CreateChaosExperiment(ctx context.Context, request *model.ChaosExperimentRequest, projectID string) (*model.ChaosExperimentResponse, error) {
func (c *ChaosExperimentHandler) CreateChaosExperiment(ctx context.Context, request *model.ChaosExperimentRequest, projectID string, username string) (*model.ChaosExperimentResponse, error) {
var revID = uuid.New().String()
@ -180,9 +174,7 @@ func (c *ChaosExperimentHandler) CreateChaosExperiment(ctx context.Context, requ
return nil, err
}
tkn := ctx.Value(authorization.AuthKey).(string)
uid, err := authorization.GetUsername(tkn)
err = c.chaosExperimentService.ProcessExperimentCreation(context.TODO(), newRequest, uid, projectID, wfType, revID, nil)
err = c.chaosExperimentService.ProcessExperimentCreation(context.TODO(), newRequest, username, projectID, wfType, revID, nil)
if err != nil {
return nil, err
}
@ -196,7 +188,7 @@ func (c *ChaosExperimentHandler) CreateChaosExperiment(ctx context.Context, requ
}, nil
}
func (c *ChaosExperimentHandler) DeleteChaosExperiment(ctx context.Context, projectID string, workflowID string, workflowRunID *string, r *store.StateData) (bool, error) {
func (c *ChaosExperimentHandler) DeleteChaosExperiment(ctx context.Context, projectID string, workflowID string, workflowRunID *string, r *store.StateData, username string) (bool, error) {
query := bson.D{
{"experiment_id", workflowID},
{"project_id", projectID},
@ -212,14 +204,12 @@ func (c *ChaosExperimentHandler) DeleteChaosExperiment(ctx context.Context, proj
if workflow.IsRemoved {
return false, errors.New("chaos experiment already deleted: " + workflowID)
}
tkn := ctx.Value(authorization.AuthKey).(string)
uid, err := authorization.GetUsername(tkn)
// If workflowRunID is nil, delete the experiment and all its corresponding runs
if workflowRunID == nil {
if workflow.CronSyntax != "" {
err = c.DisableCronExperiment(uid, workflow, projectID, r)
err = c.DisableCronExperiment(username, workflow, projectID, r)
if err != nil {
return false, err
}
@ -235,7 +225,7 @@ func (c *ChaosExperimentHandler) DeleteChaosExperiment(ctx context.Context, proj
return false, err
}
// Delete experiment
err = c.chaosExperimentService.ProcessExperimentDelete(query, workflow, uid, r)
err = c.chaosExperimentService.ProcessExperimentDelete(query, workflow, username, r)
if err != nil {
return false, err
}
@ -263,7 +253,7 @@ func (c *ChaosExperimentHandler) DeleteChaosExperiment(ctx context.Context, proj
return false, err
}
err = c.chaosExperimentRunService.ProcessExperimentRunDelete(ctx, query, workflowRunID, workflowRun, workflow, uid, r)
err = c.chaosExperimentRunService.ProcessExperimentRunDelete(ctx, query, workflowRunID, workflowRun, workflow, username, r)
if err != nil {
return false, err
}
@ -272,7 +262,7 @@ func (c *ChaosExperimentHandler) DeleteChaosExperiment(ctx context.Context, proj
return true, nil
}
func (c *ChaosExperimentHandler) UpdateChaosExperiment(ctx context.Context, request model.ChaosExperimentRequest, projectID string, r *store.StateData) (*model.ChaosExperimentResponse, error) {
func (c *ChaosExperimentHandler) UpdateChaosExperiment(ctx context.Context, request model.ChaosExperimentRequest, projectID string, r *store.StateData, username string) (*model.ChaosExperimentResponse, error) {
var (
revID = uuid.New().String()
)
@ -287,8 +277,6 @@ func (c *ChaosExperimentHandler) UpdateChaosExperiment(ctx context.Context, requ
if err != nil {
return nil, err
}
tkn := ctx.Value(authorization.AuthKey).(string)
uid, err := authorization.GetUsername(tkn)
err = c.gitOpsService.UpsertExperimentToGit(ctx, projectID, newRequest)
if err != nil {
@ -296,7 +284,7 @@ func (c *ChaosExperimentHandler) UpdateChaosExperiment(ctx context.Context, requ
return nil, err
}
err = c.chaosExperimentService.ProcessExperimentUpdate(newRequest, uid, wfType, revID, false, projectID, r)
err = c.chaosExperimentService.ProcessExperimentUpdate(newRequest, username, wfType, revID, false, projectID, r)
if err != nil {
return nil, err
}
@ -1372,7 +1360,7 @@ func (c *ChaosExperimentHandler) validateDuplicateExperimentName(ctx context.Con
return nil
}
func (c *ChaosExperimentHandler) UpdateCronExperimentState(ctx context.Context, workflowID string, disable bool, projectID string, r *store.StateData) (bool, error) {
func (c *ChaosExperimentHandler) UpdateCronExperimentState(ctx context.Context, workflowID string, disable bool, projectID string, r *store.StateData, username string) (bool, error) {
var (
cronWorkflowManifest v1alpha1.CronWorkflow
)
@ -1420,8 +1408,6 @@ func (c *ChaosExperimentHandler) UpdateCronExperimentState(ctx context.Context,
}
//Update the revision in database
tkn := ctx.Value(authorization.AuthKey).(string)
username, err := authorization.GetUsername(tkn)
err = c.chaosExperimentService.ProcessExperimentUpdate(&model.ChaosExperimentRequest{
ExperimentID: &workflowID,
@ -1465,13 +1451,10 @@ func (c *ChaosExperimentHandler) UpdateCronExperimentState(ctx context.Context,
return true, err
}
func (c *ChaosExperimentHandler) StopExperimentRuns(ctx context.Context, projectID string, experimentID string, experimentRunID *string, r *store.StateData) (bool, error) {
func (c *ChaosExperimentHandler) StopExperimentRuns(ctx context.Context, projectID string, experimentID string, experimentRunID *string, r *store.StateData, username string) (bool, error) {
var experimentRunsID []string
tkn := ctx.Value(authorization.AuthKey).(string)
username, err := authorization.GetUsername(tkn)
query := bson.D{
{"experiment_id", experimentID},
{"project_id", projectID},

View File

@ -22,7 +22,6 @@ import (
dbChaosExperimentRun "github.com/litmuschaos/litmus/chaoscenter/graphql/server/pkg/database/mongodb/chaos_experiment_run"
dbMocks "github.com/litmuschaos/litmus/chaoscenter/graphql/server/pkg/database/mongodb/mocks"
dbGitOpsMocks "github.com/litmuschaos/litmus/chaoscenter/graphql/server/pkg/gitops/model/mocks"
"github.com/litmuschaos/litmus/chaoscenter/graphql/server/utils"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
)
@ -77,14 +76,13 @@ func TestChaosExperimentHandler_SaveChaosExperiment(t *testing.T) {
projectID string
}
username, _ := jwt.NewWithClaims(jwt.SigningMethodHS512, jwt.MapClaims{"username": "test"}).SignedString([]byte(utils.Config.JwtSecret))
username, _ := jwt.NewWithClaims(jwt.SigningMethodHS512, jwt.MapClaims{"username": "test"}).SignedString([]byte(""))
ctx := context.Background()
projectId := uuid.New().String()
experimentId := uuid.New().String()
experimentType := dbChaosExperiment.NonCronExperiment
infraId := uuid.New().String()
store := store.NewStore()
tests := []struct {
name string
args args
@ -206,7 +204,7 @@ func TestChaosExperimentHandler_SaveChaosExperiment(t *testing.T) {
t.Run(tc.name, func(t *testing.T) {
mockServices := NewMockServices()
tc.given(tc.args.request2, mockServices)
_, err := mockServices.ChaosExperimentHandler.SaveChaosExperiment(ctx, tc.args.request, tc.args.projectID, store)
_, err := mockServices.ChaosExperimentHandler.SaveChaosExperiment(ctx, tc.args.request, tc.args.projectID, "")
if (err != nil) != tc.wantErr {
t.Errorf("ChaosExperimentHandler.SaveChaosExperiment() error = %v, wantErr %v", err, tc.wantErr)
return
@ -234,7 +232,7 @@ func TestChaosExperimentHandler_CreateChaosExperiment(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
mockServices := NewMockServices()
got, err := mockServices.ChaosExperimentHandler.CreateChaosExperiment(tt.args.ctx, tt.args.request, tt.args.projectID)
got, err := mockServices.ChaosExperimentHandler.CreateChaosExperiment(tt.args.ctx, tt.args.request, tt.args.projectID, "")
if (err != nil) != tt.wantErr {
t.Errorf("ChaosExperimentHandler.CreateChaosExperiment() error = %v, wantErr %v", err, tt.wantErr)
return
@ -247,7 +245,7 @@ func TestChaosExperimentHandler_CreateChaosExperiment(t *testing.T) {
}
func TestChaosExperimentHandler_DeleteChaosExperiment(t *testing.T) {
username, _ := jwt.NewWithClaims(jwt.SigningMethodHS512, jwt.MapClaims{"username": "test"}).SignedString([]byte(utils.Config.JwtSecret))
username, _ := jwt.NewWithClaims(jwt.SigningMethodHS512, jwt.MapClaims{"username": "test"}).SignedString([]byte(""))
ctx := context.TODO()
projectId := uuid.New().String()
experimentId := uuid.New().String()
@ -334,7 +332,7 @@ func TestChaosExperimentHandler_DeleteChaosExperiment(t *testing.T) {
t.Run(tc.name, func(t *testing.T) {
mockServices := NewMockServices()
tc.given(mockServices)
_, err := mockServices.ChaosExperimentHandler.DeleteChaosExperiment(ctx, projectId, experimentId, &experimentRunID, store)
_, err := mockServices.ChaosExperimentHandler.DeleteChaosExperiment(ctx, projectId, experimentId, &experimentRunID, store, "")
if (err != nil) != tc.wantErr {
t.Errorf("ChaosExperimentHandler.DeleteChaosExperiment() error = %v, wantErr %v", err, tc.wantErr)
return
@ -349,7 +347,6 @@ func TestChaosExperimentHandler_UpdateChaosExperiment(t *testing.T) {
request *model.ChaosExperimentRequest
projectID string
}
username, _ := jwt.NewWithClaims(jwt.SigningMethodHS512, jwt.MapClaims{"username": "test"}).SignedString([]byte(utils.Config.JwtSecret))
ctx := context.Background()
projectId := uuid.New().String()
infraId := uuid.New().String()
@ -375,11 +372,10 @@ func TestChaosExperimentHandler_UpdateChaosExperiment(t *testing.T) {
},
},
given: func(request *model.ChaosExperimentRequest, mockServices *MockServices) {
ctx = context.WithValue(ctx, authorization.AuthKey, username)
mockServices.MongodbOperator.On("CountDocuments", ctx, mongodb.ChaosExperimentCollection, mock.Anything, mock.Anything).Return(int64(0), nil).Once()
mockServices.MongodbOperator.On("CountDocuments", mock.Anything, mongodb.ChaosExperimentCollection, mock.Anything, mock.Anything).Return(int64(0), nil).Once()
mockServices.ChaosExperimentService.On("ProcessExperiment", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(request, &experimentType, nil).Once()
mockServices.ChaosExperimentService.On("ProcessExperimentUpdate", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil).Once()
mockServices.GitOpsService.On("UpsertExperimentToGit", ctx, mock.Anything, request).Return(nil).Once()
mockServices.GitOpsService.On("UpsertExperimentToGit", mock.Anything, mock.Anything, request).Return(nil).Once()
},
wantErr: false,
@ -395,7 +391,6 @@ func TestChaosExperimentHandler_UpdateChaosExperiment(t *testing.T) {
},
},
given: func(request *model.ChaosExperimentRequest, mockServices *MockServices) {
ctx = context.WithValue(ctx, authorization.AuthKey, username)
mockServices.MongodbOperator.On("CountDocuments", ctx, mongodb.ChaosExperimentCollection, mock.Anything, mock.Anything).Return(int64(0), nil).Once()
mockServices.ChaosExperimentService.On("ProcessExperiment", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(request, &experimentType, errors.New("Incorrect request format")).Once()
},
@ -412,8 +407,6 @@ func TestChaosExperimentHandler_UpdateChaosExperiment(t *testing.T) {
},
},
given: func(request *model.ChaosExperimentRequest, mockServices *MockServices) {
ctx = context.WithValue(ctx, authorization.AuthKey, username)
mockServices.MongodbOperator.On("CountDocuments", ctx, mongodb.ChaosExperimentCollection, mock.Anything, mock.Anything).Return(int64(0), nil).Once()
mockServices.ChaosExperimentService.On("ProcessExperiment", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(request, &experimentType, nil).Once()
@ -429,7 +422,7 @@ func TestChaosExperimentHandler_UpdateChaosExperiment(t *testing.T) {
t.Run(tc.name, func(t *testing.T) {
mockServices := NewMockServices()
tc.given(tc.args.request, mockServices)
_, err := mockServices.ChaosExperimentHandler.UpdateChaosExperiment(ctx, *tc.args.request, tc.args.projectID, store)
_, err := mockServices.ChaosExperimentHandler.UpdateChaosExperiment(ctx, *tc.args.request, tc.args.projectID, store, "")
if (err != nil) != tc.wantErr {
t.Errorf("ChaosExperimentHandler.UpdateChaosExperiment() error = %v, wantErr %v", err, tc.wantErr)
return
@ -628,7 +621,7 @@ func TestChaosExperimentHandler_ListExperiment(t *testing.T) {
}
func TestChaosExperimentHandler_DisableCronExperiment(t *testing.T) {
username, _ := jwt.NewWithClaims(jwt.SigningMethodHS512, jwt.MapClaims{"username": "test"}).SignedString([]byte(utils.Config.JwtSecret))
projectID := uuid.New().String()
experimentID := uuid.New().String()
infraID := uuid.New().String()
@ -666,7 +659,7 @@ func TestChaosExperimentHandler_DisableCronExperiment(t *testing.T) {
t.Run(tc.name, func(t *testing.T) {
mockServices := NewMockServices()
tc.given(mockServices)
if err := mockServices.ChaosExperimentHandler.DisableCronExperiment(username, experimentRequest, projectID, store); (err != nil) != tc.wantErr {
if err := mockServices.ChaosExperimentHandler.DisableCronExperiment("", experimentRequest, projectID, store); (err != nil) != tc.wantErr {
t.Errorf("ChaosExperimentHandler.DisableCronExperiment() error = %v, wantErr %v", err, tc.wantErr)
}
assertExpectations(mockServices, t)
@ -675,6 +668,7 @@ func TestChaosExperimentHandler_DisableCronExperiment(t *testing.T) {
}
func TestChaosExperimentHandler_GetExperimentStats(t *testing.T) {
ctx := context.Background()
projectID := uuid.New().String()
tests := []struct {
@ -685,8 +679,6 @@ func TestChaosExperimentHandler_GetExperimentStats(t *testing.T) {
{
name: "success: get experiment stats",
given: func(mockServices *MockServices) {
username, _ := jwt.NewWithClaims(jwt.SigningMethodHS512, jwt.MapClaims{"username": "test"}).SignedString([]byte(utils.Config.JwtSecret))
ctx = context.WithValue(ctx, authorization.AuthKey, username)
findResult := []interface{}{
bson.D{
{Key: "project_id", Value: projectID},
@ -700,8 +692,6 @@ func TestChaosExperimentHandler_GetExperimentStats(t *testing.T) {
{
name: "failure: empty cursor returned",
given: func(mockServices *MockServices) {
username, _ := jwt.NewWithClaims(jwt.SigningMethodHS512, jwt.MapClaims{"username": "test"}).SignedString([]byte(utils.Config.JwtSecret))
ctx = context.WithValue(ctx, authorization.AuthKey, username)
cursor, _ := mongo.NewCursorFromDocuments(nil, nil, nil)
mockServices.MongodbOperator.On("Aggregate", mock.Anything, mongodb.ChaosExperimentCollection, mock.Anything, mock.Anything).Return(cursor, errors.New("empty cursor returned")).Once()
},
@ -710,8 +700,6 @@ func TestChaosExperimentHandler_GetExperimentStats(t *testing.T) {
{
name: "failure: getting experiment stats",
given: func(mockServices *MockServices) {
username, _ := jwt.NewWithClaims(jwt.SigningMethodHS512, jwt.MapClaims{"username": "test"}).SignedString([]byte(utils.Config.JwtSecret))
ctx = context.WithValue(ctx, authorization.AuthKey, username)
findResult := []interface{}{
bson.D{
{Key: "project_id", Value: projectID},

View File

@ -1,4 +1,4 @@
// Code generated by mockery v2.40.1. DO NOT EDIT.
// Code generated by mockery v2.42.0. DO NOT EDIT.
package mocks

View File

@ -787,8 +787,6 @@ func (c *ChaosExperimentRunHandler) RunChaosWorkFlow(ctx context.Context, projec
return nil, err
}
tkn := ctx.Value(authorization.AuthKey).(string)
username, err := authorization.GetUsername(tkn)
var (
wc = writeconcern.New(writeconcern.WMajority())
rc = readconcern.Snapshot()
@ -817,11 +815,11 @@ func (c *ChaosExperimentRunHandler) RunChaosWorkFlow(ctx context.Context, projec
IsRemoved: false,
CreatedAt: currentTime,
CreatedBy: mongodb.UserDetailResponse{
Username: username,
Username: ctx.Value(authorization.AuthKey).(string),
},
UpdatedAt: currentTime,
UpdatedBy: mongodb.UserDetailResponse{
Username: username,
Username: ctx.Value(authorization.AuthKey).(string),
},
},
},
@ -863,11 +861,11 @@ func (c *ChaosExperimentRunHandler) RunChaosWorkFlow(ctx context.Context, projec
IsRemoved: false,
CreatedAt: currentTime,
CreatedBy: mongodb.UserDetailResponse{
Username: username,
Username: ctx.Value(authorization.AuthKey).(string),
},
UpdatedAt: currentTime,
UpdatedBy: mongodb.UserDetailResponse{
Username: username,
Username: ctx.Value(authorization.AuthKey).(string),
},
},
NotifyID: &notifyID,
@ -910,7 +908,7 @@ func (c *ChaosExperimentRunHandler) RunChaosWorkFlow(ctx context.Context, projec
if err != nil {
return nil, fmt.Errorf("failed to generate probes in workflow manifest, err: %v", err)
}
username := ctx.Value(authorization.AuthKey).(string)
manifest, err := yaml.Marshal(workflowManifest)
if err != nil {
return nil, err
@ -993,8 +991,7 @@ func (c *ChaosExperimentRunHandler) RunCronExperiment(ctx context.Context, proje
return err
}
tkn := ctx.Value(authorization.AuthKey).(string)
username, err := authorization.GetUsername(tkn)
username := ctx.Value(authorization.AuthKey).(string)
if r != nil {
chaos_infrastructure.SendExperimentToSubscriber(projectID, &model.ChaosExperimentRequest{

View File

@ -1,4 +1,4 @@
// Code generated by mockery v2.40.1. DO NOT EDIT.
// Code generated by mockery v2.42.0. DO NOT EDIT.
package mocks

View File

@ -1,11 +1,14 @@
package chaos_infrastructure
import (
"context"
"errors"
"fmt"
"github.com/litmuschaos/litmus/chaoscenter/graphql/server/pkg/database/mongodb"
"github.com/litmuschaos/litmus/chaoscenter/graphql/server/pkg/database/mongodb/authConfig"
"github.com/golang-jwt/jwt"
"github.com/litmuschaos/litmus/chaoscenter/graphql/server/utils"
)
// InfraCreateJWT generates jwt used in chaos_infra registration
@ -13,8 +16,11 @@ func InfraCreateJWT(id string) (string, error) {
claims := jwt.MapClaims{}
claims["chaos_infra_id"] = id
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
tokenString, err := token.SignedString([]byte(utils.Config.JwtSecret))
config, err := authConfig.NewAuthConfigOperator(mongodb.Operator).GetAuthConfig(context.Background())
if err != nil {
return "", err
}
tokenString, err := token.SignedString([]byte(config.Value))
if err != nil {
return "", err
}
@ -28,7 +34,11 @@ func InfraValidateJWT(token string) (string, error) {
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"])
}
return []byte(utils.Config.JwtSecret), nil
config, err := authConfig.NewAuthConfigOperator(mongodb.Operator).GetAuthConfig(context.Background())
if err != nil {
return "", err
}
return []byte(config.Value), nil
})
if err != nil {

View File

@ -0,0 +1,27 @@
package authConfig
import (
"context"
"github.com/litmuschaos/litmus/chaoscenter/graphql/server/pkg/database/mongodb"
)
// Operator is the model for cluster collection
type Operator struct {
operator mongodb.MongoOperator
}
// NewAuthConfigOperator returns a new instance of Operator
func NewAuthConfigOperator(mongodbOperator mongodb.MongoOperator) *Operator {
return &Operator{
operator: mongodbOperator,
}
}
func (c *Operator) GetAuthConfig(ctx context.Context) (*mongodb.AuthConfig, error) {
salt, err := c.operator.GetAuthConfig(ctx, "salt")
if err != nil {
return nil, err
}
return salt, nil
}

View File

@ -19,3 +19,8 @@ type UserDetailResponse struct {
Username string `bson:"username" json:"username"`
Email string `bson:"email" json:"email"`
}
type AuthConfig struct {
Key string `bson:"key"`
Value string `bson:"value"`
}

View File

@ -4,6 +4,7 @@ package mocks
import (
"context"
"github.com/litmuschaos/litmus/chaoscenter/graphql/server/pkg/database/mongodb"
"github.com/stretchr/testify/mock"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
@ -16,11 +17,17 @@ type MongoOperator struct {
}
// WatchEvents implements mongodb.MongoOperator.
func (m *MongoOperator) WatchEvents(ctx context.Context, client *mongo.Client, collectionType int, pipeline mongo.Pipeline, opts ...*options.ChangeStreamOptions) (*mongo.ChangeStream, error) {
func (m MongoOperator) WatchEvents(ctx context.Context, client *mongo.Client, collectionType int, pipeline mongo.Pipeline, opts ...*options.ChangeStreamOptions) (*mongo.ChangeStream, error) {
args := m.Called(ctx, client, collectionType, pipeline, opts)
return args.Get(0).(*mongo.ChangeStream), args.Error(1)
}
// GetAuthConfig implements mongodb.MongoOperator.
func (m MongoOperator) GetAuthConfig(ctx context.Context, key string) (*mongodb.AuthConfig, error) {
args := m.Called(ctx, key)
return args.Get(0).(*mongodb.AuthConfig), args.Error(1)
}
// Create provides a mock function with given fields: ctx, collectionType, document
func (m MongoOperator) Create(ctx context.Context, collectionType int, document interface{}) error {
args := m.Called(ctx, collectionType, document)

View File

@ -2,6 +2,7 @@ package mongodb
import (
"context"
"encoding/base64"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
@ -25,6 +26,7 @@ type MongoOperator interface {
ListCollection(ctx context.Context, mclient *mongo.Client) ([]string, error)
ListDataBase(ctx context.Context, mclient *mongo.Client) ([]string, error)
WatchEvents(ctx context.Context, client *mongo.Client, collectionType int, pipeline mongo.Pipeline, opts ...*options.ChangeStreamOptions) (*mongo.ChangeStream, error)
GetAuthConfig(ctx context.Context, key string) (*AuthConfig, error)
}
type MongoOperations struct {
@ -214,3 +216,23 @@ func (m *MongoOperations) WatchEvents(ctx context.Context, client *mongo.Client,
}
return events, nil
}
func (m *MongoOperations) GetAuthConfig(ctx context.Context, key string) (*AuthConfig, error) {
authDb := MgoClient.Database("auth")
find := authDb.Collection("auth-config").FindOne(ctx, bson.D{
{"key", key},
})
var conf AuthConfig
err := find.Decode(&conf)
if err != nil {
return nil, err
}
decodedValue, err := base64.URLEncoding.DecodeString(conf.Value)
if err != nil {
return nil, err
}
conf.Value = string(decodedValue)
return &conf, nil
}

View File

@ -15,7 +15,6 @@ import (
"github.com/litmuschaos/litmus/chaoscenter/graphql/server/graph/model"
"github.com/litmuschaos/litmus/chaoscenter/graphql/server/pkg/authorization"
"github.com/litmuschaos/litmus/chaoscenter/graphql/server/pkg/database/mongodb"
"github.com/litmuschaos/litmus/chaoscenter/graphql/server/utils"
"github.com/sirupsen/logrus"
"github.com/stretchr/testify/mock"
"go.mongodb.org/mongo-driver/bson"
@ -45,7 +44,6 @@ func GetSignedJWT(name string) (string, error) {
}
func FuzzCreateEnvironment(f *testing.F) {
utils.Config.JwtSecret = JwtSecret
f.Fuzz(func(t *testing.T, data []byte) {
fuzzConsumer := fuzz.NewConsumer(data)
targetStruct := &struct {
@ -65,7 +63,7 @@ func FuzzCreateEnvironment(f *testing.F) {
ctx := context.WithValue(context.Background(), authorization.AuthKey, token)
service := handler.NewEnvironmentService(environmentOperator)
env, err := service.CreateEnvironment(ctx, targetStruct.projectID, &targetStruct.input)
env, err := service.CreateEnvironment(ctx, targetStruct.projectID, &targetStruct.input, "")
if err != nil {
t.Errorf("Unexpected error: %v", err)
}
@ -76,7 +74,6 @@ func FuzzCreateEnvironment(f *testing.F) {
}
func FuzzTestDeleteEnvironment(f *testing.F) {
utils.Config.JwtSecret = JwtSecret
testCases := []struct {
projectID string
environmentID string
@ -107,7 +104,7 @@ func FuzzTestDeleteEnvironment(f *testing.F) {
ctx := context.WithValue(context.Background(), authorization.AuthKey, token)
service := handler.NewEnvironmentService(environmentOperator)
env, err := service.DeleteEnvironment(ctx, projectID, environmentID)
env, err := service.DeleteEnvironment(ctx, projectID, environmentID, "")
if err != nil {
t.Errorf("Unexpected error: %v", err)
}
@ -119,7 +116,6 @@ func FuzzTestDeleteEnvironment(f *testing.F) {
}
func FuzzTestGetEnvironment(f *testing.F) {
utils.Config.JwtSecret = JwtSecret
testCases := []struct {
projectID string
environmentID string

View File

@ -7,7 +7,6 @@ import (
"time"
"github.com/litmuschaos/litmus/chaoscenter/graphql/server/graph/model"
"github.com/litmuschaos/litmus/chaoscenter/graphql/server/pkg/authorization"
"github.com/litmuschaos/litmus/chaoscenter/graphql/server/pkg/database/mongodb"
"github.com/litmuschaos/litmus/chaoscenter/graphql/server/pkg/database/mongodb/environments"
dbOperationsEnvironment "github.com/litmuschaos/litmus/chaoscenter/graphql/server/pkg/database/mongodb/environments"
@ -16,9 +15,9 @@ import (
)
type EnvironmentHandler interface {
CreateEnvironment(ctx context.Context, projectID string, input *model.CreateEnvironmentRequest) (*model.Environment, error)
UpdateEnvironment(ctx context.Context, projectID string, request *model.UpdateEnvironmentRequest) (string, error)
DeleteEnvironment(ctx context.Context, projectID string, environmentID string) (string, error)
CreateEnvironment(ctx context.Context, projectID string, input *model.CreateEnvironmentRequest, username string) (*model.Environment, error)
UpdateEnvironment(ctx context.Context, projectID string, request *model.UpdateEnvironmentRequest, username string) (string, error)
DeleteEnvironment(ctx context.Context, projectID string, environmentID string, username string) (string, error)
GetEnvironment(projectID string, environmentID string) (*model.Environment, error)
ListEnvironments(projectID string, request *model.ListEnvironmentRequest) (*model.ListEnvironmentResponse, error)
}
@ -33,19 +32,13 @@ func NewEnvironmentService(EnvironmentOperator *dbOperationsEnvironment.Operator
}
}
func (e *EnvironmentService) CreateEnvironment(ctx context.Context, projectID string, input *model.CreateEnvironmentRequest) (*model.Environment, error) {
func (e *EnvironmentService) CreateEnvironment(ctx context.Context, projectID string, input *model.CreateEnvironmentRequest, username string) (*model.Environment, error) {
currentTime := time.Now()
if input.Tags == nil || len(input.Tags) == 0 {
input.Tags = []string{}
}
tkn := ctx.Value(authorization.AuthKey).(string)
username, err := authorization.GetUsername(tkn)
if err != nil {
return nil, err
}
desc := ""
if input.Description != nil {
desc = *input.Description
@ -75,7 +68,7 @@ func (e *EnvironmentService) CreateEnvironment(ctx context.Context, projectID st
},
}
err = e.EnvironmentOperator.InsertEnvironment(context.Background(), newEnv)
err := e.EnvironmentOperator.InsertEnvironment(context.Background(), newEnv)
if err != nil {
return &model.Environment{}, err
}
@ -91,7 +84,7 @@ func (e *EnvironmentService) CreateEnvironment(ctx context.Context, projectID st
}
func (e *EnvironmentService) UpdateEnvironment(ctx context.Context, projectID string, request *model.UpdateEnvironmentRequest) (string, error) {
func (e *EnvironmentService) UpdateEnvironment(ctx context.Context, projectID string, request *model.UpdateEnvironmentRequest, username string) (string, error) {
query := bson.D{
{"environment_id", request.EnvironmentID},
@ -104,12 +97,6 @@ func (e *EnvironmentService) UpdateEnvironment(ctx context.Context, projectID st
return "couldn't update environment", err
}
tkn := ctx.Value(authorization.AuthKey).(string)
username, err := authorization.GetUsername(tkn)
if err != nil {
return "", err
}
updateQuery := bson.D{}
updateQuery = append(updateQuery, bson.E{
Key: "$set", Value: bson.D{
@ -156,20 +143,16 @@ func (e *EnvironmentService) UpdateEnvironment(ctx context.Context, projectID st
return "environment updated successfully", nil
}
func (e *EnvironmentService) DeleteEnvironment(ctx context.Context, projectID string, environmentID string) (string, error) {
func (e *EnvironmentService) DeleteEnvironment(ctx context.Context, projectID string, environmentID string, username string) (string, error) {
currTime := time.Now().UnixMilli()
tkn := ctx.Value(authorization.AuthKey).(string)
username, err := authorization.GetUsername(tkn)
if err != nil {
return "", err
}
query := bson.D{
{"environment_id", environmentID},
{"project_id", projectID},
{"is_removed", false},
}
_, err = e.EnvironmentOperator.GetEnvironment(query)
_, err := e.EnvironmentOperator.GetEnvironment(query)
if err != nil {
return "couldn't fetch environment details", err
}

View File

@ -2,10 +2,11 @@ package test
import (
"context"
"errors"
"testing"
"time"
"go.mongodb.org/mongo-driver/mongo"
"github.com/golang-jwt/jwt"
"github.com/google/uuid"
"github.com/litmuschaos/litmus/chaoscenter/graphql/server/graph/model"
@ -14,7 +15,6 @@ import (
dbOperationsEnvironment "github.com/litmuschaos/litmus/chaoscenter/graphql/server/pkg/database/mongodb/environments"
dbMocks "github.com/litmuschaos/litmus/chaoscenter/graphql/server/pkg/database/mongodb/mocks"
"github.com/litmuschaos/litmus/chaoscenter/graphql/server/pkg/environment/handler"
"github.com/litmuschaos/litmus/chaoscenter/graphql/server/utils"
"github.com/stretchr/testify/mock"
"go.mongodb.org/mongo-driver/bson"
)
@ -42,7 +42,6 @@ func GetSignedJWT(name string) (string, error) {
}
func TestCreateEnvironment(t *testing.T) {
utils.Config.JwtSecret = JwtSecret
testCases := []struct {
name string
projectID string
@ -63,7 +62,7 @@ func TestCreateEnvironment(t *testing.T) {
return nil
},
expectedEnv: nil,
expectedErr: errors.New("invalid Token"),
expectedErr: nil,
given: func() string {
token, err := GetSignedJWT("testUser")
if err != nil {
@ -72,34 +71,18 @@ func TestCreateEnvironment(t *testing.T) {
return "invalid Token"
},
},
{
name: "Failed environment creation due to invalid token",
projectID: "testProject",
input: &model.CreateEnvironmentRequest{
EnvironmentID: "testEnvID",
Name: "testName",
},
mockInsertFunc: func(ctx context.Context, env environments.Environment) error {
return nil
},
expectedEnv: nil,
expectedErr: errors.New("invalid Token"),
given: func() string {
return "invalid Token"
},
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
mongodbMockOperator.On("Insert", mock.Anything, mock.AnythingOfType("environments.Environment")).
Return(tc.mockInsertFunc)
mongodbMockOperator.On("Create", mock.Anything, mock.Anything, mock.AnythingOfType("environments.Environment")).
Return(nil)
token := tc.given()
ctx := context.WithValue(context.Background(), authorization.AuthKey, token)
mockOperator := environmentOperator
service := handler.NewEnvironmentService(mockOperator)
env, err := service.CreateEnvironment(ctx, tc.projectID, tc.input)
env, err := service.CreateEnvironment(ctx, tc.projectID, tc.input, "")
if (err != nil && tc.expectedErr == nil) ||
(err == nil && tc.expectedErr != nil) ||
(err != nil && tc.expectedErr != nil && err.Error() != tc.expectedErr.Error()) {
@ -115,30 +98,27 @@ func TestCreateEnvironment(t *testing.T) {
}
func TestDeleteEnvironment(t *testing.T) {
utils.Config.JwtSecret = JwtSecret
findResult := []interface{}{bson.D{
{Key: "environment_id", Value: "testEnvID"},
}}
singleResult := mongo.NewSingleResultFromDocument(findResult[0], nil, nil)
testCases := []struct {
name string
projectID string
environmentID string
mockGetEnvironmentFunc func(query bson.D) (environments.Environment, error)
mockUpdateFunc func(ctx context.Context, query bson.D, update bson.D) error
mockGetEnvironmentFunc *mongo.SingleResult
mockUpdateFunc *mongo.UpdateResult
expectedResult string
expectedErr error
given func() string
}{
{
name: "success",
projectID: "testProject",
environmentID: "testEnvID",
mockGetEnvironmentFunc: func(query bson.D) (environments.Environment, error) {
return environments.Environment{
EnvironmentID: "testEnvID",
}, nil
},
mockUpdateFunc: func(ctx context.Context, query bson.D, update bson.D) error {
return nil
},
expectedErr: errors.New("invalid Token"),
name: "success",
projectID: "testProject",
environmentID: "testEnvID",
mockGetEnvironmentFunc: singleResult,
mockUpdateFunc: &mongo.UpdateResult{},
expectedErr: nil,
given: func() string {
token, err := GetSignedJWT("testUser")
if err != nil {
@ -146,37 +126,21 @@ func TestDeleteEnvironment(t *testing.T) {
}
return "invalid Token"
},
},
{
name: "Failed environment",
projectID: "testProject",
environmentID: "testEnvID",
mockGetEnvironmentFunc: func(query bson.D) (environments.Environment, error) {
return environments.Environment{
EnvironmentID: "testEnvID",
}, nil
},
mockUpdateFunc: func(ctx context.Context, query, update bson.D) error {
return nil
},
expectedErr: errors.New("invalid Token"),
given: func() string {
return "invalid Token"
},
},
}
}}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
mongodbMockOperator.On("Insert", mock.Anything, mock.AnythingOfType("environments.Environment")).
Return(tc.mockUpdateFunc)
mongodbMockOperator.On("Get", mock.Anything, mock.Anything, mock.Anything).Return(tc.mockGetEnvironmentFunc, nil)
mongodbMockOperator.On("UpdateMany", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).
Return(tc.mockUpdateFunc, nil)
token := tc.given()
ctx := context.WithValue(context.Background(), authorization.AuthKey, token)
mockOperator := environmentOperator
service := handler.NewEnvironmentService(mockOperator)
_, err := service.DeleteEnvironment(ctx, tc.projectID, tc.environmentID)
_, err := service.DeleteEnvironment(ctx, tc.projectID, tc.environmentID, "")
if (err != nil && tc.expectedErr == nil) ||
(err == nil && tc.expectedErr != nil) ||
(err != nil && tc.expectedErr != nil && err.Error() != tc.expectedErr.Error()) {

View File

@ -8,7 +8,6 @@ type Configuration struct {
Version string `required:"true"`
InfraDeployments string `required:"true" split_words:"true"`
DbServer string `required:"true" split_words:"true"`
JwtSecret string `required:"true" split_words:"true"`
LitmusPortalNamespace string `required:"true" split_words:"true"`
DbUser string `required:"true" split_words:"true"`
DbPassword string `required:"true" split_words:"true"`