Skip to content

Commit

Permalink
Merge pull request #15 from anomaly/dto-implementation
Browse files Browse the repository at this point in the history
Major DTO implementation
  • Loading branch information
devraj authored Mar 27, 2024
2 parents 4d167af + de4cc97 commit a38dcc3
Show file tree
Hide file tree
Showing 154 changed files with 4,209 additions and 970 deletions.
38 changes: 38 additions & 0 deletions .github/ISSUE_TEMPLATE/bug_report.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
assignees: ''

---

**Describe the bug**
A clear and concise description of what the bug is.

**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error

**Expected behavior**
A clear and concise description of what you expected to happen.

**Screenshots**
If applicable, add screenshots to help explain your problem.

**Desktop (please complete the following information):**
- OS: [e.g. iOS]
- Browser [e.g. chrome, safari]
- Version [e.g. 22]

**Smartphone (please complete the following information):**
- Device: [e.g. iPhone6]
- OS: [e.g. iOS8.1]
- Browser [e.g. stock browser, safari]
- Version [e.g. 22]

**Additional context**
Add any other context about the problem here.
20 changes: 20 additions & 0 deletions .github/ISSUE_TEMPLATE/feature_request.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: ''
assignees: ''

---

**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]

**Describe the solution you'd like**
A clear and concise description of what you want to happen.

**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.

**Additional context**
Add any other context or screenshots about the feature request here.
33 changes: 33 additions & 0 deletions .github/workflows/run-tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
name: Testing
on:
push:
branches:
- master
pull_request:
branches:
- master

jobs:
test:
runs-on: ubuntu-latest

steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Python
uses: actions/setup-python@v4
with:
python-version-file: pyproject.toml
- name: Install Task
uses: arduino/setup-task@v1
with:
version: 3.x
repo-token: ${{ secrets.GITHUB_TOKEN }}
- name: Install dependencies
run: |
pip install poetry
poetry install
- name: Run tests
run: |
export GACC_API_KEY=${{ secrets.GACC_API_KEY }}
task test
15 changes: 6 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
> Currently under heavy development, please check for stable release before use
# Gallagher Python Toolkit

# Gallagher Command Centre REST API Client

