mirror of
https://github.com/binary-kitchen/doorlockd
synced 2024-10-31 22:47:05 +01:00
pydoorlock: Refactor LogicResponse to DoorlockResponse
Signed-off-by: Ralf Ramsauer <ralf@binary-kitchen.de>
This commit is contained in:
parent
8d37886ee1
commit
00f74d69f9
68
doorlockd
68
doorlockd
@ -28,9 +28,10 @@ from subprocess import Popen
|
|||||||
from threading import Thread
|
from threading import Thread
|
||||||
from time import sleep
|
from time import sleep
|
||||||
|
|
||||||
from pydoorlock.Authenticator import Authenticator, AuthMethod, AuthenticationResult
|
from pydoorlock.Authenticator import Authenticator, AuthMethod
|
||||||
from pydoorlock.WebApp import webapp_run, emit_doorstate
|
from pydoorlock.WebApp import webapp_run, emit_doorstate
|
||||||
from pydoorlock.Door import DoorState
|
from pydoorlock.Door import DoorState
|
||||||
|
from pydoorlock.Doorlock import DoorlockResponse
|
||||||
|
|
||||||
SYSCONFDIR = '.'
|
SYSCONFDIR = '.'
|
||||||
PREFIX = '.'
|
PREFIX = '.'
|
||||||
@ -106,6 +107,7 @@ def start_hook(script):
|
|||||||
def sound_helper(old_state, new_state, button):
|
def sound_helper(old_state, new_state, button):
|
||||||
if old_state == new_state:
|
if old_state == new_state:
|
||||||
playsound(wave_zonk)
|
playsound(wave_zonk)
|
||||||
|
return
|
||||||
|
|
||||||
if button:
|
if button:
|
||||||
if new_state == DoorState.Open:
|
if new_state == DoorState.Open:
|
||||||
@ -123,40 +125,6 @@ def sound_helper(old_state, new_state, button):
|
|||||||
playsound(wave_lock)
|
playsound(wave_lock)
|
||||||
|
|
||||||
|
|
||||||
class LogicResponse(Enum):
|
|
||||||
Success = 0
|
|
||||||
Perm = 1
|
|
||||||
AlreadyActive = 2
|
|
||||||
# don't break old apps, value 3 is reserved now
|
|
||||||
RESERVED = 3
|
|
||||||
Inval = 4
|
|
||||||
|
|
||||||
EmergencyUnlock = 10,
|
|
||||||
ButtonLock = 11,
|
|
||||||
ButtonUnlock = 12,
|
|
||||||
ButtonPresent = 13,
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
if self == LogicResponse.Success:
|
|
||||||
return 'Yo, passt.'
|
|
||||||
elif self == LogicResponse.Perm:
|
|
||||||
return choose_insult()
|
|
||||||
elif self == LogicResponse.AlreadyActive:
|
|
||||||
return 'Zustand bereits aktiv'
|
|
||||||
elif self == LogicResponse.Inval:
|
|
||||||
return 'Das was du willst geht nicht.'
|
|
||||||
elif self == LogicResponse.EmergencyUnlock:
|
|
||||||
return '!!! Emergency Unlock !!!'
|
|
||||||
elif self == LogicResponse.ButtonLock:
|
|
||||||
return 'Closed by button'
|
|
||||||
elif self == LogicResponse.ButtonUnlock:
|
|
||||||
return 'Opened by button'
|
|
||||||
elif self == LogicResponse.ButtonPresent:
|
|
||||||
return 'Present by button'
|
|
||||||
|
|
||||||
return 'Error'
|
|
||||||
|
|
||||||
|
|
||||||
class DoorHandler:
|
class DoorHandler:
|
||||||
state = DoorState.Closed
|
state = DoorState.Closed
|
||||||
do_close = False
|
do_close = False
|
||||||
@ -229,37 +197,41 @@ class DoorHandler:
|
|||||||
|
|
||||||
def open(self):
|
def open(self):
|
||||||
if self.state == DoorState.Open:
|
if self.state == DoorState.Open:
|
||||||
return LogicResponse.AlreadyActive
|
return DoorlockResponse.AlreadyActive
|
||||||
|
|
||||||
self.state = DoorState.Open
|
self.state = DoorState.Open
|
||||||
start_hook('post_unlock')
|
start_hook('post_unlock')
|
||||||
return LogicResponse.Success
|
return DoorlockResponse.Success
|
||||||
|
|
||||||
def present(self):
|
def present(self):
|
||||||
if self.state == DoorState.Present:
|
if self.state == DoorState.Present:
|
||||||
return LogicResponse.AlreadyActive
|
return DoorlockResponse.AlreadyActive
|
||||||
|
|
||||||
self.state = DoorState.Present
|
self.state = DoorState.Present
|
||||||
start_hook('post_present')
|
start_hook('post_present')
|
||||||
return LogicResponse.Success
|
return DoorlockResponse.Success
|
||||||
|
|
||||||
def close(self):
|
def close(self):
|
||||||
if self.state == DoorState.Closed:
|
if self.state == DoorState.Closed:
|
||||||
return LogicResponse.AlreadyActive
|
return DoorlockResponse.AlreadyActive
|
||||||
|
|
||||||
self.do_close = True
|
self.do_close = True
|
||||||
self.state = DoorState.Closed
|
self.state = DoorState.Closed
|
||||||
start_hook('post_lock')
|
start_hook('post_lock')
|
||||||
return LogicResponse.Success
|
return DoorlockResponse.Success
|
||||||
|
|
||||||
def request(self, state):
|
def request(self, state):
|
||||||
|
old_state = self.state
|
||||||
if state == DoorState.Closed:
|
if state == DoorState.Closed:
|
||||||
err = self.close()
|
err = self.close()
|
||||||
elif state == DoorState.Present:
|
elif state == DoorState.Present:
|
||||||
err = self.present()
|
err = self.present()
|
||||||
elif state == DoorState.Open:
|
elif state == DoorState.Open:
|
||||||
err = self.open()
|
err = self.open()
|
||||||
|
|
||||||
|
sound_helper(old_state, self.state, False)
|
||||||
emit_doorstate()
|
emit_doorstate()
|
||||||
|
return err
|
||||||
|
|
||||||
|
|
||||||
class Logic:
|
class Logic:
|
||||||
@ -267,19 +239,13 @@ class Logic:
|
|||||||
self.auth = Authenticator(cfg)
|
self.auth = Authenticator(cfg)
|
||||||
self.door_handler = DoorHandler(cfg)
|
self.door_handler = DoorHandler(cfg)
|
||||||
|
|
||||||
def _request(self, state, credentials):
|
|
||||||
err = self.auth.try_auth(credentials)
|
|
||||||
if err != AuthenticationResult.Success:
|
|
||||||
return err
|
|
||||||
return self.door_handler.request(state)
|
|
||||||
|
|
||||||
def request(self, state, credentials):
|
def request(self, state, credentials):
|
||||||
old_state = self.door_handler.state
|
err = self.auth.try_auth(credentials)
|
||||||
err = self._request(state, credentials)
|
if err != DoorlockResponse.Success:
|
||||||
if err == LogicResponse.Success or err == LogicResponse.AlreadyActive:
|
|
||||||
sound_helper(old_state, self.door_handler.state, False)
|
|
||||||
return err
|
return err
|
||||||
|
|
||||||
|
return self.door_handler.request(state)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def state(self):
|
def state(self):
|
||||||
return self.door_handler.state
|
return self.door_handler.state
|
||||||
|
@ -20,35 +20,11 @@ import ldap
|
|||||||
import logging
|
import logging
|
||||||
|
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
from random import sample
|
|
||||||
|
from .Doorlock import DoorlockResponse
|
||||||
|
|
||||||
log = logging.getLogger()
|
log = logging.getLogger()
|
||||||
|
|
||||||
# copied from sudo
|
|
||||||
eperm_insults = {
|
|
||||||
'Wrong! You cheating scum!',
|
|
||||||
'And you call yourself a Rocket Scientist!',
|
|
||||||
'No soap, honkie-lips.',
|
|
||||||
'Where did you learn to type?',
|
|
||||||
'Are you on drugs?',
|
|
||||||
'My pet ferret can type better than you!',
|
|
||||||
'You type like i drive.',
|
|
||||||
'Do you think like you type?',
|
|
||||||
'Your mind just hasn\'t been the same since the electro-shock, has it?',
|
|
||||||
'Maybe if you used more than just two fingers...',
|
|
||||||
'BOB says: You seem to have forgotten your passwd, enter another!',
|
|
||||||
'stty: unknown mode: doofus',
|
|
||||||
'I can\'t hear you -- I\'m using the scrambler.',
|
|
||||||
'The more you drive -- the dumber you get.',
|
|
||||||
'Listen, broccoli brains, I don\'t have time to listen to this trash.',
|
|
||||||
'I\'ve seen penguins that can type better than that.',
|
|
||||||
'Have you considered trying to match wits with a rutabaga?',
|
|
||||||
'You speak an infinite deal of nothing',
|
|
||||||
}
|
|
||||||
|
|
||||||
def choose_insult():
|
|
||||||
return(sample(eperm_insults, 1)[0])
|
|
||||||
|
|
||||||
|
|
||||||
class AuthMethod(Enum):
|
class AuthMethod(Enum):
|
||||||
LDAP_USER_PW = 1
|
LDAP_USER_PW = 1
|
||||||
@ -62,19 +38,6 @@ class AuthMethod(Enum):
|
|||||||
return 'Error'
|
return 'Error'
|
||||||
|
|
||||||
|
|
||||||
class AuthenticationResult(Enum):
|
|
||||||
Success = 0
|
|
||||||
Perm = 1
|
|
||||||
InternalError = 2
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
if self == AuthenticationResult.Success:
|
|
||||||
return 'Yo, passt!'
|
|
||||||
elif self == AuthenticationResult.Perm:
|
|
||||||
return choose_insult()
|
|
||||||
else:
|
|
||||||
return 'Internal authentication error'
|
|
||||||
|
|
||||||
class Authenticator:
|
class Authenticator:
|
||||||
def __init__(self, cfg):
|
def __init__(self, cfg):
|
||||||
self._simulate = cfg.boolean('SIMULATE_AUTH')
|
self._simulate = cfg.boolean('SIMULATE_AUTH')
|
||||||
@ -111,14 +74,14 @@ class Authenticator:
|
|||||||
|
|
||||||
def _try_auth_local(self, user, password):
|
def _try_auth_local(self, user, password):
|
||||||
if user not in self._local_db:
|
if user not in self._local_db:
|
||||||
return AuthenticationResult.Perm
|
return DoorlockResponse.Perm
|
||||||
|
|
||||||
stored_pw = self._local_db[user][0]
|
stored_pw = self._local_db[user][0]
|
||||||
stored_salt = self._local_db[user][1]
|
stored_salt = self._local_db[user][1]
|
||||||
if stored_pw == hashlib.sha256(stored_salt.encode() + password.encode()).hexdigest():
|
if stored_pw == hashlib.sha256(stored_salt.encode() + password.encode()).hexdigest():
|
||||||
return AuthenticationResult.Success
|
return DoorlockResponse.Success
|
||||||
|
|
||||||
return AuthenticationResult.Perm
|
return DoorlockResponse.Perm
|
||||||
|
|
||||||
def _try_auth_ldap(self, user, password):
|
def _try_auth_ldap(self, user, password):
|
||||||
log.info(' Trying to LDAP auth (user, password) as user %s', user)
|
log.info(' Trying to LDAP auth (user, password) as user %s', user)
|
||||||
@ -129,24 +92,24 @@ class Authenticator:
|
|||||||
l.unbind_s()
|
l.unbind_s()
|
||||||
except ldap.INVALID_CREDENTIALS:
|
except ldap.INVALID_CREDENTIALS:
|
||||||
log.info(' Invalid credentials')
|
log.info(' Invalid credentials')
|
||||||
return AuthenticationResult.Perm
|
return DoorlockResponse.Perm
|
||||||
except ldap.LDAPError as e:
|
except ldap.LDAPError as e:
|
||||||
log.info(' LDAP Error: %s' % e)
|
log.info(' LDAP Error: %s' % e)
|
||||||
return AuthenticationResult.InternalError
|
return DoorlockResponse.InternalError
|
||||||
return AuthenticationResult.Success
|
return DoorlockResponse.Success
|
||||||
|
|
||||||
def try_auth(self, credentials):
|
def try_auth(self, credentials):
|
||||||
if self._simulate:
|
if self._simulate:
|
||||||
log.info('SIMULATION MODE! ACCEPTING ANYTHING!')
|
log.info('SIMULATION MODE! ACCEPTING ANYTHING!')
|
||||||
return AuthenticationResult.Success
|
return DoorlockResponse.Success
|
||||||
|
|
||||||
method = credentials[0]
|
method = credentials[0]
|
||||||
if method not in self._backends:
|
if method not in self._backends:
|
||||||
return AuthenticationResult.InternalError
|
return DoorlockResponse.InternalError
|
||||||
|
|
||||||
if method == AuthMethod.LDAP_USER_PW:
|
if method == AuthMethod.LDAP_USER_PW:
|
||||||
return self._try_auth_ldap(credentials[1], credentials[2])
|
return self._try_auth_ldap(credentials[1], credentials[2])
|
||||||
elif method == AuthMethod.LOCAL_USER_DB:
|
elif method == AuthMethod.LOCAL_USER_DB:
|
||||||
return self._try_auth_local(credentials[1], credentials[2])
|
return self._try_auth_local(credentials[1], credentials[2])
|
||||||
|
|
||||||
return AuthenticationResult.InternalError
|
return DoorlockResponse.InternalError
|
||||||
|
62
pydoorlock/Doorlock.py
Normal file
62
pydoorlock/Doorlock.py
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
from enum import Enum
|
||||||
|
from random import sample
|
||||||
|
|
||||||
|
# copied from sudo
|
||||||
|
eperm_insults = {
|
||||||
|
'Wrong! You cheating scum!',
|
||||||
|
'And you call yourself a Rocket Scientist!',
|
||||||
|
'No soap, honkie-lips.',
|
||||||
|
'Where did you learn to type?',
|
||||||
|
'Are you on drugs?',
|
||||||
|
'My pet ferret can type better than you!',
|
||||||
|
'You type like i drive.',
|
||||||
|
'Do you think like you type?',
|
||||||
|
'Your mind just hasn\'t been the same since the electro-shock, has it?',
|
||||||
|
'Maybe if you used more than just two fingers...',
|
||||||
|
'BOB says: You seem to have forgotten your passwd, enter another!',
|
||||||
|
'stty: unknown mode: doofus',
|
||||||
|
'I can\'t hear you -- I\'m using the scrambler.',
|
||||||
|
'The more you drive -- the dumber you get.',
|
||||||
|
'Listen, broccoli brains, I don\'t have time to listen to this trash.',
|
||||||
|
'I\'ve seen penguins that can type better than that.',
|
||||||
|
'Have you considered trying to match wits with a rutabaga?',
|
||||||
|
'You speak an infinite deal of nothing',
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def choose_insult():
|
||||||
|
return(sample(eperm_insults, 1)[0])
|
||||||
|
|
||||||
|
|
||||||
|
class DoorlockResponse(Enum):
|
||||||
|
Success = 0
|
||||||
|
Perm = 1
|
||||||
|
AlreadyActive = 2
|
||||||
|
# don't break old apps, value 3 is reserved now
|
||||||
|
RESERVED = 3
|
||||||
|
Inval = 4
|
||||||
|
|
||||||
|
EmergencyUnlock = 10,
|
||||||
|
ButtonLock = 11,
|
||||||
|
ButtonUnlock = 12,
|
||||||
|
ButtonPresent = 13,
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
if self == DoorlockResponse.Success:
|
||||||
|
return 'Yo, passt.'
|
||||||
|
elif self == DoorlockResponse.Perm:
|
||||||
|
return choose_insult()
|
||||||
|
elif self == DoorlockResponse.AlreadyActive:
|
||||||
|
return 'Zustand bereits aktiv'
|
||||||
|
elif self == DoorlockResponse.Inval:
|
||||||
|
return 'Das was du willst geht nicht.'
|
||||||
|
elif self == DoorlockResponse.EmergencyUnlock:
|
||||||
|
return '!!! Emergency Unlock !!!'
|
||||||
|
elif self == DoorlockResponse.ButtonLock:
|
||||||
|
return 'Closed by button'
|
||||||
|
elif self == DoorlockResponse.ButtonUnlock:
|
||||||
|
return 'Opened by button'
|
||||||
|
elif self == DoorlockResponse.ButtonPresent:
|
||||||
|
return 'Present by button'
|
||||||
|
|
||||||
|
return 'Error'
|
Loading…
Reference in New Issue
Block a user