1
0
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:
Ralf Ramsauer 2018-10-08 22:59:34 +02:00
parent 8d37886ee1
commit 00f74d69f9
3 changed files with 91 additions and 100 deletions

View File

@ -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

View File

@ -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
View 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'