# GUIDE

[![Travis build status](http://img.shields.io/travis/gajus/guide/master.svg?style=flat-square)](https://travis-ci.org/gajus/guide)
[![Coveralls](https://img.shields.io/coveralls/gajus/guide.svg?style=flat-square)](https://coveralls.io/github/gajus/guide)
[![NPM version](http://img.shields.io/npm/v/guide.svg?style=flat-square)](https://www.npmjs.org/package/guide)
[![Canonical Code Style](https://img.shields.io/badge/code%20style-canonical-blue.svg?style=flat-square)](https://github.com/gajus/canonical)
[![Twitter Follow](https://img.shields.io/twitter/follow/kuizinas.svg?style=social&label=Follow)](https://twitter.com/kuizinas)

Encrypted Globally Unique Identifier (GUIDE) generator.

* [Implementation](#implementation)
* [Use case](#use-case)
* [API](#api)
* [Usage](#Usage)

## Implementation

* GUIDE is using aes-256-gcm encryption.
* Identifiers are encoded using URL-safe base64 encoding.

> `aes-256-gcm` is the closest thing I have found to a misuse resistant algorithm.
> If you know of a better encryption algorithm (misuse resistant) thats available to Node.js – [raise an issue](https://github.com/gajus/guide/issues).

## Use case

GUIDE is used to mitigate certain types of DDoS attacks.

* [Protecting APIs from the DDoS attacks by encrypting the PKs](https://medium.com/p/97a8a5090c89)

## API

```js
type GuidePayloadType = {|
  id: number | string,
  namespace: string,
  type: string
|};

/**
* @throws InvalidGuideError Throws if input guide cannot be decrypted.
* @throws UnexpectedNamespaceValueError Throws if the namespace contained in the payload does not match the expected namespace.
* @throws UnexpectedResourceTypeNameValueError Throws if the resource type name contained in the payload does not match the expected resource type name.
*/
type FromGuideType = (initializationVectorValue: string, expectedNamespace: string, expectedResourceTypeName: string, guide: string) => GuidePayloadType;

/**
 * @param initializationVectorValue Initialization vector. Must be at least 128 characters long.
 * @param namespace A namespace of the GUID (e.g. company name or the application name).
 * @param type A resource type name (e.g. article).
 */
type ToGuideType = (initializationVectorValue: string, namespace: string, type: string, id: number | string) => string;

```

## Usage

```js
import {
  fromGuide,
  toGuide,
} from 'guide';

const initializationVectorValue = 'lGMUlgYOZXkT7MWjRozJ7F3MlSm89SPkop2AvQciBk1xXLGCX5aUy3uIJHEInjQzyHZSnZ0NaQaVpEldAlVWeguOLYkW5ZluwbaHY0iWEgFULRV92GV5KgHj2P5YChgW';
const namespace = 'gajus';
const resourceTypeName = 'article';

const guide = toGuide(initializationVectorValue, namespace, resourceTypeName, 1);

// "ao-CZ7gmFSaFhA4tzWaM2CiOGtt772ZqJDB1k1ty3QWkc24Rx43iYuUc_S0ecZiiWS8aTP-0EQ"

const payload = fromGuide(initializationVectorValue, namespace, resourceTypeName, guide);

// {
//   "id": 1,
//   "namespace": "gajus",
//   "type": "article"
// }

```


## Handling errors

`fromGuide` method can throw the following errors.

|Error constructor name|Description|
|---|---|
|`InvalidGuideError`|Throws if input guide cannot be decrypted.|
|`UnexpectedNamespaceValueError`|Throws if the namespace contained in the payload does not match the expected namespace.|
|`UnexpectedResourceTypeNameValueError`|Throws if the resource type name contained in the payload does not match the expected resource type name.|

Error constructors can be imported from `guide` package.

`UnexpectedNamespaceValueError` and `UnexpectedResourceTypeNameValueError` extend from `InvalidGuideError`. It is enough to check if an error object is an instance of `InvalidGuideError` to assert that an error is a result of an invalid GUIDE.

```js
import {
  fromGuide,
  InvalidGuideError
} from 'guide';

try {
  fromGuide(initializationVectorValue, namespace, resourceTypeName, guide);
} catch (error) {
  if (error instanceof InvalidGuideError) {
    // Handle error.
  }

  // Re-throw other errors.
  throw error;
}

```
