Skip to content

Commit

Permalink
Merge pull request #91 from MakerSpaceLeiden/feat_msg_send
Browse files Browse the repository at this point in the history
Feat msg send
  • Loading branch information
dirkx authored Sep 30, 2024
2 parents c8dd028 + 4cebfe2 commit fe7ebb4
Show file tree
Hide file tree
Showing 12 changed files with 432 additions and 13 deletions.
8 changes: 3 additions & 5 deletions acl/management/commands/acl_show.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,9 @@

from django.core.management.base import BaseCommand

from acl.views import tags4machineBIN

from members.models import User
from acl.models import Machine, useNeedsToStateStr
from members.models import User


class Command(BaseCommand):
help = "Export binary tag/member file for a given machine."
Expand All @@ -17,7 +16,6 @@ def add_arguments(self, parser):
def handle(self, *args, **options):
rc = 0

terminal = None
machine = options["machine"]
user = options["user"]

Expand All @@ -27,6 +25,6 @@ def handle(self, *args, **options):
(needs, has) = machine.useState(user)
res = needs & has
print(f"has({has:X}) & needs({needs:X}) = {res:X}")
print(useNeedsToStateStr(needs,has))
print(useNeedsToStateStr(needs, has))

sys.exit(rc)
22 changes: 22 additions & 0 deletions acl/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
from django.utils import timezone
from simple_history.models import HistoricalRecords

# from pettycash.models import PettycashBalanceCache
from members.models import Tag, User

logger = logging.getLogger(__name__)
Expand All @@ -31,6 +32,8 @@ class MachineUseFlags(IntEnum):
PERMIT = 2
FORM = 4
APPROVE = 8
INSTRUCT = 16
BUDGET = 32


def bits2str(needs, has):
Expand All @@ -39,6 +42,9 @@ def bits2str(needs, has):
return "ok"
else:
return "fail"
else:
if has:
return "NN"
return "nn"


Expand All @@ -55,6 +61,15 @@ def useNeedsToStateStr(needs, has):
out += ", approve:" + bits2str(
needs & MachineUseFlags.APPROVE, has & MachineUseFlags.APPROVE
)
if has & MachineUseFlags.INSTRUCT:
out += ", instructor=yes"
else:
out += ", instructor=no"
if has & MachineUseFlags.BUDGET:
out += ", budget=sufficient"
else:
out += ", budget=no"

out += " = "
if has & needs == needs:
out += "ok"
Expand Down Expand Up @@ -190,6 +205,13 @@ def useState(self, user):
flags |= MachineUseFlags.PERMIT
if e and e.active:
flags |= MachineUseFlags.APPROVE
if self.canInstruct(user):
flags |= MachineUseFlags.INSTRUCT
# ce = PettycashBalanceCache.objects.get(owner=user)
# if ce.balance > settings.MIN_BALANCE_FOR_CREDIT:
if user.pettycash_cache.first().balance > settings.MIN_BALANCE_FOR_CREDIT:
flags |= MachineUseFlags.BUDGET

return [needs, flags]

def canOperate(self, user):
Expand Down
5 changes: 5 additions & 0 deletions acl/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,4 +84,9 @@
views.api_gettags4machineBIN,
name="acl-v1-gettags-bin",
),
path(
"acl/api/v2/gettags4machineBIN/<str:machine>",
views.api2_gettags4machineBIN,
name="acl-v2-gettags-bin",
),
]
42 changes: 37 additions & 5 deletions acl/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -707,12 +707,18 @@ def byte_xor(ba1, ba2):
#
# 116+LT+LM EOF
#
def tags4machineBIN(terminal=None, machine=None):
# MSL2 -- same as above; but the AES block no longer just contains
# the name of the user; but also their unqiue user ID (for API
# purposes) and their first/last name separate.
#
def tags4machineBIN(terminal=None, machine=None, v2=False):
try:
machine = Machine.objects.get(node_machine_name=machine)
ctc = change_tracker_counter()
except ObjectDoesNotExist:
logger.error(f"BIN request for an unknown machine: {machine} (node-machine-name)")
logger.error(
f"BIN request for an unknown machine: {machine} (node-machine-name)"
)
raise ObjectDoesNotExist

