Metadata-Version: 2.4
Name: checkscanner
Version: 0.1.18
Summary: Check scanner API server and admin console
Home-page: https://bitbucket.org/disciplemakers/check-reader
Author: DiscipleMakers
License: MIT
Keywords: check scanner,micr,magtek,rdm
Classifier: Programming Language :: Python :: 3
Classifier: Operating System :: OS Independent
Classifier: Framework :: Bottle
Classifier: Topic :: Office/Business :: Financial
Requires-Python: <3.13,>=3.6
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: gevent<22.0.0,>=1.5.0; python_version < "3.7"
Requires-Dist: gevent>=23.0.0; python_version >= "3.7"
Requires-Dist: Pillow<9.0.0,>=5.0.0; python_version < "3.7"
Requires-Dist: Pillow<10.0.0,>=9.5.0; python_version == "3.7"
Requires-Dist: Pillow>=10.3.0; python_version >= "3.8"
Requires-Dist: pyftpdlib<2.0.0,>=1.5.0; python_version < "3.7"
Requires-Dist: pyftpdlib>=1.5.7; python_version >= "3.7"
Requires-Dist: PyJWT<2.5.0,>=2.0.0; python_version < "3.7"
Requires-Dist: PyJWT>=2.8.0; python_version >= "3.7"
Requires-Dist: requests<2.28.0,>=2.20.0; python_version < "3.7"
Requires-Dist: requests>=2.31.0; python_version >= "3.7"
Requires-Dist: toml>=0.10.0
Requires-Dist: click<8.1,>=7.1; python_version < "3.7"
Requires-Dist: click>=8.1; python_version >= "3.7"
Requires-Dist: rich<13.0,>=12.0; python_version < "3.7"
Requires-Dist: rich>=13.0; python_version >= "3.7"
Requires-Dist: questionary<2.0,>=1.10.0; python_version < "3.8"
Requires-Dist: questionary>=2.0; python_version >= "3.8"
Provides-Extra: test
Requires-Dist: pytest<7.1,>=6.2; python_version < "3.7" and extra == "test"
Requires-Dist: pytest>=7.0; python_version >= "3.7" and extra == "test"
Dynamic: license-file

# checkscanner

Check scanner server for Magtek and RDM check readers. It connects to the devices, extracts MICR data and check images, and serves them through a web interface and a JWT-authenticated REST API.

## Requirements

