コード例 #1
0
ファイル: handlers.py プロジェクト: troublesomepony/pyledger
    def set_password(self, message: PyledgerRequest) -> Tuple[bool, bytes]:
        password = message.data.decode('utf-8')
        user = User.from_name(message.user)
        user.set_password(password)
        DB.session.commit()

        return True, message.user.encode('utf-8')
コード例 #2
0
def test_1_user():
    """
    Create a normal user
    """
    create_user('user', 'password')
    user = User.from_name('user')
    assert user.get_permissions() == Permissions.USER
    assert user.check_password('password') == True
コード例 #3
0
ファイル: auth.py プロジェクト: troublesomepony/pyledger
def create_user(name, password):
    kpdf = PBKDF2HMAC(algorithm=hashes.SHA256(),
                      length=32,
                      salt=SECRET,
                      iterations=1000000,
                      backend=password_backend)
    user = User()
    user.name = name
    user.when = datetime.datetime.now()
    user.set_permissions(Permissions.USER)
    user.set_password(kpdf.derive(password.encode('utf-8')))

    DB.session.add(user)
    DB.session.commit()
コード例 #4
0
def test_0_master_user():
    """
    Create a master user
    """
    create_master('password')
    user = User.from_name('master')
    assert user.get_permissions() == Permissions.ROOT
    assert user.check_password('password') == True

    # Create dummy session
    session = Session()
    session.user = user
    session.key = 'test_session'
    session.registered = datetime.datetime.now()
    session.until = datetime.datetime.now() + datetime.timedelta(hours=LIFETIME)

    DB.session.add(session)
    DB.session.commit()
コード例 #5
0
def test_2_create_user():
    """
    Create a user from the API
    """
    request = PyledgerRequest()
    request.request = 'new_user'
    request.user = '******'
    request.password = '******'
    request.session_key = 'test_session'
    request.data = pickle.dumps(('user2', 'new_password'))

    response = PyledgerResponse()
    response.ParseFromString(handle_request(request.SerializeToString()))
    assert response.successful == True
    assert response.data == b'user2'

    user = User.from_name('user2')
    assert user.get_permissions() == Permissions.USER
    assert user.check_password('new_password')
コード例 #6
0
ファイル: handlers.py プロジェクト: troublesomepony/pyledger
    def session(self, message: PyledgerRequest) -> Tuple[bool, bytes]:
        """
        Get authentication key

        :param message:
        :return:
        """
        user = User.from_name(message.user)
        session = Session()
        session.user = user
        session.key = str(uuid4())
        session.registered = datetime.datetime.now()
        session.until = datetime.datetime.now() + datetime.timedelta(
            hours=LIFETIME)

        DB.session.add(session)
        DB.session.commit()

        return True, session.key.encode('utf-8')
コード例 #7
0
ファイル: handlers.py プロジェクト: troublesomepony/pyledger
def handle_request(payload: bytes):
    """
    Handle a single request

    :param payload: Serialized PyledgerRequest message
    :return:
    """
    handler = Handler()
    message = PyledgerRequest()
    response = PyledgerResponse()

    try:
        message.ParseFromString(payload)
    except DecodeError:
        response.successful = False
        response.data = b'Message not properly formatted'
        return response.SerializeToString()

    if message.request not in handler_methods(handler):
        response.successful = False
        response.data = 'Request type {} not available'.format(
            message.request).encode()
        return response.SerializeToString()

    else:
        # Handle authentication
        if message.request in permissions_registry:
            user = User.from_name(message.user)
            permission_required = permissions_registry[message.request]

            if not user.check_password(message.password):
                response.successful = False
                response.data = b'Wrong user and/or password'
                return response.SerializeToString()

            if user.get_permissions().value > permission_required.value:
                response.successful = False
                response.data = b'Not enough permissions'
                return response.SerializeToString()

            session = Session.from_key(message.session_key)

            if not session:
                response.successful = False
                response.data = b'Session not available'
                return response.SerializeToString()

            if not session.user == user:
                response.successful = False
                response.data = b'Session not owned by this user'
                return response.SerializeToString()

            if session.until < datetime.datetime.now():
                response.successful = False
                response.data = b'Session expired, restart your client'
                return response.SerializeToString()

        # Select the function from the handler
        try:
            print('Handling message', message)
            successful, result = getattr(handler, message.request)(message)
        except Exception as exc:
            successful = False
            result = b'Exception in user function: ' + repr(exc).encode(
                'utf-8')

        response.successful = successful
        response.data = result
        return response.SerializeToString()
コード例 #8
0
ファイル: handlers.py プロジェクト: troublesomepony/pyledger
    def call(self, message: PyledgerRequest) -> Tuple[bool, bytes]:
        """
        Call handler for contract methods.

        :param message:
        :return:
        """
        if message.contract not in contract_registry:
            return False, 'Contract {} not available'.format(
                message.contract).encode('utf-8')

        contract = contract_registry[message.contract]
        if message.call not in methods(contract):
            return False, 'Method {} not found in contact'.format(
                message.call).encode('utf-8')

        if message.call in method_permissions_registry:
            user = User.from_name(message.user)
            permission_required = method_permissions_registry[message.call]

            if not user:
                if permission_required.value < Permissions.ANON.value:
                    return False, b'Not enough permissions'

            elif not user.check_password(message.password):
                return False, b'Wrong user and/or password'

            elif user.get_permissions().value > permission_required.value:
                return False, b'Not enough permissions'

        # Get the last status of the contract.
        db_contract = Contract.from_name(message.contract)
        status_data = db_contract.last_status()
        status = contract._status_class()
        status.load(status_data.attributes)

        method = contract.__class__.__dict__[message.call]
        method_args = pickle.loads(message.data)

        # Coerce types given the API, since the arguments are pickled
        method_api = api(contract_registry[message.contract])
        signature = method_api[message.call]

        for arg in method_args:
            try:
                method_args[arg] = signature[arg](method_args[arg])
            except KeyError:
                return False, str(
                    ValueError('{} is not a valid key'.format(arg))).encode()

        # Load additional attributes
        status.user = message.user
        status.session = message.session_key

        # Call the method
        result = method(status, **method_args)

        # Persist the new status
        new_status = Status()
        new_status.contract = db_contract
        new_status.attributes = status.dump()
        new_status.when = datetime.datetime.now()

        # This is the status chain standard
        m = hashlib.sha256()
        m.update(status_data.key)
        m.update(new_status.when.isoformat().encode('utf-8'))
        m.update(new_status.attributes)

        new_status.key = m.digest()
        DB.session.add(new_status)
        DB.session.commit()

        return True, pickle.dumps(result)