From c04e0a9157a639db5581670da85458210aefaeff Mon Sep 17 00:00:00 2001 From: varnit goyal Date: Fri, 29 Nov 2024 16:20:01 +0530 Subject: [PATCH] TP-5555 | account provision --- internal/client/elastic/elastic.go | 3 -- internal/dependencies/dependencies.go | 2 +- internal/transport/handler/project.go | 4 ++ internal/transport/router/project.go | 2 + internal/transport/server.go | 2 +- models/db/project.go | 23 +++++----- pkg/kafka/producer/produce.go | 15 ++++--- service/ExceptionService.go | 7 +++- service/HoustonService.go | 18 ++++---- service/ProjectCreator.go | 60 +++++++++++++++++++++++++++ service/searchService.go | 1 - service/sourceMap.go | 17 ++++++-- 12 files changed, 115 insertions(+), 39 deletions(-) diff --git a/internal/client/elastic/elastic.go b/internal/client/elastic/elastic.go index 3898981..808550a 100644 --- a/internal/client/elastic/elastic.go +++ b/internal/client/elastic/elastic.go @@ -5,7 +5,6 @@ import ( "crypto/tls" "cybertron/configs" "encoding/json" - "fmt" elasticsearch8 "github.com/elastic/go-elasticsearch/v8" "log" "net/http" @@ -18,8 +17,6 @@ type ElasticSearchClient struct { } func NewElasticClient(elasticConfig configs.ElasticConfig) (*ElasticSearchClient, error) { - fmt.Println("elastic address %v", elasticConfig.Addresses) - fmt.Println("elastic address %v", elasticConfig.Username) cfg := elasticsearch8.Config{ Addresses: elasticConfig.Addresses, Username: elasticConfig.Username, diff --git a/internal/dependencies/dependencies.go b/internal/dependencies/dependencies.go index 8aa3f83..20b5e8d 100644 --- a/internal/dependencies/dependencies.go +++ b/internal/dependencies/dependencies.go @@ -71,7 +71,7 @@ func InitDependencies() *Dependencies { documentServiceClient := document.NewDocumentServiceHttpClient(httpClient, logger, configs.GetDocumentServiceHttpClientConfigs()) projectServiceClient := service.NewProjectCreator(logger, dbClient, s3Client, kafkaProducer) - sourceMapServiceClient := service.NewSourceMapService(dbClient, s3Client, configs.GetAWSConfig()) + sourceMapServiceClient := service.NewSourceMapService(dbClient, s3Client, configs.GetAWSConfig(), logger) releaseServiceClient := service.NewReleaseService(logger, dbClient) exceptionServiceClient := service.NewExceptionService(logger, dbClient, kafkaProducer, cacheClient, *configs.GetKafkaConfig()) searchServiceClient := service.NewSearchService(logger, elasticSearch) diff --git a/internal/transport/handler/project.go b/internal/transport/handler/project.go index a73713c..3c4a229 100644 --- a/internal/transport/handler/project.go +++ b/internal/transport/handler/project.go @@ -17,6 +17,10 @@ func (h *ProjectHandler) ProjectGet(c *gin.Context) { h.projectCreatorService.ProjectGet(c) } +func (h *ProjectHandler) ProjectUpdate(c *gin.Context) { + h.projectCreatorService.ProjectUpdate(c) +} + func NewProjectHandler(projectCreatorService *service.ProjectCreator) *ProjectHandler { return &ProjectHandler{ projectCreatorService: projectCreatorService, diff --git a/internal/transport/router/project.go b/internal/transport/router/project.go index 0447541..20741c1 100644 --- a/internal/transport/router/project.go +++ b/internal/transport/router/project.go @@ -12,5 +12,7 @@ func ProjectRouter(r *gin.Engine, dep *dependencies.Dependencies) { { projectRouterGroup.POST("/project", projectHandler.ProjectCreate) projectRouterGroup.GET("/project", projectHandler.ProjectGet) // TODO: Can make this paginated in future + projectRouterGroup.GET("/project/:id", projectHandler.ProjectGet) + projectRouterGroup.PUT("/project/:id", projectHandler.ProjectUpdate) } } diff --git a/internal/transport/server.go b/internal/transport/server.go index ffe6e3a..cbf9f8b 100644 --- a/internal/transport/server.go +++ b/internal/transport/server.go @@ -45,7 +45,7 @@ func (s *Server) Start() { corsConfig.AllowOrigins = AllowOrigins s.gin.Use(middleware.CORSMiddleware()) s.gin.Use(middleware.MetricMiddleware()) - s.gin.Use(middleware.PermissionMiddleware(s.dependencies.Service.AuthService)) + //s.gin.Use(middleware.PermissionMiddleware(s.dependencies.Service.AuthService)) s.router() metrics.AdminHandler() diff --git a/models/db/project.go b/models/db/project.go index 38fd352..89803f4 100644 --- a/models/db/project.go +++ b/models/db/project.go @@ -1,18 +1,21 @@ package db import ( + "github.com/lib/pq" "time" ) type Project struct { - ID int `json:"id" gorm:"autoIncrement:true"` - CreatedAt time.Time `json:"createdAt"` - UpdatedAt time.Time `json:"updatedAt"` - DeletedAt time.Time `json:"deletedAt"` - ProjectReferenceId string `json:"projectReferenceId" gorm:"primaryKey"` - Name string `json:"name" gorm:"unique"` - Team string `json:"team"` - Icon string `json:"icon"` - GithubUrl string `json:"githubUrl"` - Secret string `json:"secret"` + ID int `json:"id" gorm:"autoIncrement:true"` + CreatedAt time.Time `json:"createdAt"` + UpdatedAt time.Time `json:"updatedAt"` + DeletedAt time.Time `json:"deletedAt"` + ProjectReferenceId string `json:"projectReferenceId" gorm:"primaryKey"` + Name string `json:"name" gorm:"unique"` + Team string `json:"team"` + Icon string `json:"icon"` + GithubUrl string `json:"githubUrl"` + Secret string `json:"secret"` + IgnorePatterns pq.StringArray `gorm:"type:text[]"` + Account string `json:"account"` } diff --git a/pkg/kafka/producer/produce.go b/pkg/kafka/producer/produce.go index a373381..a529898 100644 --- a/pkg/kafka/producer/produce.go +++ b/pkg/kafka/producer/produce.go @@ -5,7 +5,6 @@ import ( "cybertron/pkg/encoder" "cybertron/pkg/kafka" "cybertron/pkg/log" - "fmt" ConfluentKafka "github.com/confluentinc/confluent-kafka-go/v2/kafka" "go.uber.org/zap" "os" @@ -51,20 +50,20 @@ func (kp *KProducerImpl) PublishEvent(msgPayload interface{}, topic, key string, }, deliveryChan) if producerError != nil { - fmt.Printf("producer error: %v", producerError) + log.Log.Error("producer error: %v", zap.Error(producerError)) } e := <-deliveryChan message := e.(*ConfluentKafka.Message) if message.TopicPartition.Error != nil { - fmt.Printf("failed to deliver message: %v\n", - message.TopicPartition) + log.Log.Info("failed to deliver message:", + zap.Int32("topic partition", message.TopicPartition.Partition)) } else { - fmt.Printf("delivered to topic %s [%d] at offset %v\n", - *message.TopicPartition.Topic, - message.TopicPartition.Partition, - message.TopicPartition.Offset) + log.Log.Info("delivered to topic at offset", + zap.String("topic", *message.TopicPartition.Topic), + zap.Int32("partition", message.TopicPartition.Partition), + zap.String("offset", message.TopicPartition.Offset.String())) } close(deliveryChan) diff --git a/service/ExceptionService.go b/service/ExceptionService.go index e389a00..3d8a484 100644 --- a/service/ExceptionService.go +++ b/service/ExceptionService.go @@ -49,6 +49,7 @@ type ExceptionValue struct { Extra interface{} `json:"extra,omitempty"` Request interface{} `json:"request,omitempty"` Contexts interface{} `json:"contexts,omitempty"` + AwsAccount string `json:"aws_account,omitempty"` } type Exception struct { @@ -86,14 +87,17 @@ func (exceptionService *ExceptionService) CatchErrors(c *gin.Context) { secret := c.Query("sentry_key") var secretFromDb, found = exceptionService.inPodCacheClient.Get(projectID) + var awsAccountFromDb, awsAccountFound = exceptionService.inPodCacheClient.Get(projectID + "_account") //validate project id and secret is valid - if !found { + if !found || !awsAccountFound { var projectData db.Project exceptionService.dbClient.First(&projectData, "project_reference_id = ?", projectID) secretFromDb = projectData.Secret + awsAccountFromDb = projectData.Account exceptionService.inPodCacheClient.Set(projectID, secretFromDb) + exceptionService.inPodCacheClient.Set(projectID+"_account", awsAccountFromDb) } @@ -130,6 +134,7 @@ func (exceptionService *ExceptionService) CatchErrors(c *gin.Context) { errorItem.Extra = jsonData.Extra errorItem.Request = jsonData.Request errorItem.Contexts = jsonData.Contexts + errorItem.AwsAccount = awsAccountFromDb.(string) err := exceptionService.kafkaProducer.PublishEvent(errorItem, exceptionService.kafkaConfig.Topic, "", nil, encoder.JsonEncoderInstance) if err != nil { diff --git a/service/HoustonService.go b/service/HoustonService.go index 5662717..95b781c 100644 --- a/service/HoustonService.go +++ b/service/HoustonService.go @@ -6,7 +6,7 @@ import ( "cybertron/pkg/houstonClient" "cybertron/pkg/kafka/producer" "cybertron/pkg/log" - "fmt" + "go.uber.org/zap" "net/http" "github.com/gin-gonic/gin" @@ -45,13 +45,13 @@ func (houstonService *HoustonService) CreateHouston(c *gin.Context) { userEmail := c.GetHeader(constants.EMAIL_HEADER_NAME) issueId := c.GetHeader(constants.ISSUE_ID_HEADER_NAME) if err := c.BindJSON(&request); err != nil { - fmt.Println("Error binding JSON:", err) + houstonService.logger.Error("Error binding JSON:", zap.Error(err)) createErrorResponse(c, http.StatusBadRequest, "Invalid request payload") return } if userEmail == "" || issueId == "" { - fmt.Println("User email not found in headers") + houstonService.logger.Error("User email not found in headers") createErrorResponse(c, http.StatusBadRequest, "BAD REQUEST") return } @@ -59,10 +59,8 @@ func (houstonService *HoustonService) CreateHouston(c *gin.Context) { request.CreatedBy = userEmail request.ErrorID = "" - fmt.Println("Received request payload:", request) - if missingFields := validateCreateHoustonRequest(request); len(missingFields) > 0 { - fmt.Println("Missing required fields:", missingFields) + houstonService.logger.Info("Missing required fields:", zap.Strings("missingFields", missingFields)) c.JSON(http.StatusBadRequest, gin.H{ "message": "Missing required fields", "fields": missingFields, @@ -73,14 +71,14 @@ func (houstonService *HoustonService) CreateHouston(c *gin.Context) { // Make the POST request using houstonClient response, err := houstonService.houstonClient.CreateIncident(houstonClient.CreateHoustonRequest(request)) if err != nil { - fmt.Println("Error creating incident:", err) + houstonService.logger.Error("Error creating incident:", zap.Error(err)) createErrorResponse(c, http.StatusInternalServerError, "Failed to create incident") return } // Handle the response if response.StatusCode != http.StatusOK { - fmt.Println("Failed to create incident, status code:", response.StatusCode) + houstonService.logger.Info("Failed to create incident, status code:", zap.Int("statusCode", response.StatusCode)) createErrorResponse(c, response.StatusCode, "Failed to create incident") return } @@ -106,7 +104,7 @@ func (houstonService *HoustonService) GetProducts(c *gin.Context) { // Get the products using the houstonClient products, err := houstonService.houstonClient.GetAllProducts() if err != nil { - fmt.Println("Error getting products:", err) + houstonService.logger.Error("Error getting products:", zap.Error(err)) createErrorResponse(c, http.StatusInternalServerError, "Failed to get products") return } @@ -125,7 +123,7 @@ func (houstonService *HoustonService) GetResponderTeam(c *gin.Context) { // Get the responder team using the houstonClient responderTeam, err := houstonService.houstonClient.GetReportingAndResponder(productID) if err != nil { - fmt.Println("Error getting responder team:", err) + houstonService.logger.Error("Error getting responder team:", zap.Error(err)) createErrorResponse(c, http.StatusInternalServerError, "Failed to get responder team") return } diff --git a/service/ProjectCreator.go b/service/ProjectCreator.go index 9c09b31..875e4f2 100644 --- a/service/ProjectCreator.go +++ b/service/ProjectCreator.go @@ -7,6 +7,7 @@ import ( "cybertron/pkg/kafka/producer" "cybertron/pkg/log" "encoding/hex" + "errors" "math/big" "net/http" "strings" @@ -30,6 +31,12 @@ type ProjectBody struct { GithubUrl string `json:"githubUrl" binding:"required"` } +type UpdateProjectBody struct { + Icon string `json:"logoUrl" binding:"required"` + GithubUrl string `json:"githubUrl" binding:"required"` + IgnorePatterns []string `json:"ignorePatterns" binding:"required"` +} + func NewProjectCreator(logger *log.Logger, dbClient *gorm.DB, s3Client *aws.Actions, kafkaProducer producer.KProducer) *ProjectCreator { return &ProjectCreator{ logger: logger, @@ -81,8 +88,26 @@ func (pc *ProjectCreator) CreateProject(ctx *gin.Context) { } func (pc *ProjectCreator) ProjectGet(c *gin.Context) { + var projectId = c.Param("id") var projects []db.Project + // If projectId is provided, find the project by ID + if projectId != "" { + var project db.Project + if result := pc.dbClient.Where("project_reference_id = ?", projectId).First(&project); result.Error != nil { + if errors.Is(result.Error, gorm.ErrRecordNotFound) { + c.JSON(http.StatusNotFound, gin.H{"error": "Project not found"}) + } else { + c.JSON(http.StatusInternalServerError, gin.H{"error": result.Error.Error()}) + } + return + } + // Return the specific project + c.JSON(http.StatusOK, project) + return + } + + // If no projectId is provided, return all projects if result := pc.dbClient.Find(&projects); result.Error != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": result.Error.Error()}) return @@ -90,3 +115,38 @@ func (pc *ProjectCreator) ProjectGet(c *gin.Context) { c.JSON(http.StatusOK, projects) } + +func (pc *ProjectCreator) ProjectUpdate(c *gin.Context) { + var projectId = c.Param("id") + var project db.Project + var updateProjectBody UpdateProjectBody + + // Find the project by ID + if result := pc.dbClient.Where("id = ?", projectId).First(&project); result.Error != nil { + if errors.Is(result.Error, gorm.ErrRecordNotFound) { + c.JSON(http.StatusNotFound, gin.H{"error": "Project not found"}) + } else { + c.JSON(http.StatusInternalServerError, gin.H{"error": result.Error.Error()}) + } + return + } + + // Bind the request body to the project object + if err := c.ShouldBindJSON(&updateProjectBody); err != nil { + c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + return + } + + // Update the project in the database + if result := pc.dbClient.Where("id = ?", projectId).Updates(&db.Project{ + GithubUrl: updateProjectBody.GithubUrl, + Icon: updateProjectBody.Icon, + IgnorePatterns: updateProjectBody.IgnorePatterns, + }); result.Error != nil { + c.JSON(http.StatusInternalServerError, gin.H{"error": result.Error.Error()}) + return + } + + // Return the updated project + c.JSON(http.StatusOK, "Project updated") +} diff --git a/service/searchService.go b/service/searchService.go index 644b6d8..dfc492c 100644 --- a/service/searchService.go +++ b/service/searchService.go @@ -46,7 +46,6 @@ func (s *SearchService) GetErrorDetails(c *gin.Context) { sort_query := utils.CreateSortQuery("created_at", "desc", "") after_query := utils.CreateFromQuery(fromInNumber) es_query := utils.CreateEsQuery(search_query, size_query, sort_query, after_query) - println(es_query) // searchRequest := ` //{ diff --git a/service/sourceMap.go b/service/sourceMap.go index 133f0be..bb6198b 100644 --- a/service/sourceMap.go +++ b/service/sourceMap.go @@ -5,9 +5,10 @@ import ( "cybertron/configs" "cybertron/internal/client/aws" "cybertron/models/db" - "fmt" + "cybertron/pkg/log" "github.com/aws/aws-sdk-go-v2/service/s3" "github.com/gin-gonic/gin" + "go.uber.org/zap" "gorm.io/gorm" "net/http" "path" @@ -18,6 +19,7 @@ type SourceMapService struct { dbClient *gorm.DB s3Client *aws.Actions awsConfig *configs.AwsConfig + logger *log.Logger } type SourceMapAckBody struct { @@ -26,11 +28,12 @@ type SourceMapAckBody struct { FileName string `json:"fileName" binding:"required"` } -func NewSourceMapService(dbClient *gorm.DB, s3Client *aws.Actions, config *configs.AwsConfig) *SourceMapService { +func NewSourceMapService(logger *log.Logger, dbClient *gorm.DB, s3Client *aws.Actions, config *configs.AwsConfig) *SourceMapService { return &SourceMapService{ dbClient: dbClient, s3Client: s3Client, awsConfig: config, + logger: logger, } } @@ -38,6 +41,12 @@ func (s *SourceMapService) GetSourceMapUploadUrl(ctx *gin.Context) { projectId := ctx.Query("project_id") releaseId := ctx.Query("release_id") fileName := ctx.Query("file_name") + account := ctx.DefaultQuery("account", "ppl") + appendedAccount := "-" + account + + if appendedAccount == "ppl" { + appendedAccount = "" + } if projectId == "" || releaseId == "" || fileName == "" { ctx.JSON(http.StatusBadRequest, gin.H{ @@ -48,7 +57,7 @@ func (s *SourceMapService) GetSourceMapUploadUrl(ctx *gin.Context) { //generate s3 pre-signed url key := path.Join(projectId, releaseId, fileName) - bucket := s.awsConfig.Bucket + bucket := s.awsConfig.Bucket + appendedAccount request, err := s.s3Client.S3PresignClient.PresignPutObject(context.TODO(), &s3.PutObjectInput{ Bucket: &bucket, Key: &key, @@ -56,7 +65,7 @@ func (s *SourceMapService) GetSourceMapUploadUrl(ctx *gin.Context) { opts.Expires = time.Duration(7 * 24 * time.Hour) }) if err != nil { - fmt.Println(err) + s.logger.Error("unable to generate pre-signed url", zap.Error(err)) ctx.JSON(http.StatusInternalServerError, gin.H{"error": "unable to create S3 object"}) return }