tl = []
Expand All @@ -738,9 +744,17 @@ def tags4machineBIN(terminal=None, machine=None):
# by ESP32 anyway).
#
name = user.name()
clr = pad(name.encode("utf-8"), AES.block_size)
block = b""
if v2:
block += user.id.to_bytes(4, "big")
block += user.first_name.encode("utf-8") + b"\0"
block += user.last_name.encode("utf-8") + b"\0"
else:
block += name.encode("utf-8")

clr = pad(block, AES.block_size)
if len(clr) > 128:
raise Exception("name too large")
raise Exception("information block too large")

enc = AES.new(key, AES.MODE_CBC, iv=uiv).encrypt(clr)

Expand Down Expand Up @@ -780,7 +794,10 @@ def tags4machineBIN(terminal=None, machine=None):
tlb += e["udx"].to_bytes(4, "big")

hdr = b""
hdr += "MSL1".encode("ASCII")
if v2:
hdr += "MSL2".encode("ASCII")
else:
hdr += "MSL1".encode("ASCII")
hdr += ctc.count.to_bytes(
4, "big"
) # byte order not strictly needed - opaque 4 bytes.
Expand Down Expand Up @@ -812,6 +829,21 @@ def api_gettags4machineBIN(request, terminal=None, machine=None):
return HttpResponse(out, status=200, content_type="application/octet-stream")


@csrf_exempt
@is_paired_terminal
def api2_gettags4machineBIN(request, terminal=None, machine=None):
try:
out = tags4machineBIN(terminal, machine, v2=True)
except ObjectDoesNotExist:
logger.error(f"getBIN: Machine '{machine}' not found, denied.")
return HttpResponse("Machine not found", status=404, content_type="text/plain")
except Exception as e:
logger.error(f"Exception: {e}")
return HttpResponse("Internal Error", status=500, content_type="text/plain")

return HttpResponse(out, status=200, content_type="application/octet-stream")


@csrf_exempt
@superuser_or_bearer_required
@checktag
Expand Down
10 changes: 10 additions & 0 deletions makerspaceleiden/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,11 @@
) # as for Reimbursement; but now for 'is_priv' users.
CURRENCIES = ["EUR"]

# Minimal balance needed to be listed as `good for
# your money' - not a real time thing; just a soft
# indicator.
MIN_BALANCE_FOR_CREDIT = Money(-25.00, EUR)

# How long an admin has to accept a new terminal post
# it booting up with a new key.
#
Expand All @@ -325,6 +330,11 @@

NODERED_URL = "http://localhost:1880"

# Notification aliases
NOTIFICATION_MAP = {
"noc": "[email protected]",
}

try:
from .local import * # noqa: F403
except ImportError:
Expand Down
4 changes: 3 additions & 1 deletion members/management/commands/import-consolidated.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,9 @@ def handle(self, *args, **options):

machine, wasCreated = Machine.objects.get_or_create(name=w)
machine.description = "The " + w + " machine"
# machine.location = loc
# machine.location = lo
machine.node_name = "Node" + machine.name.upper()
machine.node_machine_name = machine.name.lower()
machine.requires_form = True
machine.requires_instruction = True
machine.requires_permit = permit
Expand Down
8 changes: 7 additions & 1 deletion pettycash/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,13 @@ def __str__(self):


class PettycashBalanceCache(models.Model):
owner = models.ForeignKey(User, on_delete=models.CASCADE, blank=True, null=True)
owner = models.ForeignKey(
User,
on_delete=models.CASCADE,
blank=True,
null=True,
related_name="pettycash_cache",
)

balance = MoneyField(
max_digits=8, decimal_places=2, null=True, default_currency="EUR"
Expand Down
Loading

0 comments on commit fe7ebb4

Please sign in to comment.