def get_events_from_lock_id(lock_id: str) -> List[Event]: events = DB.child("LockEvents").child(lock_id).get().val() event_ids = events.keys() if events else set() output = [] for event_id in event_ids: event = Event.from_database( event_id, DB.child("EventHistory").child(event_id).get().val()) output.append(event) return output
def update_password(lock_id: str, password_id: str, update_request: Dict[str, str]) -> PasswordMetadata: if len(update_request.keys()) == 0: raise ValidationException("Fields to update weren't supplied") password = get_password(lock_id, password_id) password.update(update_request) DB.child("Locks").child(lock_id).child("passwords").child( password_id).update(password.serialize()) return get_password_metadata(lock_id, password_id)
def change_lock_status(lock_id, status, was_lock_removed=None): DB.child("Locks").child(lock_id).update({'status': status.value}) if was_lock_removed is None: return { "status": status.value, } else: return { "status": status.value, "providedPasswordDisabled": was_lock_removed }
def delete_user_lock(uid, lock_id): user_lock_entry = DB.child("UserLocks").child(uid).get().val() owned_locks = set( user_lock_entry.get('ownedLockIds') if user_lock_entry else []) owned_locks.remove(lock_id) DB.child("UserLocks").child(uid).set(list(owned_locks)) # TODO: more expensive than necessary, can simply build # an object using the variables above return get_user_locks(uid)
def decorated_func(*args, **kws): if 'Authorization' in request.headers: header_key = 'Authorization' else: abort(401) data = str(request.headers[header_key]) if not data.startswith('Basic'): raise ValidationException("Basic authorization required") coded_string = str.replace(str(data), 'Basic ', '') decoded = base64.b64decode(coded_string).decode('utf-8') string_split = decoded.split(':') if len(string_split) < 2: msg = ("Basic auth must be base-64 " "encoded in 'lockId:password' format") raise AuthorizationException(msg) lock_id, secret = string_split[0], ':'.join(string_split[1:]) try: secret_hashed = DB.child("Locks").child( lock_id).get().val().get('secret') except BaseException: raise AuthorizationException("Lock could not be found") if not security_utils.check_password(secret, secret_hashed): raise AuthorizationException("Invalid secret supplied") return f(lock_id, *args, **kws)
def _get_sorted_passwords(lock_id): type_ordinal = { PasswordType.UNLIMITED: 0, PasswordType.OTP: 1, } passwords = DB.child("Locks").child(lock_id).child( "passwords").get().val() or {} passwords_list = [(pw_id, password_dict) for pw_id, password_dict in passwords.items()] passwords_list = sorted( passwords_list, key=lambda x: type_ordinal[PasswordType(x[1]['type'])]) passwords_list = [ Password.from_database(id, password_dict) for id, password_dict in passwords_list ] expired_passwords = [] output = [] for password in passwords_list: if password.expiration != -1 \ and password.expiration < time_utils.get_current_time_ms(): expired_passwords.append(password) elif _password_is_active(password): output.append(password) _prune_passwords(lock_id, expired_passwords) return output
def decorated_func(*args, **kws): if 'api_key' in request.args: token = request.args['api_key'] else: if 'Authorization' in request.headers: header_key = 'Authorization' elif 'Api-Key' in request.headers: header_key = 'Api-Key' else: abort(401) data = str(request.headers[header_key]) token = str.replace(str(data), 'Bearer ', '') try: user = AUTH.get_account_info(token)['users'][0] except BaseException: abort(401) uid = user['localId'] found_user = DB.child("Users").child(uid).get().val() if not found_user: create_or_update_user_from_json(uid, user) if admin and not found_user.get('isAdmin', False): raise AdminOnlyException("Admin account required") return f(uid, user, *args, **kws)
def create_or_update_user_lock(uid, user_locks, should_overwrite=False): invalid_ids = [] for lock_id in user_locks.owned_lock_ids: if DB.child("Locks").child(lock_id).get().val() is None: invalid_ids.append(lock_id) if len(invalid_ids) > 0: raise ValidationException("Invalid lock ids: {}".format(invalid_ids)) if not should_overwrite: user_lock_entry = DB.child("UserLocks").child(uid).get().val() prev_locks = user_lock_entry.get( 'ownedLockIds') if user_lock_entry else [] combined_locks = list(set(prev_locks).union(user_locks.owned_lock_ids)) user_locks.owned_lock_ids = combined_locks DB.child("UserLocks").child(uid).set(user_locks.serialize()) return user_locks.serialize()
def verify_lock_ownership(uid, lock_id): is_owned = True message = '' uid_lookup = DB.child("UserLocks").child(uid).get().val() if DB.child("Locks").child(lock_id).get().val() is None: is_owned = False message = 'Lock could not be identified' elif uid_lookup is None: is_owned = False message = 'User could not be identified or has not registered a lock' else: owned_locks = set(uid_lookup.get('ownedLockIds')) if lock_id not in owned_locks: is_owned = False message = 'User does not own this lock' if not is_owned: raise AuthorizationException(message=message)
def add_password(lock_id, password: Password) -> PasswordMetadata: new_id = DB.child("Locks").child(lock_id).child("passwords").push( password.serialize())['name'] # return a metadata object instead of a password to ensure that the # password is not shared with the outside world return PasswordMetadata( type=password.type, expiration=password.expiration, active_days=password.active_days, active_times=password.active_times, id=new_id, )
def add_event(event: Event): serialized_event = event.serialize() new_id = DB.child("EventHistory").push(serialized_event)['name'] event.id = new_id DB.child("LockEvents").child(event.lock_id).update({new_id: True}) return {new_id: serialized_event}
def get_user_locks(uid): owned_lock_ids = DB.child("UserLocks").child(uid).child( 'ownedLockIds').get().val() if owned_lock_ids is None: owned_lock_ids = [] return {'ownedLockIds': owned_lock_ids}
def get_user(uid): return DB.child("Users").child(uid).get().val()
def get_lock_status(lock_id): status_str = DB.child("Locks").child(lock_id).get().val().get("status") return {"status": status_str}
def add_lock(lock): new_id = DB.child("Locks").push(lock.serialize())['name'] lock.id = new_id return {new_id: lock.serialize()}
def remove_password_by_id(lock_id: str, password_id: str) -> None: if password_id.strip() == '': return DB.child("Locks").child(lock_id).child("passwords").child( password_id).remove()
def create_or_update_user_locks(user_locks): DB.child("UserLocks").set(user_locks.serialize())
def get_locks(lock_ids): return { lock_id: DB.child("Locks").child(lock_id).get().val() for lock_id in lock_ids }
def create_or_update_user(uid, user): DB.child("Users").child(uid).set(user.serialize())
def _prune_passwords(lock_id, passwords): for password in passwords: DB.child("Locks").child(lock_id).child("passwords").child( password.id).remove()