# Guss

Generate [Signed URLs]( for Google Cloud Storage in Elixir.

## Installation

  1. Add `guss` to your list of dependencies in `mix.exs`:

def deps do
    {:guss, "~> 0.1.0"}

  2. If you're using [Goth]( for authentication, be sure to configure your credentials:

config :goth,
  json: {:system, "GCP_CREDENTIALS_JSON"}

## Documentation

Documentation can be found at [](

## Usage

First, create a new resource with your URL components:

iex(1)> url ="downloads", "movie.mp4", content_type: "video/mp4")
%Guss.Resource{bucket: "downloads", objectname: "movie.mp4"...}

Then, sign the url:

iex(2)> Guss.sign(url)
{:ok, ""}

### Signatures

By default, `sign/1` will use the default credentials stored in the Goth config to generate the signature.

To specify an account other than the default, update the `:account` on the resource:

Guss.sign(%{url | account: ""})

It is also possible to [use Guss without Goth](#usage-without-goth).

### String Components

#### Expiration

The default `:expires` value is 1 hour.  You can use `Guss.expires_in/1` to set a custom future timestamp:

iex(4)> url ="downloads", "movie.mp4", expires: Guss.expires_in({1, :day}))
  account: :default,
  base_url: "",
  bucket: "downloads",
  content_md5: nil,
  content_type: nil,
  expires: 1543526299,
  extensions: [],
  http_verb: :get,
  objectname: "movie.mp4"

#### Content Type

Setting the content type in the signature requires the `Content-Type` header to be set on upload:

Guss.put("downloads", "movie.mp4", content_type: "video/mp4")

#### Custom Extension Headers

Guss can incorporate custom extension headers into the URL signature.

For instance, to set the canned ACL policy for the object during upload:

Guss.put("bucket", "objectname", acl: :public_read)

Any `x-goog-` header can be included in the options list...

Guss.put("bucket", "objectname", content_length_range: "0,256")

...including `x-goog-meta-` headers:

Guss.put("bucket", "objectname", meta: [project: [name: "My Project"]])

**Please Note:** All headers that appear within the signature **MUST** also appear in the request to the Signed URL, or the request will be rejected.

## Usage without Goth

If you store your authentication data somewhere other than Goth, you can supply your own config module when signing URLs.

First, create a module that can return values for `"client_email"` and `"private_key"`:

defmodule MyGussConfig do
  def get(account \\ :default, key)
  def get(account, "client_email"), do: fetch_email(account)
  def get(account, "private_key"), do: fetch_private_key(account)

Then, create a resource and sign it using your config module:

|>"objectname", account: "")
|> Guss.sign(config_module: MyGussConfig)