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 %}