# Static service

Microservice for working with files: upload to AWS, resize images, etc.

Support platforms:

- AWS S3

Support background actions:

- resize images ( processing in the background )

The microservice used
- PostgresSql for saving records about files
- RabbitMQ as queue for processing images in the background
- Rsa public key for request authentication

## How to use

### Prepare upload config

Create JSON file with templates: `upload.config.json`
## upload.config.json example:

The first level key (avatar/document) it's a template name, and your
future routing param key for uploading. Specify your keys.

Example:

```
{
  "avatar": {
    "maxSize": 10,
    "maxCount": 5,
    "extensions": ["png", "jpg", "jpeg"],
    "resize": [
      {
        "method": "contain",
        "args": [100, 100]
      },
      {
        "method": "contain",
        "args": [200, 200]
      }
    ]
  },
  "document": {
    "maxSize": 10,
    "maxCount": 3,
    "folder": "document",
    "extensions": ["pdf", "doc", "docs"]
  }
}
```

Template settings:
- maxSize: Maximum size of uploaded file in Mb. `Optional`
- maxCount: Maximum number of uploaded files. `Optional`
- extensions: Array of allowed files extensions. `Optional`
- folder: Folder in aws bucket. `Optional`
- resize: Config for files resizes: `Optional`
  - method: resize method from [jimp](https://www.npmjs.com/package/jimp) library
  - args: list of arguments of the chosen method from [jimp](https://www.npmjs.com/package/jimp) library

### Configure authentication
This service uses public (rsa or ECDSA) key for validating jwt token received from Authorization header or cookie.
Save publicKey and pass key path to RSA_PUBLIC_KEY_PATH environment. Default path: /app/key/publicKey.pem

### Launch the service
Then you need to run this service and connect it to PostgresSQL. For example, you can use Docker Compose:

```yaml
version: "3"
services:
  rabbitmq:
    image: "rabbitmq:3-management"
    ports:
      - "127.0.0.1:5672:5672"
      - "127.0.0.1:15672:15672"

  postgres:
    image: postgres:11.5-alpine
    ports:
      - "127.0.0.1:27192:5432"
    volumes:
      - postgres_data:/var/lib/postgresql/data/

  static-service:
    image: "pixelplex/static-service:0.1.10"
    environment:
      - AMQP_HOST=amqp://rabbitmq:5672
      - AWS_ACCESS_KEY_ID=aws_key
      - AWS_SECRET_ACCESS_KEY=aws_secret
      - AWS_PUBLIC_BUCKET_NAME=aws_bucket_name
      - AWS_REGION=eu-west-1
      - POSTGRES_PASSWORD=root
      - POSTGRES_USERNAME=postgres
      - POSTGRES_DATABASE=static-db
      - POSTGRES_PORT=27192
      - SENTRY_DSN=https://sentry-url-here
      - RSA_PUBLIC_KEY_PATH=/app/key/publicKey.pem
    volumes:
      - ./upload.config.json:/app/upload.config.json # file wit upload templates
      - ${RSA_PUBLIC_KEY}:/app/key/publicKey.pem #public key for jwt strategy
    depends_on:
      - rabbitmq
      - postgres
    ports:
      - "127.0.0.1:27196:3003"

volumes:
  postgres_data:

```

## Configuration Environment Variables

| Name                       | Description                                                    | Example                                 |Default                            |
|----------------------------|----------------------------------------------------------------|-----------------------------------------|-----------------------------------|
| STATIC_SERVICE_PORT        | Specify which port to use                                      | 3002                                    |3003                               |
| STATIC_SERVICE_QUEUE       | Specify queue name for tasks                                   | `static_service`                        |`static_service`                   |
| CORS                       | Cross-Origin Resource Sharing                                  | `true`                                  |`true`                             |
| AMQP_HOST                  | Connection url to RabbitMQ                                     | `amqp://login:password@rabbitmq:5672`   |`amqp://guest:guest@localhost:5672`|
| AWS_ACCESS_KEY_ID          | Aws access key                                                 | `access`                                |                                   |
| AWS_SECRET_ACCESS_KEY      | Aws secret key                                                 | `secret`                                |                                   |
| AWS_PUBLIC_BUCKET_NAME     | Aws bucket name                                                | `Ab4rah121`                             |                                   |
| AWS_REGION                 | Aws region                                                     | `eu-west-1`                             |`eu-west-1`                        |
| POSTGRES_PASSWORD          | Postgres password                                              | `root`                                  |                                   |
| POSTGRES_USERNAME          | Postgres username                                              | `root`                                  |`postgres`                         |
| POSTGRES_DATABASE          | Database name to store files                                   | `project_db`                            |`file_db`                          |
| POSTGRES_PORT              | Postgres port                                                  | 27190                                   |5432                               |
| SENTRY_DSN                 | The Dsn used to connect to Sentry and identify the project     | `https://sentry`                        |                                   |
| RSA_PUBLIC_KEY_PATH        | The path to public key used for validate jwt token             | `/app/key/publicKey.pem`                |`/app/key/publicKey.pem`           |
| JWT_ALGORITHM              | Algorithm for token decryption                                 | `RS256`                                 |`/app/key/publicKey.pem`           |

### Adding `FileEntity` to your typeorm configs.

**1. Install npm package**

```bash
yarn add @pixelplex/static-service
```

**2. Import FileEntity and to your typeorm settings:

```typescript
import { FileEntity } from '@pixelplex/static-service';

```
Or Create it:

```typescript
import { Column, CreateDateColumn, Entity, PrimaryGeneratedColumn, UpdateDateColumn } from 'typeorm';

@Entity({ name: 'file' })
export class FileEntity {

  @PrimaryGeneratedColumn()
  id: number;

  @CreateDateColumn({ type: 'timestamptz' })
  createdAt: Date;

  @UpdateDateColumn({ type: 'timestamptz' })
  updatedAt: Date;

  @Column()
  originalName: string;

  @Column()
  path: string;

  @Column()
  type: string;

  @Column()
  size: number;

  @Column()
  key: string;

  @Column()
  hash: string;
}

```

**3. Import StaticModule** in your module:

```typescript
import { Module } from '@nestjs/common';
import { StaticModule } from '@pixelplex/static-service';

@Module({
  controllers: [],
  imports: [StaticModule],
})
export class AppModule {}
```

**4. Import StaticService and call it:

```typescript
import { Injectable } from '@nestjs/common';
import { StaticService } from '@pixelplex/static-service';

@Injectable()
export class AppService {

  constructor(private staticService: StaticService) {}

  // Remove file and all related resized files
  async onModuleInit() {
    this.staticService.deleteFile(2);
  }

}
```

**5. Connect front end to static service via STATIC_SERVICE_PORT

**6. Call api `/static/v1/files/{template-name}` with body: { file: file_buffer }
