package main import ( "encoding/json" "flag" "fmt" "log" "net/http" "os" "path" "time" "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/credentials" "github.com/aws/aws-sdk-go/aws/session" "github.com/aws/aws-sdk-go/service/s3" "github.com/gin-gonic/gin" ) const SharingTime = 10 * time.Minute var ( s3_endpoint string s3_region = "us" s3_bucket string s3_access_key string s3_secret_key string s3_path_style bool ) func init() { s3_endpoint, _ = os.LookupEnv("S3_ENDPOINT") if region, ok := os.LookupEnv("S3_REGION"); ok { s3_region = region } s3_bucket, _ = os.LookupEnv("S3_BUCKET") s3_access_key, _ = os.LookupEnv("S3_ACCESS_KEY") s3_secret_key, _ = os.LookupEnv("S3_SECRET_KEY") if path_style, ok := os.LookupEnv("S3_PATH_STYLE"); ok { s3_path_style = path_style == "1" || path_style == "ON" || path_style == "on" || path_style == "TRUE" || path_style == "true" || path_style == "yes" || path_style == "YES" } flag.StringVar(&s3_endpoint, "s3-endpoint", s3_endpoint, "When using S3 backend, endpoint to use") flag.StringVar(&s3_region, "s3-region", s3_region, "When using S3 backend, region to use") flag.StringVar(&s3_bucket, "s3-bucket", s3_bucket, "When using S3 backend, bucket to use") flag.StringVar(&s3_access_key, "s3-access-key", s3_access_key, "When using S3 backend, Access Key") flag.StringVar(&s3_secret_key, "s3-secret-key", s3_secret_key, "When using S3 backend, Secret Key") flag.BoolVar(&s3_path_style, "s3-path-style", s3_path_style, "When using S3 backend, force path style (when using minio)") } func s3NewSession() (*session.Session, error) { return session.NewSession(&aws.Config{ Credentials: credentials.NewStaticCredentials(s3_access_key, s3_secret_key, ""), Endpoint: aws.String(s3_endpoint), Region: aws.String(s3_region), S3ForcePathStyle: &s3_path_style, }) } func declareAPIWorkSubmissionsRoutes(router *gin.RouterGroup) { router.GET("/submission", func(c *gin.Context) { var u *User if user, ok := c.Get("user"); ok { u = user.(*User) } else { u = c.MustGet("LoggedUser").(*User) } work := c.MustGet("work").(*Work) s, err := s3NewSession() if err != nil { c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": "Something goes wrong."}) return } result, err := s3.New(s).GetObject(&s3.GetObjectInput{ Bucket: aws.String(s3_bucket), Key: aws.String(path.Join(fmt.Sprintf("%d", work.Id), fmt.Sprintf("rendu-%s.metadata", u.Login))), }) if err != nil { c.AbortWithStatusJSON(http.StatusNotFound, gin.H{"errmsg": "Submission not found."}) return } tmp := map[string]interface{}{} err = json.NewDecoder(result.Body).Decode(&tmp) if err != nil { log.Println("Unable to decode JSON metadata:", err.Error()) c.AbortWithStatusJSON(http.StatusNotFound, gin.H{"errmsg": "Submission not found."}) return } c.JSON(http.StatusOK, tmp) }) router.GET("/download", func(c *gin.Context) { var u *User if user, ok := c.Get("user"); ok { u = user.(*User) } else { u = c.MustGet("LoggedUser").(*User) } work := c.MustGet("work").(*Work) s, err := s3NewSession() if err != nil { c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": "Something goes wrong."}) return } req, _ := s3.New(s).GetObjectRequest(&s3.GetObjectInput{ Bucket: aws.String(s3_bucket), Key: aws.String(path.Join(fmt.Sprintf("%d", work.Id), fmt.Sprintf("rendu-%s.tar.xz", u.Login))), }) url, err := req.Presign(SharingTime) if err != nil { log.Println("Unable to create presign URL:", err) c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": "Something goes wrong when creating the presigned URL."}) return } c.Redirect(http.StatusFound, url) }) }