mirror of
https://gitlab.com/sfz.aalen/infra/fabaccess.git
synced 2025-03-12 15:01:47 +01:00
variable configuration through config.py and code splitting into multiple files. Also added requirements.txt and gitignore.
154 lines
5.2 KiB
Python
154 lines
5.2 KiB
Python
from keycloak import KeycloakAdmin
|
|
import json
|
|
import psycopg
|
|
import os
|
|
from paho.mqtt.client import Client as MQTTClient
|
|
|
|
import config
|
|
from mqtt_helper import MQTTHelper
|
|
|
|
conn: psycopg.Connection
|
|
keycloak_admin: KeycloakAdmin
|
|
|
|
def publish(client, topic,msg):
|
|
result = client.publish(topic, msg)
|
|
status: 0 | 1 = result[0]
|
|
if status == 0:
|
|
#print(f"Send `{msg}` to topic `{topic}`")
|
|
pass
|
|
else:
|
|
print(f"Failed to send message to topic {topic}")
|
|
|
|
def changePlug(client: MQTTClient, plug_id: str, is_running: bool):
|
|
publish(client,f"/FabLogging/{plug_id}/POWER", is_running)
|
|
cmd = "On" if is_running else "Off"
|
|
publish(client, f"/aktoren/{plug_id}/cmnd/POWER", cmd)
|
|
|
|
def changeDisplay(client: MQTTClient, reader_id: str, status: int, fab_card_id: str):
|
|
publish(client, f"/cmnd/reader/{reader_id}", '{"Cmd": "message", "MssgID": %s , "ClrTxt":"" , "AddnTxt":"%s"}' % (status, fab_card_id))
|
|
|
|
def hasPermission(UserPermsJSON, PermissionPath):
|
|
# ToDo: refactor this
|
|
permission = False
|
|
error = 0
|
|
MachinePermArray = PermissionPath.split(".")
|
|
for UserPerm in UserPermsJSON:
|
|
#print(f"check {UserPerm}")
|
|
UserPermArray = UserPerm.split(".")
|
|
x = 0
|
|
for UserPermPart in UserPermArray:
|
|
if(error == 0):
|
|
#print(f"Compare {UserPermPart} and {MachinePermArray[x]}")
|
|
if not (MachinePermArray[x] == UserPermPart):
|
|
if(UserPermPart == "*"):
|
|
#print("* regelt")
|
|
permission = True
|
|
else:
|
|
error = 1
|
|
#print(f"MISmatch between {MachinePermArray[x]} and {UserPermPart}")
|
|
else:
|
|
pass
|
|
#print(f"Match between {MachinePermArray[x]} and {UserPermPart}")
|
|
x = x + 1
|
|
if(error == 1):
|
|
pass
|
|
#print("Error")
|
|
else:
|
|
#print("Hurra")
|
|
permission = True
|
|
error = 0
|
|
return permission
|
|
|
|
def handle_msg(client: MQTTClient, userdata, msg):
|
|
global conn
|
|
|
|
payload = msg.payload.decode()
|
|
print(f"Received `{payload}` from `{msg.topic}` topic")
|
|
|
|
fab_card_id = json.loads(msg.payload.decode())["UID"]
|
|
reader_id = msg.topic.split("/")[-1]
|
|
|
|
# check user exists
|
|
users = keycloak_admin.get_users({ 'attributes': { 'FabCard': fab_card_id } })
|
|
if (len(users) != 1):
|
|
print(f'Found {len(users)} users with {fab_card_id=}')
|
|
changeDisplay(client, reader_id, 16, fab_card_id)
|
|
return
|
|
|
|
# retrieve user attributes from DB
|
|
user = users[0]
|
|
print(f"FabCard matches with user {user['username']}")
|
|
with conn.cursor() as cursor:
|
|
cursor.execute(f'SELECT PlugName,PermissionPath,Status,LastUser FROM ReaderPlug WHERE ReaderID=?;', (reader_id,))
|
|
res = cursor.fetchone()
|
|
if res is None:
|
|
print(f'Error fetching card info from db for {reader_id=}')
|
|
return
|
|
plug_id, permission_path, is_running, last_user = res
|
|
|
|
# check permissions
|
|
user_permissions = user['attributes']['FabPermissions'][0]
|
|
if not hasPermission(user_permissions, permission_path):
|
|
changeDisplay(client, reader_id, 7, "")
|
|
return
|
|
|
|
# check for mentor
|
|
if is_running and last_user != user['username']:
|
|
try:
|
|
if (keycloak_admin.get_user_groups(user_id=user['id'])[0]['name'] == 'Mentoren'):
|
|
print('Overrided becouse of "Mentor" Group')
|
|
else:
|
|
print(f'Bereits benutzt von {last_user}')
|
|
error = True
|
|
except IndexError:
|
|
print("No groups available")
|
|
error = True
|
|
if(error):
|
|
changeDisplay(client, reader_id, 9, last_user)
|
|
|
|
# toggle machine state
|
|
print(f"Turn Plug {'off' if is_running else 'on'}")
|
|
changePlug(client, plug_id, is_running)
|
|
publish(client, f"/FabLogging/{plug_id}/USER", user['username'])
|
|
|
|
# ToDo: refactor display name construction
|
|
try:
|
|
firstCombo = user['firstName']+" "
|
|
DisplayUser = firstCombo+user['lastName']
|
|
if(len(firstCombo) >= 7):
|
|
DisplayUser = user['firstName'][:7]
|
|
except KeyError:
|
|
DisplayUser = user['username']
|
|
if(len(DisplayUser) > 7):
|
|
DisplayUser = DisplayUser[0:7] + "." + DisplayUser[7+1: ]
|
|
DisplayUser = DisplayUser[:8]
|
|
|
|
changeDisplay(client, reader_id, 20, f"Login\n{DisplayUser}" if is_running else "Bitte anmelden")
|
|
|
|
# write new status to db
|
|
with conn.cursor() as cursor:
|
|
cursor.execute(
|
|
f'UPDATE ReaderPlug SET Status=?, LastUser="?" WHERE ReaderID="?";',
|
|
(is_running, user['username'], reader_id),
|
|
)
|
|
conn.commit()
|
|
|
|
def main():
|
|
global conn
|
|
|
|
mqtt_client = MQTTHelper(**config.get_mqtt_config())
|
|
mqtt_client.subscribe("/rfid_reader/#", handle_msg)
|
|
mqtt_client.loop_forever()
|
|
|
|
try:
|
|
conn = psycopg.connect(**config.get_database_config())
|
|
except mariadb.Error as e:
|
|
print(f"Error connecting to MariaDB Platform")
|
|
raise e
|
|
|
|
keycloak_admin = KeycloakAdmin(**config.get_keycloak_config(), verify=True)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|