// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package storage

import (
	"crypto"
	"crypto/rand"
	"crypto/rsa"
	"crypto/sha256"
	"encoding/base64"
	"encoding/json"
	"errors"
	"fmt"
	"net/url"
	"strings"
	"time"
)

// PostPolicyV4Options are used to construct a signed post policy.
// Please see https://cloud.google.com/storage/docs/xml-api/post-object
// for reference about the fields.
type PostPolicyV4Options struct {
	// GoogleAccessID represents the authorizer of the signed URL generation.
	// It is typically the Google service account client email address from
	// the Google Developers Console in the form of "xxx@developer.gserviceaccount.com".
	// Required.
	GoogleAccessID string

	// PrivateKey is the Google service account private key. It is obtainable
	// from the Google Developers Console.
	// At https://console.developers.google.com/project/<your-project-id>/apiui/credential,
	// create a service account client ID or reuse one of your existing service account
	// credentials. Click on the "Generate new P12 key" to generate and download
	// a new private key. Once you download the P12 file, use the following command
	// to convert it into a PEM file.
	//
	//    $ openssl pkcs12 -in key.p12 -passin pass:notasecret -out key.pem -nodes
	//
	// Provide the contents of the PEM file as a byte slice.
	// Exactly one of PrivateKey or SignBytes must be non-nil.
	PrivateKey []byte

	// SignBytes is a function for implementing custom signing.
	//
	// Deprecated: Use SignRawBytes. If both SignBytes and SignRawBytes are defined,
	// SignBytes will be ignored.
	// This SignBytes function expects the bytes it receives to be hashed, while
	// SignRawBytes accepts the raw bytes without hashing, allowing more flexibility.
	// Add the following to the top of your signing function to hash the bytes
	// to use SignRawBytes instead:
	//		shaSum := sha256.Sum256(bytes)
	//		bytes = shaSum[:]
	//
	SignBytes func(hashBytes []byte) (signature []byte, err error)

	// SignRawBytes is a function for implementing custom signing. For example, if
	// your application is running on Google App Engine, you can use
	// appengine's internal signing function:
	//		ctx := appengine.NewContext(request)
	//     	acc, _ := appengine.ServiceAccount(ctx)
	//     	&PostPolicyV4Options{
	//     		GoogleAccessID: acc,
	//     		SignRawBytes: func(b []byte) ([]byte, error) {
	//     			_, signedBytes, err := appengine.SignBytes(ctx, b)
	//     			return signedBytes, err
	//     		},
	//     		// etc.
	//     	})
	//
	// SignRawBytes is equivalent to the SignBytes field on SignedURLOptions;
	// that is, you may use the same signing function for the two.
	//
	// Exactly one of PrivateKey or SignRawBytes must be non-nil.
	SignRawBytes func(bytes []byte) (signature []byte, err error)

	// Expires is the expiration time on the signed URL.
	// It must be a time in the future.
	// Required.
	Expires time.Time

	// Style provides options for the type of URL to use. Options are
	// PathStyle (default), BucketBoundHostname, and VirtualHostedStyle. See
	// https://cloud.google.com/storage/docs/request-endpoints for details.
	// Optional.
	Style URLStyle

	// Insecure when set indicates that the generated URL's scheme
	// will use "http" instead of "https" (default).
	// Optional.
	Insecure bool

	// Fields specifies the attributes of a PostPolicyV4 request.
	// When Fields is non-nil, its attributes must match those that will
	// passed into field Conditions.
	// Optional.
	Fields *PolicyV4Fields

	// The conditions that the uploaded file will be expected to conform to.
	// When used, the failure of an upload to satisfy a condition will result in
	// a 4XX status code, back with the message describing the problem.
	// Optional.
	Conditions []PostPolicyV4Condition

	shouldHashSignBytes bool
}

