package service import ( "context" "cybertron/configs" "cybertron/internal/client/aws" "cybertron/models/db" "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" "time" ) type SourceMapService struct { dbClient *gorm.DB s3Client *aws.Actions awsConfig *configs.AwsConfig logger *log.Logger } type SourceMapAckBody struct { ProjectReferenceId string `json:"projectId" binding:"required"` ReleaseId string `json:"releaseId" binding:"required"` FileName string `json:"fileName" binding:"required"` } func NewSourceMapService(dbClient *gorm.DB, s3Client *aws.Actions, config *configs.AwsConfig, logger *log.Logger) *SourceMapService { return &SourceMapService{ dbClient: dbClient, s3Client: s3Client, awsConfig: config, logger: logger, } } 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 account == "ppl" { appendedAccount = "" } if projectId == "" || releaseId == "" || fileName == "" { ctx.JSON(http.StatusBadRequest, gin.H{ "error": "Missing required query parameters: project_id, release_id, and file_name are required.", }) return } //generate s3 pre-signed url key := path.Join(projectId, releaseId, fileName) bucket := s.awsConfig.Bucket + appendedAccount request, err := s.s3Client.S3PresignClient.PresignPutObject(context.TODO(), &s3.PutObjectInput{ Bucket: &bucket, Key: &key, }, func(opts *s3.PresignOptions) { opts.Expires = time.Duration(7 * 24 * time.Hour) }) if err != nil { 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 } // save state in database //result := *s.dbClient.Create(&db.SourceMap{ // ProjectReferenceId: projectId, // ReleaseReferenceId: releaseId, // FileName: fileName, // State: "IN_PROGRESS", //}) //if result.Error != nil { // ctx.JSON(http.StatusInternalServerError, gin.H{"error": result.Error.Error(), "message": "Failed to source map"}) // return //} ctx.JSON(http.StatusOK, gin.H{ "url": request.URL, }) return } func (s *SourceMapService) SourceMapUploadAck(c *gin.Context) { //var sourceMapAckBody SourceMapAckBody //if err := c.BindJSON(&sourceMapAckBody); err != nil { // c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) // return //} // ////find the record to update ack //var existingSourceMap db.SourceMap //existingRecordError := s.dbClient.First(&existingSourceMap, "project_reference_id = ? and release_reference_id= ? and file_name = ?", sourceMapAckBody.ProjectReferenceId, sourceMapAckBody.ReleaseId, sourceMapAckBody.FileName).Error //if existingRecordError != nil { // c.JSON(http.StatusBadRequest, gin.H{"error": existingRecordError.Error()}) // return //} // //existingSourceMap.State = "DONE" // //err := s.dbClient.Save(&existingSourceMap).Error //if err != nil { // c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) // return //} c.JSON(http.StatusOK, gin.H{"status": "Source map stored successfully"}) } func (s *SourceMapService) ValidateSourceMap(ctx *gin.Context) { projectId := ctx.Query("project_id") releaseId := ctx.Query("release_id") fileName := ctx.Query("file_name") if projectId == "" || releaseId == "" || fileName == "" { ctx.JSON(http.StatusBadRequest, gin.H{ "error": "Missing required query parameters: project_id, release_id, and file_name are required.", }) } var existingSourceMap db.SourceMap result := s.dbClient.First(&existingSourceMap, "ProjectReferenceId = ? and ReleaseReferenceId= ? and file_name = ?", projectId, releaseId, fileName) if result.Error != nil { ctx.JSON(http.StatusInternalServerError, gin.H{"error": result.Error.Error()}) return } if existingSourceMap.State == "DONE" { ctx.JSON(http.StatusOK, gin.H{"status": "Source map stored successfully"}) } ctx.JSON(http.StatusNotFound, gin.H{"error": "Source map not found"}) }