Skip to content

Feature/more prometheus metrics #265

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 28 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
1c1bcee
added GHA comment about PR on wrong branch
jabelone Apr 20, 2024
b3941ad
fix unhandled exception when logging access for non existent user
jabelone Apr 20, 2024
44737f0
updated logging with per app level configuration
jabelone Apr 23, 2024
2f54bf1
sync device if exempt_signin changes
jabelone Apr 23, 2024
b349f46
Increase Docker Python version to 3.12
jabelone May 23, 2024
1e1f2f7
Increase Docker Node version to 22
jabelone May 23, 2024
dc30244
Upgrade archaic Stripe npm version
jabelone May 23, 2024
4c52514
Add signal to automatically sync access changes in realtime
jabelone May 23, 2024
ab4419c
Added MemberbucksProduct and MemberbucksProductPurchaseLog
jabelone May 23, 2024
6bcc8fb
Updated AccessControlledDevice with supports credit/debit/purchase flags
jabelone May 23, 2024
a6984bd
Refactored credit websocket API to combined credit/debit websocket api
jabelone May 23, 2024
519b435
fixed devices list not showing door bump & manage button on mobile
jabelone May 24, 2024
1c9a07c
highlight offline devices with warning colour and disable bump
jabelone May 24, 2024
39faa77
fix bugs on device modal with weird next logic
jabelone May 24, 2024
b0b42c0
fixed typo in model
jabelone May 24, 2024
586e8d8
fixed door syncing signals
jabelone May 24, 2024
3232c81
added memberbucks devices to devices page
jabelone May 24, 2024
ae92046
added total purchases to memberbucks device list
jabelone May 24, 2024
07f4f1e
added memberbucks product log with external_id to credit/debit api
jabelone May 24, 2024
edcc707
show maintenance lockout on access permissions page
jabelone May 24, 2024
83a4a59
fixed memberbucks spacing
jabelone May 24, 2024
940eebe
removed old confusing signals
jabelone May 26, 2024
4153d8b
fixed weird device auth related bug
jabelone May 26, 2024
48fd09a
admin access page list shows warning about disabled state/locked out
jabelone May 26, 2024
d9fd92d
added prometheus metrics to all db models
jabelone May 28, 2024
98874e6
update gha
jabelone May 28, 2024
12e9fac
escaped backticks in gha comment
jabelone May 28, 2024
c42ea8a
update gha comment
jabelone May 28, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 49 additions & 0 deletions .github/workflows/comment_wrong_branch.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
name: Wrong Branch Warning

on:
workflow_dispatch:
pull_request:
types: [opened]
branches:
- "main"

jobs:
comment_warning:
if: ${{ github.event.pull_request.base.repo.clone_url != github.event.pull_request.head.repo.clone_url }}
runs-on: ubuntu-latest
steps:
- name: Comment warning about the wrong branch selected for PR
id: comment_docker_image
uses: actions/github-script@v6
with:
script: |
const output = `
Warning: we only accept PRs to the \`dev\` branch. It looks like you've created a PR to the \`main\` branch. Please edit this PR and select the \`dev\` branch as the target branch instead. If this was intentional please ignore this message.
`;

github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: output
})

comment_warning_internal_pr:
if: ${{ github.event.pull_request.head.ref != 'dev' }}
runs-on: ubuntu-latest
steps:
- name: Comment warning about the wrong branch selected for PR
id: comment_docker_image
uses: actions/github-script@v6
with:
script: |
const output = `
Warning: we only accept PRs to main from the \`dev\` branch. It looks like you've created a PR from a different branch. Please edit this PR and select the \`dev\` branch as the source branch instead. If this was intentional please ignore this message.
`;

github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: output
})
4 changes: 2 additions & 2 deletions docker/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Specify our base image
FROM python:3.10-bullseye
FROM python:3.12-bullseye
LABEL maintainer="Jaimyn Mayer ([email protected])"
LABEL description="Base Dockerfile for the MemberMatters software."

Expand All @@ -11,7 +11,7 @@ RUN mkdir -p /usr/src/app/frontend && mkdir /usr/src/logs && mkdir /usr/src/data
RUN apt-get update -y && apt-get install -y nginx curl daphne