- Python 3.6+
- pip 21.3.1+ (required on Python 3.6 to resolve pre-built wheels)
- [GNU screen](https://www.gnu.org/software/screen/) (optional, for `checkscanner screen`)

## Installation

Update pip, then install the package:

```bash
pip install --upgrade pip
pip install checkscanner
```

To upgrade an existing install:

```bash
pip install --upgrade checkscanner
```

## Setup

```bash
checkscanner setup        # add -i to edit the config interactively first
```

Setup creates anything that is missing in the [server directory](#server-directory), and prints where that is:

| File | Description |
|---|---|
| `config/config.toml` | Server host, port, debug mode, optional log file |
| `config/auth.toml` | JWT signing key; optional FTP credentials for Magtek readers |
| `server.db` | SQLite database |
| `admin_credentials.txt` | Generated admin username and password — delete after noting |

Setup also runs automatically before the server and admin console start.

### Server directory

Config, the database and logs live in one server directory. It belongs to the install rather than to a user or the current folder, so `checkscanner` finds the same server from anywhere. Each command uses the first of:

1. `-d PATH` / `--dir PATH`, for one command (`checkscanner --dir . status` uses the current folder)
2. the `CHECKSCANNER_DIR` environment variable
3. the directory saved with `checkscanner dir PATH`
4. the default for how the package was installed:

| How it's installed | Default server directory | `checkscanner dir` saves to |
|---|---|---|
| venv (e.g. `/opt/checkscanner/.venv`) | the folder holding the venv (`/opt/checkscanner`) | `<venv>/etc/checkscanner.toml` |
| `pip install --user`, or `pip install` as a non-root user | `~/.local/share/checkscanner` | `~/.local/etc/checkscanner.toml` |
| pipx | `~/.local/share/checkscanner` | `~/.local/etc/checkscanner.toml` |
| global (`sudo pip install`) | `/var/lib/checkscanner` | `/etc/checkscanner.toml` |

The venv default keeps data next to the venv rather than inside it, so recreating the venv keeps the database.

**Sharing a server between users.** Members of the `checkscanner` group can all manage a shared server directory without sudo. Files they create stay writable by the group (umask 007), and other users can't open the folder.

- **Global install:** always shared. Run setup once as root with the full path, since sudo's `secure_path` leaves out `/usr/local/bin` on RHEL/Rocky: `sudo /usr/local/bin/checkscanner setup`. It creates the group and shares `/var/lib/checkscanner` (setgid, so new files join the group).
- **User install, pipx or venv:** opt in with `checkscanner setup --shared`. The folder must be one other users can reach, so not in your home folder. Root makes the group and folder once: `sudo groupadd --system checkscanner`, `sudo mkdir /srv/checkscanner`, `sudo chown $USER:checkscanner /srv/checkscanner`. Then run `checkscanner dir /srv/checkscanner` and `checkscanner setup --shared`. Each other admin installs checkscanner and runs `checkscanner dir /srv/checkscanner`. Keep everyone on the same version.

Add each admin with `sudo usermod -aG checkscanner USER`; they need to log in again. If permissions get out of step (e.g. a server set up with 0.1.12 or earlier), run setup again as root, or as the owner of the files.

Versions 0.1.10 and earlier used the current directory. If the default directory has no server yet but the current folder does, commands stop and ask you to run `checkscanner dir .` (or pass `--dir`), so an existing server is never replaced by a new empty one.

## Usage

Start the server, then open the web interface at `http://localhost:8000/`:

```bash
checkscanner
```

Server options can be passed directly, e.g. `checkscanner --port 9000`. Run `checkscanner server --help` for the full list.

Warnings and errors go to the console. Add `--debug` (or `debug = true` in `config.toml`) to see everything. Setup turns on a log file at `logs/checkscanner.log`, which gets info and above (everything with debug). Change or remove `log_file` in `config.toml`, or pass `--log-file`; the file rotates at 5 MB and keeps 5 old copies. To read the log file from the web interface, set `ui_logs = true` in `config.toml` or turn on "Allow viewing logs in the web UI" on the Settings page (off by default); admins then get a Logs page.

Magtek readers upload check images over FTP. The FTP server only starts when a Magtek reader connects, and its settings are optional: without `ftp_user`/`ftp_pass` in `auth.toml` it uses `check-reader` and a random password, which is sent to the reader on connect.

Open the interactive admin console:

```bash
checkscanner-cli
```

The admin console is an arrow-key menu for viewing server status, managing users and scanner profiles, editing config, regenerating auth keys, getting a bearer token, and starting the server (optionally restarting it when it stops).

### Commands

Every admin console action is also available as a `checkscanner` subcommand. See the [command reference](#command-reference) below, or run `checkscanner --help` and `checkscanner <command> --help`.

### Running in screen

To keep the server running after you log out, start it in a detached GNU screen session:

```bash
checkscanner screen                     # Start a session named "checkscanner"
checkscanner screen front --port 9000   # Start a session named "front" with server options
checkscanner screen ls                  # List running sessions, their state and directory
checkscanner screen logs front [-n 100] # Show recent output without attaching
checkscanner screen attach front        # Attach (detach again with Ctrl+A D)
checkscanner screen restart front       # Restart with the same options and directory
checkscanner screen stop front          # Stop a session (--all stops every session)
```

The session name defaults to `checkscanner` for every subcommand. Sessions show as `checkscanner-<name>` in `screen -ls`.

### Scanning checks

1. Log in to the web interface with the admin credentials from `admin_credentials.txt`.
2. Add a scanner profile (web interface or `checkscanner profile add`) with the device's host and type.
3. Connect to the scanner and scan checks. Only one user can be connected to a given scanner at a time.

Supported devices:

| Type | Protocol |
|---|---|
| Magtek | Telnet + FTP |
| RDM | HTTPS (XML) |

### API

Swagger UI is available at `http://localhost:8000/docs` while the server is running. Authenticate with `POST /token` (or `checkscanner token <username>`) and send the returned JWT as `Authorization: Bearer <token>`.

## Command reference

Commands work from any folder; see [Server directory](#server-directory). `-h`/`--help` works everywhere.

```
checkscanner [-V | --version] [-h | --help] [-d | --dir PATH] [COMMAND] [ARGS]...
checkscanner-cli
```

| Command | Description |
|---|---|
| `checkscanner` | With no command, run setup for anything missing, then start the server |
| `checkscanner [SERVER OPTIONS]` | Same as `checkscanner server [SERVER OPTIONS]` |
| `checkscanner-cli` | Same as `checkscanner admin`; takes no arguments |
| `-V`, `--version` | Print the version and exit |
| `-d`, `--dir PATH` | Server directory for this command (`.` for the current folder). Also works with `checkscanner-cli` |

### `checkscanner server [SERVER OPTIONS]`

Start the API server in the foreground. Setup runs first. The options override `config/config.toml` and `config/auth.toml` for this run only, unless `--save` is given.

| Option | Setting | Description |
|---|---|---|
| `-c`, `--clear-connections` | | Clear the connections table before starting |
| `--port PORT` | `port` | Port to listen on (local mode only) |
| `--host HOST` | `host` | Address to bind to (local mode only) |
| `--debug` / `--no-debug` | `debug` | Log everything / log warnings to the console and info to the log file |
| `--ui` / `--no-ui` | `ui` | Serve the web UI / API only (frontend URLs return 404; the API and `/docs` stay up) |
| `--serve-static` / `--no-serve-static` | `serve_static` | Serve the bundled frontend / proxy it to the Nuxt dev server at `localhost:3000` |
| `--log-file PATH` | `log_file` | Also write logs to this file, rotated at 5 MB with 5 old copies |
| `--jwt-key KEY` | `jwt_key` | JWT signing key. Changing it invalidates issued tokens |
| `--ftp-bind-host HOST` | `ftp_bind_host` | Address the Magtek FTP server binds to (default `0.0.0.0`) |
| `--ftp-user USER` | `ftp_user` | Magtek FTP username (default `check-reader`) |
| `--ftp-pass PASS` | `ftp_pass` | Magtek FTP password (default: random on each start) |
| `--save` | | Also write the options above to `config/config.toml` and `config/auth.toml` |

`jwt_key`, `ftp_user` and `ftp_pass` live in `auth.toml`; the rest live in `config.toml`.

You can turn `ui` off on the web Settings page, but after a restart that page won't load. Turn it back on with `checkscanner config`, `--ui --save`, or `PATCH /config`.

### `checkscanner setup [-i] [--shared]`

Create whatever is missing: `config/config.toml`, `config/auth.toml`, `server.db`, and an `admin` user with a random password saved to `admin_credentials.txt`. Existing files are left alone, so it is safe to run again.

| Option | Description |
|---|---|
| `-i`, `--interactive` | Walk through the config settings first |
| `--shared` | Let members of the `checkscanner` group manage this server too (see [Sharing a server between users](#server-directory)) |

### `checkscanner dir [PATH] [--unset]`

Show or save the server directory for this install.

| Usage | Description |
|---|---|
| `dir` | Show the directory in use, where it came from, and whether a server is set up there. Prints just the path when output is piped |
| `dir PATH` | Save `PATH` (an existing folder; `.` for the current one) as this install's server directory |
| `dir --unset` | Remove the saved directory and go back to the default |

On a global install the setting is in `/etc`, so saving it needs `sudo /usr/local/bin/checkscanner dir PATH`.

### `checkscanner status`

Show the server directory and where it came from, mode, URL, frontend, firewall warnings, debug setting, auth keys, and counts of users, profiles and active connections.

### `checkscanner admin`

Open the interactive admin console. Same as `checkscanner-cli`.

### `checkscanner token [USERNAME[:PASSWORD]]`

Print a bearer token for API testing. If the password is not given, you are prompted for it. When output is piped, only the token is printed:

```bash
curl -H "Authorization: Bearer $(checkscanner token admin:secret)" http://localhost:8000/profiles
```

| Option | Description |
|---|---|
| `-u`, `--username TEXT` | User to issue the token for |
| `-p`, `--password TEXT` | Password |

### `checkscanner user`

| Command | Description |
|---|---|
| `user list` | List users and their permissions |
| `user add USERNAME [--admin] [-p PASSWORD]` | Create a user. `--admin` gives admin permissions. The password is prompted for (twice) if `-p` is not given |
| `user passwd USERNAME [-p PASSWORD]` | Change a password. This also revokes the user's tokens |
| `user revoke USERNAME [-y]` | Revoke every token issued to the user. They must log in again |
| `user delete USERNAME [-y]` | Delete a user |

`-y`/`--yes` skips the confirmation prompt.

### `checkscanner profile`

| Command | Description |
|---|---|
| `profile list` | List scanner profiles and who is connected to each |
| `profile add [NAME] [--host HOST] [--type magtek\|rdm] [--ftp-host HOST]` | Create a profile, prompting for anything not given. `--host` is the scanner address, e.g. `192.168.1.20:443`. `--ftp-host` is the FTP host a Magtek reader uploads to |
| `profile delete NAME [-y]` | Delete a profile. `-y` skips the confirmation prompt |

### `checkscanner config`

| Command | Description |
|---|---|
| `config show` | Show the settings in `config/config.toml` |
| `config edit` | Edit `config/config.toml` interactively: logging, the web log viewer, local or WSGI mode, the frontend, host and port |
| `config rotate-keys [-y]` | Regenerate the JWT key, and the FTP password if one is set. Every issued token stops working. Restart the server to apply. `-y` skips the confirmation prompt |

### `checkscanner screen`

Run servers in detached GNU screen sessions (see [Running in screen](#running-in-screen)). `NAME` defaults to `checkscanner` everywhere. `checkscanner screen [NAME] [SERVER OPTIONS]` is short for `checkscanner screen start`.

| Command | Description |
|---|---|
| `screen start [NAME] [SERVER OPTIONS]` | Run setup in this terminal, then start the server in a detached session |
| `screen ls` | List running sessions with their state and directory |
| `screen attach [NAME]` | Attach to a session. Detach again with Ctrl+A D |
| `screen logs [NAME] [-n LINES]` | Show recent output without attaching. `-n`/`--lines` defaults to 50; `0` shows everything |
| `screen restart [NAME]` | Restart a session's server with the same options and directory |
| `screen stop [NAME]... [-a]` | Stop one or more sessions. `-a`/`--all` stops every session |

### `checkscanner build`

Source checkouts only. Runs `npm run generate` in `client/`, then copies `client/.output/public/` into the package's `static/` directory. See `DEVELOPMENT.md` in the [source repository](https://bitbucket.org/disciplemakers/check-reader) for the development setup.