func (opts *PostPolicyV4Options) clone() *PostPolicyV4Options {
	return &PostPolicyV4Options{
		GoogleAccessID:      opts.GoogleAccessID,
		PrivateKey:          opts.PrivateKey,
		SignBytes:           opts.SignBytes,
		SignRawBytes:        opts.SignRawBytes,
		Expires:             opts.Expires,
		Style:               opts.Style,
		Insecure:            opts.Insecure,
		Fields:              opts.Fields,
		Conditions:          opts.Conditions,
		shouldHashSignBytes: opts.shouldHashSignBytes,
	}
}

// PolicyV4Fields describes the attributes for a PostPolicyV4 request.
type PolicyV4Fields struct {
	// ACL specifies the access control permissions for the object.
	// Optional.
	ACL string
	// CacheControl specifies the caching directives for the object.
	// Optional.
	CacheControl string
	// ContentType specifies the media type of the object.
	// Optional.
	ContentType string
	// ContentDisposition specifies how the file will be served back to requesters.
	// Optional.
	ContentDisposition string
	// ContentEncoding specifies the decompressive transcoding that the object.
	// This field is complementary to ContentType in that the file could be
	// compressed but ContentType specifies the file's original media type.
	// Optional.
	ContentEncoding string
	// Metadata specifies custom metadata for the object.
	// If any key doesn't begin with "x-goog-meta-", an error will be returned.
	// Optional.
	Metadata map[string]string
	// StatusCodeOnSuccess when set, specifies the status code that Cloud Storage
	// will serve back on successful upload of the object.
	// Optional.
	StatusCodeOnSuccess int
	// RedirectToURLOnSuccess when set, specifies the URL that Cloud Storage
	// will serve back on successful upload of the object.
	// Optional.
	RedirectToURLOnSuccess string
}

// PostPolicyV4 describes the URL and respective form fields for a generated PostPolicyV4 request.
type PostPolicyV4 struct {
	// URL is the generated URL that the file upload will be made to.
	URL string
	// Fields specifies the generated key-values that the file uploader
	// must include in their multipart upload form.
	Fields map[string]string
}

// PostPolicyV4Condition describes the constraints that the subsequent
// object upload's multipart form fields will be expected to conform to.
type PostPolicyV4Condition interface {
	isEmpty() bool
	json.Marshaler
}

type startsWith struct {
	key, value string
}

func (sw *startsWith) MarshalJSON() ([]byte, error) {
	return json.Marshal([]string{"starts-with", sw.key, sw.value})
}
func (sw *startsWith) isEmpty() bool {
	return sw.value == ""
}

// ConditionStartsWith checks that an attributes starts with value.
// An empty value will cause this condition to be ignored.
func ConditionStartsWith(key, value string) PostPolicyV4Condition {
	return &startsWith{key, value}
}

type contentLengthRangeCondition struct {
	start, end uint64
}

func (clr *contentLengthRangeCondition) MarshalJSON() ([]byte, error) {
	return json.Marshal([]interface{}{"content-length-range", clr.start, clr.end})
}
func (clr *contentLengthRangeCondition) isEmpty() bool {
	return clr.start == 0 && clr.end == 0
}

type singleValueCondition struct {
	name, value string
}

func (svc *singleValueCondition) MarshalJSON() ([]byte, error) {
	return json.Marshal(map[string]string{svc.name: svc.value})
}
func (svc *singleValueCondition) isEmpty() bool {
	return svc.value == ""
}

// ConditionContentLengthRange constraints the limits that the
// multipart upload's range header will be expected to be within.
func ConditionContentLengthRange(start, end uint64) PostPolicyV4Condition {
	return &contentLengthRangeCondition{start, end}
}

func conditionRedirectToURLOnSuccess(redirectURL string) PostPolicyV4Condition {
	return &singleValueCondition{"success_action_redirect", redirectURL}
}

func conditionStatusCodeOnSuccess(statusCode int) PostPolicyV4Condition {
	svc := &singleValueCondition{name: "success_action_status"}
	if statusCode > 0 {
		svc.value = fmt.Sprintf("%d", statusCode)
	}
	return svc
}