# Install Node
ENV NODE_VERSION=18.16.0
ENV NODE_VERSION=22.2.0
SHELL ["/bin/bash", "--login", "-c"]

RUN curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.35.3/install.sh | bash
Expand Down
2 changes: 1 addition & 1 deletion memberportal/access/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@


@admin.register(AccessControlledDeviceAPIKey)
class AccessControlledDeviceAPIKey(APIKeyModelAdmin):
class AccessControlledDeviceAPIKeyAdmin(APIKeyModelAdmin):
pass


Expand Down
41 changes: 41 additions & 0 deletions memberportal/access/migrations/0016_auto_20240523_1550.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# Generated by Django 3.2.25 on 2024-05-23 05:50

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
("access", "0015_alter_accesscontrolleddevice_ip_address"),
]

operations = [
migrations.AlterModelOptions(
name="memberbucksdevice",
options={
"verbose_name": "Memberbucks Device",
"verbose_name_plural": "Memberbucks Devices",
},
),
migrations.AddField(
model_name="memberbucksdevice",
name="supports_credits",
field=models.BooleanField(
default=False, verbose_name="Supports the MM simple credits API."
),
),
migrations.AddField(
model_name="memberbucksdevice",
name="supports_debits",
field=models.BooleanField(
default=False, verbose_name="Supports the MM simple debits API."
),
),
migrations.AddField(
model_name="memberbucksdevice",
name="supports_products",
field=models.BooleanField(
default=False, verbose_name="Supports the mm products API."
),
),
]
42 changes: 42 additions & 0 deletions memberportal/access/migrations/0017_auto_20240523_1604.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# Generated by Django 3.2.25 on 2024-05-23 06:04

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
("access", "0016_auto_20240523_1550"),
]

operations = [
migrations.AlterField(
model_name="accesscontrolleddevice",
name="play_theme",
field=models.BooleanField(
default=False, verbose_name="Play theme on successful swipe"
),
),
migrations.AlterField(
model_name="accesscontrolleddevice",
name="post_to_discord",
field=models.BooleanField(
default=True, verbose_name="Post to discord on swipe"
),
),
migrations.AlterField(
model_name="accesscontrolleddevice",
name="report_online_status",
field=models.BooleanField(
default=True,
verbose_name="Report the online status of this device and fail the uptime check if it's offline.",
),
),
migrations.AlterField(
model_name="memberbucksdevice",
name="supports_products",
field=models.BooleanField(
default=False, verbose_name="Supports the MM products API."
),
),
]
25 changes: 25 additions & 0 deletions memberportal/access/migrations/0018_auto_20240525_0016.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Generated by Django 3.2.25 on 2024-05-24 14:16

from django.db import migrations


class Migration(migrations.Migration):

dependencies = [
("access", "0017_auto_20240523_1604"),
]

operations = [
migrations.RemoveField(
model_name="memberbucksdevice",
name="supports_credits",
),
migrations.RemoveField(
model_name="memberbucksdevice",
name="supports_debits",
),
migrations.RemoveField(
model_name="memberbucksdevice",
name="supports_products",
),
]
38 changes: 24 additions & 14 deletions memberportal/access/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,10 @@
from rest_framework_api_key.permissions import BaseHasAPIKey, AbstractAPIKey
from constance import config
import hashlib
from django.core.validators import URLValidator
from django_prometheus.models import ExportModelOperationsMixin

logger = logging.getLogger("app")
logger = logging.getLogger("access")
User = auth.get_user_model()
utc = pytz.UTC

Expand All @@ -25,8 +27,7 @@ class AccessControlledDeviceAPIKey(AbstractAPIKey):
class Meta:
# Add verbose name
verbose_name = "API Key For Access Controlled Device"

pass
app_label = "access"


class HasAccessControlledDeviceAPIKey(BaseHasAPIKey):
Expand All @@ -45,7 +46,9 @@ class HasExternalAccessControlAPIKey(BaseHasAPIKey):
model = ExternalAccessControlAPIKey


