diff --git a/Pipfile b/Pipfile index 6105f90..99dc60e 100644 --- a/Pipfile +++ b/Pipfile @@ -3,6 +3,10 @@ url = "https://pypi.python.org/simple" verify_ssl = true name = "pypi" +[scripts] +serve = "python -m whois" +"init-db" = "python helpers/db_create.py" + [dev-packages] pytest = "*" freezegun = "*" @@ -15,6 +19,7 @@ Flask = "*" Flask-Login = "*" python-dateutil = "*" peewee = "*" +apscheduler = "*" [requires] python_version = "3.6" diff --git a/Pipfile.lock b/Pipfile.lock index f3d2523..9412396 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "7784c994e5edbd1576b5dba219cd76f598760d11610144388a98cd57fb32c1e4" + "sha256": "9ce968b2a2111903ed0b374792e4e9c2e629d32c99d71d0cabde6e3e708c4934" }, "pipfile-spec": 6, "requires": { @@ -16,6 +16,14 @@ ] }, "default": { + "apscheduler": { + "hashes": [ + "sha256:443d015339ceca347f9ed14a66e9b610f99f19f8ef9048aa1cdabee2560824e1", + "sha256:952c8f46a11f32b9d5bfbe3e347dac2cdf0680d8b4799590dc9c3a9865b73b65" + ], + "index": "pypi", + "version": "==3.5.1" + }, "click": { "hashes": [ "sha256:29f99fc6125fbc931b758dc053b3114e55c77a6e4c6c3a2674a2dc986016381d", @@ -80,6 +88,13 @@ "index": "pypi", "version": "==2.7.3" }, + "pytz": { + "hashes": [ + "sha256:65ae0c8101309c45772196b21b74c46b2e5d11b6275c45d251b150d5da334555", + "sha256:c06425302f2cf668f1bba7a0a03f3c1d34d4ebeef2c72003da308b3947c7f749" + ], + "version": "==2018.4" + }, "six": { "hashes": [ "sha256:70e8a77beed4562e7f14fe23a786b54f6296e34344c23bc42f07b15018ff98e9", @@ -87,6 +102,12 @@ ], "version": "==1.11.0" }, + "tzlocal": { + "hashes": [ + "sha256:4ebeb848845ac898da6519b9b31879cf13b6626f7184c496037b818e238f2c4e" + ], + "version": "==1.5.1" + }, "werkzeug": { "hashes": [ "sha256:c3fd7a7d41976d9f44db327260e263132466836cef6f91512889ed60ad26557c", @@ -119,11 +140,11 @@ }, "black": { "hashes": [ - "sha256:3efe92eafbde15f8ac06478de11cfb84e47504896ccdde64507e751d2f91ec3a", - "sha256:fc26c4ab28c541fb824f59fa83d5702f75829495d5a1dee603b29bc4fbe79095" + "sha256:479cc8b3455a75b5b289276b5f47fd2bb412f2f369292989c12b891264758b5c", + "sha256:fe3b7ac846f2a7c91d926782184826c57d2be283c57f0d6b37b85496eb5469ff" ], "index": "pypi", - "version": "==18.6b2" + "version": "==18.6b3" }, "click": { "hashes": [ @@ -211,11 +232,11 @@ }, "pytest": { "hashes": [ - "sha256:26838b2bc58620e01675485491504c3aa7ee0faf335c37fcd5f8731ca4319591", - "sha256:32c49a69566aa7c333188149ad48b58ac11a426d5352ea3d8f6ce843f88199cb" + "sha256:8ea01fc4fcc8e1b1e305252b4bc80a1528019ab99fd3b88666c9dc38d754406c", + "sha256:90898786b3d0b880b47645bae7b51aa9bbf1e9d1e4510c2cfd15dd65c70ea0cd" ], "index": "pypi", - "version": "==3.6.1" + "version": "==3.6.2" }, "python-dateutil": { "hashes": [ diff --git a/README.md b/README.md index cabcf58..0a58fcc 100644 --- a/README.md +++ b/README.md @@ -9,25 +9,29 @@ - Dependencies -```bash +```shell pipenv install ``` - Create database -```bash +```shell pipenv run python helpers/db_create.py +# or +pipenv run init-db ``` ## Running -```bash +```shell pipenv run python -m whois +# or +pipenv run serve ``` ## Deployment -```bash +```shell docker-compose build # first run, later it should just connect to existing db docker-compose run web python3 helpers/db_create.py diff --git a/whois/database.py b/whois/database.py index 3f89e17..14e6fdc 100644 --- a/whois/database.py +++ b/whois/database.py @@ -124,3 +124,15 @@ def update_or_create(cls, mac_address, last_seen, hostname=None): res.last_seen = last_seen res.hostname = hostname res.save() + + +class History(pw.Model): + """History of user activity in HS""" + + datetime = pw.DateTimeField() + user_count = pw.IntegerField() + unknown_device_count = pw.IntegerField() + known_device_count = pw.IntegerField() + + class Meta: + database = db diff --git a/whois/history.py b/whois/history.py new file mode 100644 index 0000000..0cbe3cc --- /dev/null +++ b/whois/history.py @@ -0,0 +1,33 @@ +import logging +import atexit +from datetime import datetime + +from apscheduler.schedulers.background import BackgroundScheduler as Scheduler +from whois.settings import log_frequency_time +from whois.database import History, Device +from whois.helpers import owners_from_devices, filter_hidden, unclaimed_devices + +logger = logging.getLogger(__name__) + +logger.info("Created BackgroundScheduler") +cron = Scheduler(daemon=True) +cron.start() + + +@cron.scheduled_job(**log_frequency_time) +def log_presence(): + logger = logging.getLogger(__name__) + logger.info("logging presence to history") + + now = datetime.now() + recent = Device.get_recent(**log_frequency_time) + visible_devices = filter_hidden(recent) + uc = len(filter_hidden(owners_from_devices(visible_devices))) + udc = len(unclaimed_devices(visible_devices)) + ndc = len(visible_devices) - udc + History.create( + datetime=now, user_count=uc, unknown_device_count=udc, known_device_count=ndc + ) + + +atexit.register(lambda: cron.shutdown(wait=False)) diff --git a/whois/settings.py b/whois/settings.py index bcb4d07..e9c16d3 100644 --- a/whois/settings.py +++ b/whois/settings.py @@ -6,6 +6,7 @@ device_flags = {1: "hidden", 2: "new", 4: "infrastructure", 8: "esp", 16: "laptop"} recent_time = {"minutes": 20} +log_frequency_time = {"hours": 1, "minutes": 0, "seconds": 0} # production ip_mask = "192.168.88.1-255" diff --git a/whois/static/favicon.ico b/whois/static/favicon.ico new file mode 100644 index 0000000..7306ce6 Binary files /dev/null and b/whois/static/favicon.ico differ diff --git a/whois/templates/base.html b/whois/templates/base.html index fc60e81..7b2ac43 100644 --- a/whois/templates/base.html +++ b/whois/templates/base.html @@ -15,6 +15,7 @@ + @@ -31,12 +32,12 @@ {% block header %}