// GenerateSignedPostPolicyV4 generates a PostPolicyV4 value from bucket, object and opts.
// The generated URL and fields will then allow an unauthenticated client to perform multipart uploads.
// If initializing a Storage Client, instead use the Bucket.GenerateSignedPostPolicyV4
// method which uses the Client's credentials to handle authentication.
func GenerateSignedPostPolicyV4(bucket, object string, opts *PostPolicyV4Options) (*PostPolicyV4, error) {
	if bucket == "" {
		return nil, errors.New("storage: bucket must be non-empty")
	}
	if object == "" {
		return nil, errors.New("storage: object must be non-empty")
	}
	now := utcNow()
	if err := validatePostPolicyV4Options(opts, now); err != nil {
		return nil, err
	}

	var signingFn func(hashedBytes []byte) ([]byte, error)
	switch {
	case opts.SignRawBytes != nil:
		signingFn = opts.SignRawBytes
	case opts.shouldHashSignBytes:
		signingFn = opts.SignBytes
	case len(opts.PrivateKey) != 0:
		parsedRSAPrivKey, err := parseKey(opts.PrivateKey)
		if err != nil {
			return nil, err
		}
		signingFn = func(b []byte) ([]byte, error) {
			sum := sha256.Sum256(b)
			return rsa.SignPKCS1v15(rand.Reader, parsedRSAPrivKey, crypto.SHA256, sum[:])
		}

	default:
		return nil, errors.New("storage: exactly one of PrivateKey or SignRawBytes must be set")
	}

	var descFields PolicyV4Fields
	if opts.Fields != nil {
		descFields = *opts.Fields
	}

	if err := validateMetadata(descFields.Metadata); err != nil {
		return nil, err
	}

	// Build the policy.
	conds := make([]PostPolicyV4Condition, len(opts.Conditions))
	copy(conds, opts.Conditions)
	conds = append(conds,
		// These are ordered lexicographically. Technically the order doesn't matter
		// for creating the policy, but we use this order to match the
		// cross-language conformance tests for this feature.
		&singleValueCondition{"acl", descFields.ACL},
		&singleValueCondition{"cache-control", descFields.CacheControl},
		&singleValueCondition{"content-disposition", descFields.ContentDisposition},
		&singleValueCondition{"content-encoding", descFields.ContentEncoding},
		&singleValueCondition{"content-type", descFields.ContentType},
		conditionRedirectToURLOnSuccess(descFields.RedirectToURLOnSuccess),
		conditionStatusCodeOnSuccess(descFields.StatusCodeOnSuccess),
	)

	YYYYMMDD := now.Format(yearMonthDay)
	policyFields := map[string]string{
		"key":                     object,
		"x-goog-date":             now.Format(iso8601),
		"x-goog-credential":       opts.GoogleAccessID + "/" + YYYYMMDD + "/auto/storage/goog4_request",
		"x-goog-algorithm":        "GOOG4-RSA-SHA256",
		"acl":                     descFields.ACL,
		"cache-control":           descFields.CacheControl,
		"content-disposition":     descFields.ContentDisposition,
		"content-encoding":        descFields.ContentEncoding,
		"content-type":            descFields.ContentType,
		"success_action_redirect": descFields.RedirectToURLOnSuccess,
	}
	for key, value := range descFields.Metadata {
		conds = append(conds, &singleValueCondition{key, value})
		policyFields[key] = value
	}

	// Following from the order expected by the conformance test cases,
	// hence manually inserting these fields in a specific order.
	conds = append(conds,
		&singleValueCondition{"bucket", bucket},
		&singleValueCondition{"key", object},
		&singleValueCondition{"x-goog-date", now.Format(iso8601)},
		&singleValueCondition{
			name:  "x-goog-credential",
			value: opts.GoogleAccessID + "/" + YYYYMMDD + "/auto/storage/goog4_request",
		},
		&singleValueCondition{"x-goog-algorithm", "GOOG4-RSA-SHA256"},
	)

	nonEmptyConds := make([]PostPolicyV4Condition, 0, len(opts.Conditions))
	for _, cond := range conds {
		if cond == nil || !cond.isEmpty() {
			nonEmptyConds = append(nonEmptyConds, cond)
		}
	}
	condsAsJSON, err := json.Marshal(map[string]interface{}{
		"conditions": nonEmptyConds,
		"expiration": opts.Expires.Format(time.RFC3339),
	})
	if err != nil {
		return nil, fmt.Errorf("storage: PostPolicyV4 JSON serialization failed: %v", err)
	}

	b64Policy := base64.StdEncoding.EncodeToString(condsAsJSON)
	var signature []byte
	var signErr error

	if opts.shouldHashSignBytes {
		// SignBytes expects hashed bytes as input instead of raw bytes, so we hash them
		shaSum := sha256.Sum256([]byte(b64Policy))
		signature, signErr = signingFn(shaSum[:])
	} else {
		signature, signErr = signingFn([]byte(b64Policy))
	}
	if signErr != nil {
		return nil, signErr
	}

	policyFields["policy"] = b64Policy
	policyFields["x-goog-signature"] = fmt.Sprintf("%x", signature)

	// Construct the URL.
	scheme := "https"
	if opts.Insecure {
		scheme = "http"
	}
	path := opts.Style.path(bucket, "") + "/"
	u := &url.URL{
		Path:    path,
		RawPath: pathEncodeV4(path),
		Host:    opts.Style.host(bucket),
		Scheme:  scheme,
	}

	if descFields.StatusCodeOnSuccess > 0 {
		policyFields["success_action_status"] = fmt.Sprintf("%d", descFields.StatusCodeOnSuccess)
	}

	// Clear out fields with blanks values.
	for key, value := range policyFields {
		if value == "" {
			delete(policyFields, key)
		}
	}
	pp4 := &PostPolicyV4{
		Fields: policyFields,
		URL:    u.String(),
	}
	return pp4, nil
}