class AccessControlledDevice(models.Model):
class AccessControlledDevice(
ExportModelOperationsMixin("access-controlled-device"), models.Model
):
id = models.AutoField(primary_key=True)
authorised = models.BooleanField(
"Is this device authorised to access the system?", default=False
Expand All @@ -61,13 +64,14 @@ class AccessControlledDevice(models.Model):
last_seen = models.DateTimeField(null=True, blank=True)
all_members = models.BooleanField("Members have access by default", default=False)
locked_out = models.BooleanField("Maintenance lockout enabled", default=False)
play_theme = models.BooleanField("Play theme on door swipe", default=False)
post_to_discord = models.BooleanField("Post to discord on door swipe", default=True)
play_theme = models.BooleanField("Play theme on successful swipe", default=False)
post_to_discord = models.BooleanField("Post to discord on swipe", default=True)
exempt_signin = models.BooleanField(
"Exempt this device from requiring a sign in", default=False
)
report_online_status = models.BooleanField(
"Report the online status of this device.", default=True
"Report the online status of this device and fail the uptime check if it's offline.",
default=True,
)
hidden = models.BooleanField(
"Hidden from members in their access permissions screen", default=False
Expand Down Expand Up @@ -246,12 +250,18 @@ def get_tags(self):
)


class MemberbucksDevice(AccessControlledDevice):
class MemberbucksDevice(
ExportModelOperationsMixin("memberbucks-device"), AccessControlledDevice
):
all_members = True
type = "memberbucks"

class Meta:
verbose_name = "Memberbucks Device"
verbose_name_plural = "Memberbucks Devices"


class Doors(AccessControlledDevice):
class Doors(ExportModelOperationsMixin("door"), AccessControlledDevice):
type = "door"

class Meta:
Expand Down Expand Up @@ -318,7 +328,7 @@ def log_access(self, member_id, success=True):
return door_log


class Interlock(AccessControlledDevice):
class Interlock(ExportModelOperationsMixin("interlock"), AccessControlledDevice):
type = "interlock"

cost_per_session = models.IntegerField(
Expand Down Expand Up @@ -386,18 +396,18 @@ def log_access(self, user, type="activated"):
return True


class DoorLog(models.Model):
class DoorLog(ExportModelOperationsMixin("door-log"), models.Model):
id = models.AutoField(primary_key=True)
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
door = models.ForeignKey(Doors, on_delete=models.CASCADE)
date = models.DateTimeField(default=timezone.now)
success = models.BooleanField(default=True)

def __str__(self):
return f"{self.user.get_full_name()} ({self.user.profile.screen_name}) swiped at {self.door.name} {'successfully' if self.success else 'unsuccessfully'} at {self.date.date()}"
return f"{self.user.get_full_name()} ({self.user.profile.screen_name}) swiped at {self.door.name} {'successfully' if self.success else 'unsuccessfully'} on {self.date.date()}"


class InterlockLog(models.Model):
class InterlockLog(ExportModelOperationsMixin("interlock-log"), models.Model):
id = models.UUIDField(default=uuid.uuid4, primary_key=True)
interlock = models.ForeignKey(Interlock, on_delete=models.CASCADE)
user_started = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
Expand All @@ -420,7 +430,7 @@ class InterlockLog(models.Model):
total_cost = models.FloatField(default=None, blank=True, null=True)

def __str__(self):
return f"{self.user_started.get_full_name()} ({self.user_started.profile.screen_name}) swiped at {self.interlock.name} {'successfully' if self.success else 'unsuccessfully'} for {self.total_time.total_seconds()/60} mins at {self.date_started.date()}"
return f"{self.user_started.get_full_name()} ({self.user_started.profile.screen_name}) swiped at {self.interlock.name} {'successfully' if self.success else 'unsuccessfully'} for {round(self.total_time.total_seconds()/60)} mins at {self.date_started.date()}"

def calculate_cost(self):
total_cost = self.interlock.cost_per_session
Expand Down
8 changes: 0 additions & 8 deletions memberportal/api_access/apps.py

This file was deleted.

Loading
Loading