Add script to push card data to auth server

This commit is contained in:
Tanner Collin 2018-12-04 01:05:17 -07:00
parent d8ec4b30c8
commit a619c3fe39
5 changed files with 260 additions and 0 deletions

113
doorcontrol/.gitignore vendored Normal file
View File

@ -0,0 +1,113 @@
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
*.egg-info/
.installed.cfg
*.egg
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
.hypothesis/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
target/
# Jupyter Notebook
.ipynb_checkpoints
# pyenv
.python-version
# celery beat schedule file
celerybeat-schedule
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
# Editor
*.swp
*.swo
# DB
db.sqlite3
migrations/
# media
media/*
# Custom
settings.json

85
doorcontrol/README.md Normal file
View File

@ -0,0 +1,85 @@
# Protospace lockout card updater
Runs on the door controller and updates the auth server with member cards.
## Setup
### Cloning
Clone to user `pi`'s home directory. If you'd like to place it elsewhere, adjust the supervisor config below.
```
$ cd
$ git clone https://gogs.tannercollin.com/tanner/pslockout
```
### Python
```
$ sudo apt install python3 python3-pip python3-virtualenv # for Debian
$ cd ~pi/pslockout/doorcontrol
$ virtualenv -p python3 env
$ . env/bin/activate
(env) $ pip install -r requirements.txt
(env) $ deactivate
```
### Supervisor
Supervisor is used to keep the script always running.
```
$ sudo apt install supervisor
```
Create a file named /etc/supervisor/conf.d/pushcards.conf and add:
```
[program:pushcards]
user=pi
directory=/home/pi/pslockout/doorcontrol
command=source env/bin/activate && python pushcards.py
autostart=true
autorestart=true
stderr_logfile=/var/log/pushcards.log
stderr_logfile_maxbytes=1MB
stdout_logfile=/var/log/pushcards.log
stdout_logfile_maxbytes=1MB
```
### settings.json
Copy the example and insert a lockout admin's auth token:
```
$ cd ~pi/pslockout/doorcontrol
$ cp settings.json.example settings.json
$ vim settings.json
```
You can find your auth token by requsting with `curl`:
```
$ curl -d username=tanner.collin -d password=supersecret http://tools-auth.protospace.ca/login/
{
"token": "9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b"
}
```
### Launch
Reload supervisor and start pushcards:
```
$ sudo supervisorctl reread
$ sudo supervisorctl update
```
## Theory of Operation
Every ten seconds the script checks to see if the card database has changed.
If it was modified, it reads the card numbers into a Python object.
It then sends the object (modified or not) to the auth server which updates the cards for any users found in the system.

54
doorcontrol/pushcards.py Normal file
View File

@ -0,0 +1,54 @@
import logging
logging.basicConfig(
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
level=logging.ERROR)
import json
import os
import requests
import sqlite3
import time
CARD_DB_PATH = '/home/pi/production.sqlite3'
CARD_PUSH_DELAY = 10
CARD_UPDATE_URL = 'https://tools-auth.protospace.ca/update-cards/'
settings = json.load(open('settings.json'))
request_headers = {'Authorization': 'Token ' + settings['token']}
last_modified_time = None
card_data = {}
while True:
try:
modified_time = os.path.getmtime(CARD_DB_PATH)
logging.info('modified_time: {}, last_modified_time: {}'.format(modified_time, last_modified_time))
if modified_time != last_modified_time:
logging.info('Card database modified time is different, reading database...')
conn = sqlite3.connect('file:' + CARD_DB_PATH + '?mode=ro', uri=True)
c = conn.cursor()
for row in c.execute('select owner, group_concat(serial) from cards where active=1 group by owner'):
username = row[0].replace(' ', '.').lower()
logging.info('Read name: {}, username: {}, cards: {}'.format(row[0], username, row[1]))
card_data[username] = row[1]
conn.close()
last_modified_time = modified_time
logging.info('Uploading card data to server...')
r = requests.put(CARD_UPDATE_URL, headers=request_headers, data=card_data)
if r.status_code == requests.codes.ok:
logging.info('Number of cards updated: {}'.format(r.json()['updated']))
else:
r.raise_for_status()
except BaseException as e:
logging.error(e)
time.sleep(CARD_PUSH_DELAY)

View File

@ -0,0 +1,5 @@
certifi==2018.11.29
chardet==3.0.4
idna==2.7
requests==2.20.1
urllib3==1.24.1

View File

@ -0,0 +1,3 @@
{
"token": "9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b"
}