Exemple #1
0
def update_fortune(session: Session, uuid: str, message: str):
    """
    Update a specific fortune, given a specific UUID.
    """
    
    if uuid is None:
        data = {'message': 'Please select a message.'}
        return Response(data, status=404)
    
    if not message:
        data = {'message': 'Please set a new message.'}
        return Response(data, status=400)
    
    queryset = session.query(Fortune).filter(Fortune.uuid==uuid)
    record = queryset.first()
    
    if not record:
        data = {'message': 'Please select a message.'}
        return Response(data, status=404)
    
    record.message = message
    session.commit()
    
    queryset = session.query(Fortune).filter(Fortune.uuid==uuid)
    record = queryset.first()
    
    return FortuneSerializer(record)
def teacher_details(db: SQLAlchemy, teacher_id: int):
    session = db.session_class()
    db_teacher = session.query(Teacher).get(teacher_id)

    if db_teacher is None:
        return Response({}, status=404)
    data = {"result": TeacherSerializer(db_teacher)}
    return Response(data, status=201)
Exemple #3
0
def patch_task(task_id: int, completed: Boolean) -> Response:
    """
    Mark an specific task referenced by id as completed/incompleted.

    Returns the entire updated serialized object and 200 status code on success.
    """
    if task_id not in tasks:
        return Response({}, status=404)

    tasks[task_id]['completed'] = completed
    return Response(Task(tasks[task_id]), status=200)
Exemple #4
0
def handle_option(id, headers: Headers):
    if settings.get('CORS_OPTIONS_REQUESTS_ENABLED', False) is True:
        headers = {
            'Access-Control-Allow-Origin':
            '*',
            'Access-Control-Allow-Headers':
            headers.get('Access-Control-Request-Headers', '*'),
            'Access-Control-Allow-Methods':
            'GET',
        }
        return Response('', headers=headers)
    return Response('', status_code=405)
Exemple #5
0
    def provide_treasure_map(self, treasure_map_id_as_hex):
        # For now, grab the TreasureMap for the DHT storage.  Soon, no do that.  #TODO!
        treasure_map_id = binascii.unhexlify(treasure_map_id_as_hex)
        headers = {'Content-Type': 'application/octet-stream'}

        try:
            treasure_map_bytes = self.server.storage[digest(treasure_map_id)]
            response = Response(content=treasure_map_bytes, headers=headers)
        except KeyError:
            response = Response("No Treasure Map with ID {}".format(treasure_map_id),
                                status_code=404, headers=headers)

        return response
Exemple #6
0
 def all_known_nodes(self, request: http.Request):
     headers = {'Content-Type': 'application/octet-stream'}
     ursulas_as_bytes = bytes().join(
         bytes(n) for n in self._known_nodes.values())
     ursulas_as_bytes += bytes(self)
     signature = self.stamp(ursulas_as_bytes)
     return Response(bytes(signature) + ursulas_as_bytes, headers=headers)
Exemple #7
0
    def receive_treasure_map(self, treasure_map_id, request: Request):
        from nucypher.policy.models import TreasureMap

        try:
            treasure_map = TreasureMap.from_bytes(
                bytes_representation=request.body, verify=True)
        except TreasureMap.InvalidSignature:
            do_store = False
        else:
            do_store = treasure_map.public_id() == treasure_map_id

        if do_store:
            self.log.info("{} storing TreasureMap {}".format(
                self, treasure_map_id))

            # # # #
            # TODO: Now that the DHT is retired, let's do this another way.
            # self.dht_server.set_now(binascii.unhexlify(treasure_map_id),
            #                         constants.BYTESTRING_IS_TREASURE_MAP + bytes(treasure_map))
            # # # #

            # TODO 341 - what if we already have this TreasureMap?
            self._treasure_map_tracker[keccak_digest(
                binascii.unhexlify(treasure_map_id))] = treasure_map
            return Response(content=bytes(treasure_map), status_code=202)
        else:
            # TODO: Make this a proper 500 or whatever.
            self.log.info(
                "Bad TreasureMap ID; not storing {}".format(treasure_map_id))
            assert False
Exemple #8
0
 def on_error(self,
              response: http.Response,
              x_request_id: http.Header = None) -> http.Response:
     RequestId.set_request_id(x_request_id)
     response.headers["x-request-id"] = RequestId.get_request_id()
     RequestId.clear_request_id()
     return response
