blob: a6a0cc5eec8c8eacdf3ee708542ea7917d4ddbb0 [file] [log] [blame]
// Stores and retrieves jsfiddles in Google Storage.
package store
import (
"context"
"crypto/sha256"
"fmt"
"io/ioutil"
"strings"
"cloud.google.com/go/storage"
"go.skia.org/infra/go/auth"
"go.skia.org/infra/go/httputils"
"go.skia.org/infra/go/util"
"google.golang.org/api/option"
)
const (
JSFIDDLE_STORAGE_BUCKET = "skia-jsfiddle"
)
// Store is used to read and write user code and media to and from Google
// Storage.
type Store struct {
bucket *storage.BucketHandle
}
// New creates a new Store.
//
// local - True if running locally.
func New(local bool) (*Store, error) {
ts, err := auth.NewDefaultTokenSource(local, auth.SCOPE_READ_WRITE)
if err != nil {
return nil, fmt.Errorf("Problem setting up client OAuth: %s", err)
}
client := httputils.DefaultClientConfig().WithTokenSource(ts).With2xxOnly().Client()
storageClient, err := storage.NewClient(context.Background(), option.WithHTTPClient(client))
if err != nil {
return nil, fmt.Errorf("Problem creating storage client: %s", err)
}
return &Store{
bucket: storageClient.Bucket(JSFIDDLE_STORAGE_BUCKET),
}, nil
}
// PutCode writes the code to Google Storage.
// Returns the fiddleHash.
func (s *Store) PutCode(code, fiddleType string) (string, error) {
hash := computeHash(code)
path := strings.Join([]string{fiddleType, hash, "draw.js"}, "/")
w := s.bucket.Object(path).NewWriter(context.Background())
defer util.Close(w)
w.ObjectAttrs.ContentEncoding = "text/plain"
if n, err := w.Write([]byte(code)); err != nil {
return "", fmt.Errorf("There was a problem storing the code. Uploaded %d bytes: %s", n, err)
}
return hash, nil
}
// PutCode writes the code to Google Storage.
// Returns the fiddleHash.
func (s *Store) GetCode(hash, fiddleType string) (string, error) {
path := strings.Join([]string{fiddleType, hash, "draw.js"}, "/")
o := s.bucket.Object(path)
r, err := o.NewReader(context.Background())
if err != nil {
return "", fmt.Errorf("Failed to open source file for %s: %s", hash, err)
}
b, err := ioutil.ReadAll(r)
if err != nil {
return "", fmt.Errorf("Failed to read source file for %s: %s", hash, err)
}
return string(b), nil
}
func computeHash(code string) string {
sum := sha256.Sum256([]byte(code))
return fmt.Sprintf("%x", sum)
}