> Python idiomatic client for Gallagher Command Centre API
> Python idiomatic REST API client, a command line interface and a text based console for Gallagher Command Centre API
Gallagher Security manufacture a variety of [security products](https://security.gallagher.com) all of which are controlled by their [Command Centre](https://products.security.gallagher.com/security/au/en_AU/products/software/command-centre/p/C201311) software. Traditionally Command Centre has been a Windows based server product. Version `8.6` introduced a REST API which allows you to interact with the system via HTTP requests. Gallagher also provide a [Cloud API Gateway](https://gallaghersecurity.github.io/docs/Command%20Centre%20Cloud%20Api%20Gateway%20TIP.pdf) which allows third party integrations to securely communicate with the Command Centre on site.

Expand All @@ -19,8 +17,7 @@ from gallagher import cc, const

cc.api_key = "GH_"

cc.discover()
cc.Customer.create()
cc.Customer.list()
```

> Note this project is **NOT** officially affiliated with Gallagher Security
Expand Down Expand Up @@ -131,7 +128,7 @@ We use [Taskfile](https://taskfile.dev) to automate running tasks.

The project provides a comprehensive set of tests which can be run with `task test`. These tests do create objects in the Command Centre, we advice you to obtain a test license.

**DO NOT** run the tests against a production system.
> It's **not recommended** to run tests against a production system.
### Data Transfer Objects

Expand All @@ -155,7 +152,7 @@ Resources are `fetchable`, `queryable`, `creatable`, `updatable` and `deletable`

Responses can be the object itself or a response layout

# Configuring the Command Centre
## Configuring the Command Centre

The following requires you to have an understanding of the Gallagher Command Centre and how to configure it. If you are unsure, please contact your Gallagher representative.

Expand Down Expand Up @@ -183,6 +180,6 @@ To check your API key:

![Command Centre Cloud Connections](assets/gallagher-rest-properties.png)

# License
## License

Distributed under the MIT License.
36 changes: 17 additions & 19 deletions TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,38 +2,37 @@

The following is tracking which endpoints are available along with their test cases

- [ ] Authentication
- [ ] Base API route design
- [x] Authentication
- [x] Base API route design

## Alarms, events, and non-cardholder items

- [ ] Alarm search
- [ ] Alarm updates
- [ ] Alarm summary
- [x] Alarm summary
- [ ] Alarm detail
- [ ] Alarm history entry
- [ ] Alarm update request
- [ ] Event search
- [ ] Event summary
- [x] Event summary
- [ ] Event detail
- [ ] Event POST body
- [ ] Event groups
- [ ] Divisions
- [ ] Division
- [x] Event groups
- [x] Divisions
- [x] Division
- [ ] Division PATCH and POST example
- [ ] Item search
- [X] Item summary
- [X] Item detail
- [X] Item types
- [x] Item summary
- [x] Item detail
- [x] Item types
- [ ] Item update
- [ ] Item update subscription


## Cardholders and related items

- [ ] Cardholder search
- [ ] Cardholder summary
- [ ] Cardholder detail
- [x] Cardholder summary
- [x] Cardholder detail
- [ ] Cardholder POST example
- [ ] Cardholder Update Location POST example
- [ ] Cardholder PATCH example
Expand Down Expand Up @@ -64,13 +63,13 @@ The following is tracking which endpoints are available along with their test ca
- [ ] Competency summary
- [ ] Competency detail
- [ ] Card type search
- [ ] Card type
- [x] Card type
- [ ] Operator group search
- [ ] Operator group summary
- [ ] Operator group detail
- [ ] Operator group membership
- [ ] PDF definition search
- [ ] PDF definition
- [x] PDF definition
- [ ] Reception search
- [ ] Reception
- [ ] Redaction
Expand All @@ -94,7 +93,7 @@ The following is tracking which endpoints are available along with their test ca
- [ ] Alarm Zone summary
- [ ] Alarm Zone detail
- [ ] Day category search
- [X] Day category
- [x] Day category
- [ ] Door search
- [ ] Door summary
- [ ] Door detail
Expand All @@ -117,17 +116,16 @@ The following is tracking which endpoints are available along with their test ca
- [ ] Output summary
- [ ] Output detail
- [ ] Schedule search
- [X] Schedule summary
- [x] Schedule summary
- [ ] Schedule detail
- [ ] Schedule POST and PATCH
- [ ] Override end time


## PIV cards

- [ ] PIV card GET
- [ ] PIV card type
- [ ] PIV card create example
- [ ] PIV card update example
- [ ] PIV card data
- [ ] CHUID
- [ ] CHUID
22 changes: 20 additions & 2 deletions Taskfile.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,28 @@ tasks:
cmds:
- poetry build
test:
desc: runs tests inside the server container
desc: runs tests inside the virtualenv
summary:
runs all the tests inside the virtualenv, optionally
provide the name of the test as an argument to run a single test
cmds:
- poetry run coverage run -m pytest -s
- poetry run coverage run -m pytest -s --tap tests/{{.CLI_ARGS}}
test:list:
desc: lists the available tests
summary:
runs collect only on pytest to list the tests available
cmds:
- poetry run pytest --co
test:coverreport:
desc: runs coverage inside the server container
cmds:
- poetry run coverage report -m
dev:textual:
desc: runs the textual cli
cmds:
- poetry run textual --
dev:gcon:
desc: runs text gallagher console in dev mode
cmds:
- poetry run textual run --dev gallagher.console:main

47 changes: 47 additions & 0 deletions docs/docs/cli.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# Command Line Interface

We provide a command line interface to interact with the Gallagher Command Centre. It uses the API client to communicate with the server, which doubly serves as a reference example of how to use the API client.

> We use [typer](https://typer.tiangolo.com) to construct the CLI, which in turn uses [click](https://click.palletsprojects.com). We also use [rich](https://rich.readthedocs.io/en/stable/) to make the output nicer. The CLI is decoupled from the API client, and is not install by default.
We follow a `git` like `command`, `sub-command` pattern, so it should feel quite familiar.

poetry will install the alias `gal` for you to interact with the CLI. You can ask for help with:

```
gal --help
```

which will list the available commands:

```
Usage: gal [OPTIONS] COMMAND [ARGS]...
╭─ Options ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ --install-completion Install completion for the current shell. │
│ --show-completion Show completion for the current shell, to copy it or customize the installation. │
│ --help Show this message and exit. │
╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
╭─ Commands ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ alarms list or query alarms in the command centre │
│ ch query or manage cardholders │
│ events query command centre events │
╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
```

A simple example to get a list of cardholders looks like:

```
(gallagher-py3.11) ➜ gallagher git:(dto-implementation) ✗ gal ch list
Cardholders
┏━━━━━━┳━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┳━━━━━━━━━━━━┓
┃ Id ┃ First name ┃ Last name ┃ Authorised ┃
┡━━━━━━╇━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━╇━━━━━━━━━━━━┩
│ 8246 │ Johnetta │ Abdallah │ yes │
│ 7936 │ Socorro │ Abrahams │ yes │
│ 8374 │ Geoffrey │ Acey │ yes │
│ 8370 │ Weldon │ Acuff │ yes │
│ 7922 │ Rusty │ Adelsperger │ yes │
```

you can also ask each sub command to give you in
58 changes: 58 additions & 0 deletions docs/docs/design.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# Design

A central feature to this client is it's detailed design, focused on a superior developer experience and performance. We also ensure that we follow design patterns outlined by Gallagher

## Data Transfer Objects

This a central part of our design. There are three types of schema definitions, each one of them suffixed with their intent:

- **Ref** are `References` to other objects, they using contain a `href` and possibly additional meta data such as a `name` or `id`
- **Summary** is what is returned by the Gallagher API in operations such as [searches](https://gallaghersecurity.github.io/cc-rest-docs/ref/cardholders.html), these are generally a subset of the full object
- **Detail** are the full object found at a particular `href`, they compound on the `Summary` schema and add additional attributes

I additional we have classes that defined responses which are suffixed with **Response**, these wrap structures which returns `hrefs` for `next` and `previous` responses and usually have a collection to hold the response.

Ensure that each Endpoint defines their own DTOs so you can test them for authenticity. Avoid writing generic classes.

While `Refs`, `Summary` and `Detail` responses have fields, and it would make sense from an efficiency point of view to inherit e.g `Summary` builds on `Ref`, this should be avoided so logically an instance of a `Ref` class doesn't assert true for `isinstance` of a `Summary` class.

## API Client Core

The `core` package in `cc` provides two important classes:

- `APIEndpoint` which all endpoint consumers configuration must inherit from
- `EndpointConfig` an instance of which each class must return as a result of the `get_config` method

Every Endpoint Consumer Class is expected to return an instance of `EndpointConfig` from the `get_config` method. Each configuration provides references to paths that are dynamically discovered as part of our bootstrapping process.

Never hard code URLs as this violates the [HATEOAS](https://en.wikipedia.org/wiki/HATEOAS) design principle.

Additionally each configuration will provide references to DTO classes that is used to parse responses, and details of the body.

```
class Alarms(
APIEndpoint
):
""" Alarms
"""
@classmethod
async def get_config(cls) -> EndpointConfig:
return EndpointConfig(
endpoint=Capabilities.CURRENT.features.alarms.alarms,
dto_list=AlarmResponse,
dto_retrieve=AlarmZoneSummary,
)
```

The above example shows the `Alarms` class which is a consumer of the `alarms` endpoint. It nominates `AlarmResponse` as the class the infrastructure will use to parse `list` responses and `AlarmZoneSummary` as the class to parse `retrieve` responses.

It references the `Capabilities.CURRENT` singleton which is a `Capabilities` instance that is bootstrapped at runtime. This is a singleton that is used to provide references to all endpoints.

If a command centre does not have a certain capability then the objects are set to `None` and accessing the feature raises an exception (more on this in other sections).

### Designing Endpoints

## Layout

Layout of our files
Loading

0 comments on commit a38dcc3

Please sign in to comment.