Exemple #9
0
    def set_policy(self, id_as_hex, request: Request):
        """
        REST endpoint for setting a kFrag.
        TODO: Instead of taking a Request, use the apistar typing system to type
            a payload and validate / split it.
        TODO: Validate that the kfrag being saved is pursuant to an approved
            Policy (see #121).
        """
        policy_message_kit = UmbralMessageKit.from_bytes(request.body)

        alices_verifying_key = policy_message_kit.sender_pubkey_sig
        alice = self._alice_class.from_public_keys(
            {SigningPower: alices_verifying_key})

        try:
            cleartext = self._verifier(alice, policy_message_kit, decrypt=True)
        except self.InvalidSignature:
            # TODO: Perhaps we log this?
            return Response(status_code=400)

        kfrag = KFrag.from_bytes(cleartext)

        if not kfrag.verify(signing_pubkey=alices_verifying_key):
            raise self.InvalidSignature("{} is invalid".format(kfrag))

        with ThreadedSession(self.db_engine) as session:
            self.datastore.attach_kfrag_to_saved_arrangement(alice,
                                                             id_as_hex,
                                                             kfrag,
                                                             session=session)

        # TODO: Sign the arrangement here.  #495
        return  # TODO: Return A 200, with whatever policy metadata.
Exemple #10
0
    def reencrypt_via_rest(self, id_as_hex, request: http.Request):
        from nucypher.policy.models import WorkOrder  # Avoid circular import
        id = binascii.unhexlify(id_as_hex)
        work_order = WorkOrder.from_rest_payload(id, request.body)
        self.log.info("Work Order from {}, signed {}".format(
            work_order.bob, work_order.receipt_signature))
        with ThreadedSession(self.db_engine) as session:
            kfrag_bytes = self.datastore.get_policy_arrangement(
                id.hex().encode(), session=session).k_frag  # Careful!  :-)
        # TODO: Push this to a lower level.
        kfrag = KFrag.from_bytes(kfrag_bytes)
        cfrag_byte_stream = b""

        for capsule in work_order.capsules:
            # TODO: Sign the result of this.  See #141.
            cfrag = pre.reencrypt(kfrag, capsule)
            self.log.info(
                "Re-encrypting for Capsule {}, made CFrag {}.".format(
                    capsule, cfrag))
            cfrag_byte_stream += VariableLengthBytestring(cfrag)

        # TODO: Put this in Ursula's datastore
        self._work_orders.append(work_order)

        headers = {'Content-Type': 'application/octet-stream'}

        return Response(content=cfrag_byte_stream, headers=headers)
Exemple #11
0
 def get_signing_and_encrypting_public_keys(self):
     """
     REST endpoint for getting both signing and encrypting public keys.
     """
     return Response(
         content=bytes(self.stamp) + bytes(self.public_key(EncryptingPower)),
         content_type="application/octet-stream")
Exemple #12
0
    def provide_treasure_map(self, treasure_map_id_as_hex):
        # For now, grab the TreasureMap for the DHT storage.  Soon, no do that.  #TODO!
        treasure_map_id = binascii.unhexlify(treasure_map_id_as_hex)
        treasure_map_bytes = self.server.storage.get(digest(treasure_map_id))
        headers = {'Content-Type': 'application/octet-stream'}

        return Response(content=treasure_map_bytes, headers=headers)
Exemple #13
0
    def consider_contract(self, hrac_as_hex, request: http.Request):
        # TODO: This actually needs to be a REST endpoint, with the payload
        # carrying the kfrag hash separately.
        from nkms.policy.models import Contract
        contract, deposit_as_bytes = \
            BytestringSplitter(Contract)(request.body, return_remainder=True)
        contract.deposit = deposit_as_bytes

        # contract_to_store = {  # TODO: This needs to be a datastore - see #127.
        #     "alice_pubkey_sig":
        #     "deposit": contract.deposit,
        #     # TODO: Whatever type "deposit" ends up being, we'll need to
        #     # serialize it here.  See #148.
        #     "expiration": contract.expiration,
        # }
        self.keystore.add_policy_contract(contract.expiration.datetime(),
                                          contract.deposit,
                                          hrac=contract.hrac.hex().encode(),
                                          alice_pubkey_sig=contract.alice.stamp
                                          )
        # TODO: Make the rest of this logic actually work - do something here
        # to decide if this Contract is worth accepting.
        return Response(
            b"This will eventually be an actual acceptance of the contract.",
            content_type="application/octet-stream")
