# ARK (Archival Resource Key) Server
<!-- TOC -->
- [ARK (Archival Resource Key) Server](#ark-archival-resource-key-server)
- [Goal](#goal)
- [Dependencies](#dependencies)
- [Install](#install)
- [Command-line tools](#command-line-tools)
- [Install (or re-install)](#install-or-re-install)
- [Start web server](#start-web-server)
- [Run tests](#run-tests)
- [Add API account](#add-api-account)
- [CSV import](#csv-import)
- [Production deploy](#production-deploy)
- [Basic Resolver](#basic-resolver)
- [ReSTish API](#restish-api)
- [Read](#read)
- [Create](#create)
- [Update](#update)
- [API errors](#api-errors)
- [Batch mode](#batch-mode)
<!-- /TOC -->
## Goal
The goal of this software is to offer a solution for a Name Assigning Authority to distribute Archival Resources Keys and maintain basic information about the resources. It offers a database, command-line tools and an HTTP API.
## Dependencies
- Python 3.6+ (async/await, secrets)
- PostgreSQL 9.4+ (jsonb)
## Install
Create a virtualenv and activate it:
```
make venv
. ./venv/bin/activate
```
Create a database and then override default env vars (or copy the .env.dist file to .env and change settings):
```
export ARK_SERVER_PGSQL_HOST=[pg_hostname]
```
```
export ARK_SERVER_PGSQL_USER=[pg_user]
```
```
export ARK_SERVER_PGSQL_PASSWORD=[pg_password]
```
```
export ARK_SERVER_DEBUG=0 # don't set to 1 in production
```
```
export ARK_SERVER_WORKERS=4 # as much as available cpu cores
```
Install Ark server:
```
make install
```
Create tables:
```
ark install
```
## Command-line tools
All command-line tools support ```-h``` flag for help.
### Install (or re-install)
This command initializes the database.
**Warning !** This will wipe all data in your ARK database.
```
ark install
```
### Start web server
```
ark run-server
```
### Run tests
(Start web server first !)
```
pytest -vv tests.py
```
### Add API account
```
ark make-api-access
```
Would generate the following output:
```
Access granted to untitled app
id : 3
secret: @-lQ,x}aZIT%Q}X&Dg!){zeq`pN:TOPt
```
Use ```ark make-api-access -h``` for help.
### CSV import
For mass-creation or update of ARK names. Must have columns app_id, ark_location, ark_name (empty value for creation). Any other column will be treated as meta:
```
ark csv-import /path/to/some/file.csv
```
A csv file is generated at /path/to/some/file-out.csv with added ARK names for creations.
## Basic Resolver
```https://yourhost.tld/ark:[your NAAN]/[ARK id]``` will redirect you to the location available in the db.
## ReSTish API
- An endpoint is available at http://whatever-your-host-is.tld/api/v1/
- Available HTTP verbs are GET, POST, PUT to respectively read, create or update ARKs to the database
- JSON body is used for POST and PUT
For POST and PUT, an Authorization HTTP header must contain a hmac256 of the request body, signed with your secret key (see [Add API account](#add-api-account) to generate your key). Example:
```
Authorization:16ac7bd2c03200935d72c3acbaaaf637afc7ba417d0bf6a4429379634268ecda
```
POST and PUT requests must also include the current Unix Epoch and the app_id.
### Read
```
GET /api/v1/?ark=[NAAN]/[ARK_ID]
```
If ARK exists, will return a response with a JSON body such as this:
```
{
"ark_location": "http://somewhere.tld/some-resource/",
"ark_metas":
{
"who": "someone",
"what": "something",
"where": "somewhere"
}
}
```
### Create
```
POST /api/v1/
```
With such JSON body:
```
{
"app_id": 1,
"timestamp": 1530798110,
"ark_location": "http://somewhere.tld/some-resource/",
"ark_metas":
{
"who": "someone",
"what": "something",
"where": "somewhere"
}
}
```
A status code 200 is returned with a response body containing the ARK name. Example:
```
44804/MGQP4QLZ
```
### Update
```
PUT /api/v1/
```
With such JSON body:
```
{
"app_id": 1,
"timestamp": 1530798110,
"ark_name": "44804/MGQP4QLZ"
"ark_location": "http://somewhere.tld/some-resource/",
"ark_metas":
{
"who": "someone",
"what": "something",
"where": "somewhere"
}
}
```
A status code 200 is returned.
### API errors
Appropriate HTTP status codes are used (500, 400, 403, etc). Treat anything other than 200 as an error.
### Batch mode
An additional POST endpoint at ```/api/v1/batch/``` supports batch requests with mixed create, read or update. JSON document payload looks like this:
```
{
"app_id": 1,
"timestamp": 1530798110,
"items":[
["r", "44408/TJX", null, null],
["c", null, "http://somewhere.tld/some-resource/", {
"who": "someone",
"what": "something",
"where": "somewhere"}],
["u", "44408/JBN", "http://somewhere.tld/some-resource/", {
"who": "someone",
"what": "something",
"where": "somewhere"}]
]
}
```
Each items is an array with the following informations: [crud_operation, ark_name, ark_location, ark_metas].
Letters "r", "c", "u" are used to explicitely indicate a read, a create or an update on the item. Unknown parameters are set to null.
The JSON payload MUST be gzip-encoded in the request body. As usual, the request MUST contain an authorization header signin the request body.
A (gzipped) response is sent with the completed items:
```
[
["r", "44408/TJX", "http://somewhere.tld/more-resource/", {
"who": "someone",
"what": "something",
"where": "somewhere"}],
["c", "44408/FC2S", "http://somewhere.tld/some-resource/", {
"who": "someone",
"what": "something",
"where": "somewhere"}],
["u", "44408/JBN", "http://somewhere.tld/some-resource/", {
"who": "someone",
"what": "something",
"where": "somewhere"}]
]
```