// validatePostPolicyV4Options checks that:
// * GoogleAccessID is set
// * either PrivateKey or SignRawBytes/SignBytes is set, but not both
// * the deadline set in Expires is not in the past
// * if Style is not set, it'll use PathStyle
// * sets shouldHashSignBytes to true if opts.SignBytes should be used
func validatePostPolicyV4Options(opts *PostPolicyV4Options, now time.Time) error {
	if opts == nil || opts.GoogleAccessID == "" {
		return errors.New("storage: missing required GoogleAccessID")
	}
	if privBlank, signBlank := len(opts.PrivateKey) == 0, opts.SignBytes == nil && opts.SignRawBytes == nil; privBlank == signBlank {
		return errors.New("storage: exactly one of PrivateKey or SignRawBytes must be set")
	}
	if opts.Expires.Before(now) {
		return errors.New("storage: expecting Expires to be in the future")
	}
	if opts.Style == nil {
		opts.Style = PathStyle()
	}
	if opts.SignRawBytes == nil && opts.SignBytes != nil {
		opts.shouldHashSignBytes = true
	}
	return nil
}

// validateMetadata ensures that all keys passed in have a prefix of "x-goog-meta-",
// otherwise it will return an error.
func validateMetadata(hdrs map[string]string) (err error) {
	if len(hdrs) == 0 {
		return nil
	}

	badKeys := make([]string, 0, len(hdrs))
	for key := range hdrs {
		if !strings.HasPrefix(key, "x-goog-meta-") {
			badKeys = append(badKeys, key)
		}
	}
	if len(badKeys) != 0 {
		err = errors.New("storage: expected metadata to begin with x-goog-meta-, got " + strings.Join(badKeys, ", "))
	}
	return
}