Exemple #14
0
def delete_teacher(db: SQLAlchemy, teacher_id: int):
    session = db.session_class()
    db_teacher = session.query(Teacher).get(teacher_id)
    session.delete(db_teacher)
    session.commit()

    data = {}
    return Response(data, status=204)
Exemple #15
0
 def status(self, request: Request):
     headers = {"Content-Type": "text/html", "charset": "utf-8"}
     # TODO: Seems very strange to deserialize *this node* when we can just pass it in.  Might be a sign that we need to rethnk this composition.
     this_node = self._node_class.from_bytes(
         self._node_bytes_caster(), federated_only=self.federated_only)
     content = self._status_template.render(known_nodes=self._node_tracker,
                                            this_node=this_node)
     return Response(content=content, headers=headers)
Exemple #16
0
def add_task(db: SQLAlchemy, definition: TaskDefinition) -> Response:
    """
    Add a new task. It receives its definition as an argument
    and sets an autoincremental id in the Task constructor.

    Returns the created serialized object and 201 status code on success.
    """
    if not definition:
        Response(422,
                 {'error': 'You should provide a definition of the task.'})

    task = TaskModel(definition=definition)
    session = db.session_class()
    session.add(task)
    session.commit()

    return Response(task.serialize(), status=201)
Exemple #17
0
def get_fortune(session: Session, uuid: str):
    """
    Get a specific fortune, given a specific UUID.
    """
    
    if uuid is None:
        data = {'message': 'Please select a message.'}
        return Response(data, status=404)
    
    queryset = session.query(Fortune).filter(Fortune.uuid==uuid)
    record = queryset.first()
    
    if not record:
        data = {'message': 'Please select a message.'}
        return Response(data, status=404)
    
    return FortuneSerializer(record)
Exemple #18
0
def teachers_list(db: SQLAlchemy):
    session = db.session_class()
    teachers = session.query(Teacher).all()
    data = {
        "results": [TeacherSerializer(teacher) for teacher in teachers],
        "count": len(teachers)
    }
    return Response(data, status=200)
Exemple #19
0
    def public_information(self):
        """
        REST endpoint for public keys and address..
        """
        headers = {'Content-Type': 'application/octet-stream'}
        response = Response(content=self._node_bytes_caster(), headers=headers)

        return response
Exemple #20
0
    def provide_treasure_map(self, treasure_map_id):
        headers = {'Content-Type': 'application/octet-stream'}

        try:
            treasure_map = self.treasure_maps[digest(treasure_map_id)]
            response = Response(content=bytes(treasure_map), headers=headers)
            self.log.info("{} providing TreasureMap {}".format(
                self, treasure_map_id))
        except KeyError:
            self.log.info("{} doesn't have requested TreasureMap {}".format(
                self, treasure_map_id))
            response = Response(
                "No Treasure Map with ID {}".format(treasure_map_id),
                status_code=404,
                headers=headers)

        return response
Exemple #21
0
def add_teacher(db: SQLAlchemy, name: str):
    session = db.session_class()
    db_teacher = Teacher(name=name)
    session.add(db_teacher)
    session.commit()

    db_teacher = session.query(Teacher).order_by("-id").first()
    data = {"created": TeacherSerializer(db_teacher)}
    return Response(data, status=201)
Exemple #22
0
    def node_metadata_exchange(self, request: Request,
                               query_params: QueryParams):
        # If these nodes already have the same fleet state, no exchange is necessary.
        learner_fleet_state = query_params.get('fleet')
        if learner_fleet_state == self._node_tracker.checksum:
            self.log.debug(
                "Learner already knew fleet state {}; doing nothing.".format(
                    learner_fleet_state))
            headers = {'Content-Type': 'application/octet-stream'}
            payload = self._node_tracker.snapshot()
            signature = self._stamp(payload)
            return Response(bytes(signature) + payload,
                            headers=headers,
                            status_code=204)

        nodes = self._node_class.batch_from_bytes(
            request.body,
            federated_only=self.federated_only,  # TODO: 466
        )

        # TODO: This logic is basically repeated in learn_from_teacher_node and remember_node.  Let's find a better way.  555
        for node in nodes:

            if node in self._node_tracker:
                continue  # TODO: 168 Check version and update if required.

            @crosstown_traffic()
            def learn_about_announced_nodes():
                try:
                    certificate_filepath = node.get_certificate_filepath(
                        certificates_dir=self._certificate_dir
                    )  # TODO: integrate with recorder?
                    node.save_certificate_to_disk(
                        directory=self._certificate_dir, force=True)
                    node.verify_node(
                        self.network_middleware,
                        accept_federated_only=self.federated_only,  # TODO: 466
                        certificate_filepath=certificate_filepath)
                except node.SuspiciousActivity:
                    # TODO: Account for possibility that stamp, rather than interface, was bad.
                    message = "Suspicious Activity: Discovered node with bad signature: {}.  " \
                              " Announced via REST."  # TODO: Include data about caller?
                    self.log.warn(message)
                    self._suspicious_activity_tracker['vladimirs'].append(
                        node
                    )  # TODO: Maybe also record the bytes representation separately to disk?
                except Exception as e:
                    self.log.critical(str(e))
                    raise  # TODO
                else:
                    self.log.info("Previously unknown node: {}".format(
                        node.checksum_public_address))
                    self._node_recorder(node)

        # TODO: What's the right status code here?  202?  Different if we already knew about the node?
        return self.all_known_nodes(request)
