# Audit Logger Adapter

Adapter for sending audit logs to ElasticSearch.

## Installation

Installation happens via our PyPi server:

```shell
pip install -i https://pypi.theorchard.io/pypi/ auditlogger
```

## Development

Create an environment and install the dependencies:

```shell
make env
```

Run the linter and tests:

```shell
make lint
make test
```

Be sure to publish the latest version of this package to Pypi when contributing.
This [Jenkins job](http://jenkins.theorchard.com:8080/view/pypi/job/publish-pypi-package/) will bump the version, tag and publish the package to Pypi.

## Requirements
- Store event logs to accurately represent actions taken against accounting objects
- Retain entries for up to 10 years (or as defined by auditor requirements)
- Data & metadata based search

## Backend
- The log system will be backed by elasticsearch and Kibana.
- The elasticsearch cluster will handle the scale of the logging taking place, with multiple endpoint nodes to reduce service downtime.
- As the log size increases over time, records can be exported to AWS Glacier for long-term storage.
- The Kibana interface will be used to search through entries.

## Metadata

> Generic event data that applies to all entries.

| Field Name  | Type   | Notes
|---|---|---|
| target_type | string | the object that was operated on.  Object types TBD
| target_id   | string | Id of the target object
| event_name  | string | action taken.  Each object has a group of action types.  For example, Payee:create, or Proceeds:apply_fee
| timestamp | string | format: yyyyMMdd'T'HHmmss.SSSZ  see [elastic date formatting](https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-date-format.html#built-in-date-formats)
| user_type | string | do we need to segment user types??
| user_id  | string | unique identifier of the user

## Indices

> Elasticsearch indexes define the top level sharding. We use these to organize entries in logical groups.

|Index Name|Notes
|---|---|
|royalty-accounting|Covers general monthly royalty calculations, payment generations, etc.
user-action|Approval process events, OA actions not centered around object CRUD
system-event|Automated events, such as cron-based updates
record-event|Object CRUD events

## Accounting Objects

- advance_payment
- advance_recoupment
- contract
- currency
- exchange_rate
- payee
- payment
- run
- statement
- store
- territory
- transaction
- transaction_type

## Basic Usage
```python
from auditlogger.logger import AuditLogger
from auditlogger.record_event import RecordEvent

# Create the logger
auditlogger = AuditLogger(
    [
        {'host': config.AUDIT_LOG_ES_ENDPOINT, 'port': 443}
    ]
)

# Sample data
payee_data = {
    'payee_id': 1,
    'payee_name': 'Bob',
    'payee_type': 'vendor'
}

# Log creation
new_payee = payee.create_payee(**payee_data)
changeset = {
    'original': None,
    'updated': payee_data
}
auditlogger.log(RecordEvent('payee', new_payee.id, 'create', changeset, user_type, user_id))

# Log update
new_payee.payee_name = 'Ben'
changeset = {
    'original': { 'payee_name': payee_data.payee_name },
    'updated': { 'payee_name': new_payee.payee_name }
}
auditlogger.log(RecordEvent('payee', new_payee.id, 'update', changeset, user_type, user_id))

# Log delete
payee.delete_payee(new_payee.id)
changeset = {
    'original': { 'id': new_payee.id },
    'updated': { 'id': None }
}
auditlogger.log(RecordEvent('payee', new_payee.id, 'delete', changeset, user_type, user_id))
```

If you specify no hosts the logger will output the logs instead:

```python
auditlogger = AuditLogger(None)
auditlogger.log(record_event) # Outputs to console
```