Exemple #23
0
def get_random_fortune(session: Session):
    """
    Get a random fortune from the queryset.
    """
    
    queryset = session.query(Fortune).all()
    record = random.choice(queryset)
    data = FortuneSerializer(record)
    
    return Response(data, status=200)
Exemple #24
0
    def all_known_nodes(self, request: Request):
        headers = {'Content-Type': 'application/octet-stream'}
        payload = self._node_tracker.snapshot()
        ursulas_as_bytes = bytes().join(bytes(n) for n in self._node_tracker)
        ursulas_as_bytes += self._node_bytes_caster()

        payload += ursulas_as_bytes

        signature = self._stamp(payload)
        return Response(bytes(signature) + payload, headers=headers)
Exemple #25
0
    def finalize_wsgi(self, response: Response,
                      start_response: WSGIStartResponse):
        if self.debug and response.exc_info is not None:
            exc_info = response.exc_info
            raise exc_info[0].with_traceback(exc_info[1], exc_info[2])

        response.headers = [(cap(x[0], '-'), x[1]) for x in response.headers]
        start_response(RESPONSE_STATUS_TEXT[response.status_code],
                       list(response.headers), response.exc_info)
        return [response.content]
 def finalize_response(self, response: Response) -> Response:
     """
     Inject cors headers and finalize.
     """
     response = super().finalize_response(response)
     content, status, headers, content_type = response
     headers['Access-Control-Allow-Origin'] = '*'
     headers['Access-Control-Allow-Headers'] = 'Origin, Content-Type, Authorization'
     headers['Access-Control-Allow-Credentials'] = 'true'
     headers['Access-Control-Allow-Methods'] = 'GET'
     return Response(content, status, headers, content_type)
Exemple #27
0
def create_fortune(session: Session, message: str):
    """
    Create a new fortune.
    """
    
    fortune = Fortune(message=message)
    session.add(fortune)
    session.commit()
    
    data = FortuneSerializer(fortune)
    return Response(data, status=201)
Exemple #28
0
    def get_signing_and_encrypting_public_keys(self):
        """
        REST endpoint for getting both signing and encrypting public keys.
        """

        headers = {'Content-Type': 'application/octet-stream'}
        response = Response(content=bytes(self.public_key(SigningPower)) +
                            bytes(self.public_key(EncryptingPower)),
                            headers=headers)

        return response
Exemple #29
0
def add_task(definition: TaskDefinition) -> Response:
    """
    Add a new task. It receives its definition as an argument
    and sets an autoincremental id in the Task constructor.

    Returns the created serialized object and 201 status code on success.

    TODO:
     - maybe this counter could be implemented as an injectable component?
    """
    if not definition:
        Response(422, {'error': 'You should provide a definition of the task.'})

    id = counter()
    tasks[id] = {
        'id': id,
        'definition': definition,
        'completed': False,
    }
    return Response(Task(tasks[id]), status=201)
Exemple #30
0
 def on_response(self, session: Session, response: http.Response):
     session.save()
     if session.needs_cookie:
         cookie = dump_cookie(
             session.settings.cookie_name,
             session.session_id,
             max_age=session.settings.cookie_age
             if session.expires is NOT_SET else session.expires,
             domain=session.settings.cookie_domain,
             path=session.settings.cookie_path,
             secure=session.settings.cookie_secure,
             httponly=session.settings.cookie_httponly,
         )
         response.headers['set-cookie'] = cookie