Пример #1
0
def delete_star(id):
    """ Delete a star """
    # TODO: Should only accept POST instead of GET
    # TODO: Check permissions!

    # Load instance and creator persona
    s = Star.query.get(id)

    if s is None:
        abort(404)

    # Create deletion request
    data = dict({
        "object_type": "Star",
        "object_id": s.id,
        "change": "delete",
        "change_time": datetime.datetime.now().isoformat()
    })

    message = Message(message_type="change_notification",
                      data=json.dumps(data))
    if s.creator.sign_private is not None:
        message.sign(s.creator)

    # Delete instance from db
    db.session.delete(s)
    db.session.commit()

    # Distribute deletion request
    star_deleted.send(delete_star, message=message)

    app.logger.info("Deleted star {}".format(id))

    return redirect(url_for('debug'))
Пример #2
0
def find_people():
    """Search for and follow people"""
    form = FindPeopleForm(request.form)
    found = None
    error = None

    if request.method == 'POST' and form.validate():
        # Compile message
        email = request.form['email']
        email_hash = sha256(email).hexdigest()
        app.logger.info("Searching for {}".format(email))
        data = {"email_hash": email_hash}
        message = Message(message_type='find_people', data=data)

        # Send message
        headers = {"Content-Type": "application/json"}
        url = "http://{host}/find-people".format(
            host=app.config['LOGIN_SERVER'])
        r = requests.post(url, message.json(), headers=headers)

        # Read response
        try:
            resp = r.json()
        except ValueError:
            app.logger.info("Error retrieving results: {}".format(r.data))
            flash("Server error: Please try again.")

        # TODO: Use message_errors() instead
        if resp and resp['data'] and 'found' in resp['data']:
            found = resp['data']['found']

            for p in found:
                if Persona.query.get(p['persona_id']) is None:
                    app.logger.info("Storing new Persona {}".format(
                        p['persona_id']))
                    p_new = Persona(id=p['persona_id'],
                                    username=p['username'],
                                    email=email,
                                    crypt_public=p['crypt_public'],
                                    sign_public=p['sign_public'])
                    db.session.add(p_new)
                    db.session.commit()
        else:
            error = "No record for {}. Check the spelling!".format(email)

    return render_template('find_people.html',
                           form=form,
                           found=found,
                           error=error)
Пример #3
0
    def register_persona(self, persona):
        """ Register a persona on the login server """
        self.logger.info(
            "Registering persona {} with login server".format(persona))

        # Create request
        data = {
            'persona_id': persona.id,
            'username': persona.username,
            'email_hash': persona.get_email_hash(),
            'sign_public': persona.sign_public,
            'crypt_public': persona.crypt_public,
            'reply_to': app.config['SYNAPSE_PORT']
        }
        message = Message('create_persona', data)

        url = "http://{host}/p/{persona}/create".format(
            host=app.config['LOGIN_SERVER'], persona=persona.id)
        response, errors = self.server_request(url, message=message)

        if errors:
            self.logger.error("Error creating account on server:\n{}".format(
                "\n".join(errors)))

        # Evaluate response
        if 'session_id' in response['data']:
            self.logger.info("Registered {} with server.".format(persona))
            self.sessions[persona.id] = {
                'session_id': response['data']['session_id'],
                'timeout': response['data']['timeout'],
            }
            self.update_peer_list(persona)
            self.queue_keepalive(persona)
Пример #4
0
 def request_inventory_operator(self, address):
     """Request an starmap from the soma at address and reschedule the process in 180 seconds"""
     self.logger.info("Requesting starmap from {}".format(
         self.source_format(address)))
     m = Message("starmap_request", data=None)
     self.message_pool.spawn(self.send_message, address, m)
     self.message_pool.spawn_later(180, self.send_message, address, m)
Пример #5
0
class MessageTest(unittest.TestCase):
	
	def setUp(self):
		self.uuid = uuid4().hex
		self.change_time = datetime.datetime.now().isoformat()
		self.message_type = "change_notification"
		
		data = dict({
            "object_type": "Persona",
            "object_id": self.uuid,
            "change": "insert",
            "change_time": self.change_time
		})

		self.message = Message(message_type=self.message_type, data=data)
	
	def test_json(self):
		repr = self.message.json()
		
		#jsonification added timestamp
		self.assertTrue("timestamp" in repr)
		self.assertTrue(self.change_time in repr)
		
		#json encoding complete
		self.assertTrue("message_type" in repr)
		self.assertTrue(self.message_type in repr)
		
		self.assertTrue("data" in repr)
		self.assertTrue("Persona" in repr)
		self.assertTrue(self.uuid in repr)
		
		self.assertTrue("reply_to" in repr)
		
		# jsonification sensitive to new attributes
		self.assertFalse("signature" in repr)
		self.message.send_attributes.append("signature")
		self.message.signature="sincerly yours"
		
		repr = self.message.json()
		self.assertTrue("signature" in repr)
		
	
	def test_read(self):
		pass
		
	def test_sign(self):
		pass
Пример #6
0
    def on_star_created(self, sender, message):
        """Add new stars to starmap and send notification message"""
        star = message
        data = dict({
            "object_type": "Star",
            "object_id": star.id,
            "change": "insert",
            "change_time": star.modified.isoformat()
        })

        message = Message(message_type="change_notification", data=data)
        message.sign(star.creator)

        self.logger.info("[{sender}] Distributing {msg}".format(sender=sender,
                                                                msg=message))
        self.distribute_message(message)

        orb = Orb("Star", star.id, star.modified, star.creator.id)
        self.starmap.add(orb)  # Add to starmap
Пример #7
0
    def handle_starmap_request(self, message, address):
        """ Send starmap of published objects to the given address """
        data = {
            'soma_id': app.config['SOMA_ID'],
            'starmap': self.create_starmap()
        }
        m = Message("starmap", data)

        self.logger.info("Sending requested starmap of {} orbs to {}".format(
            len(data), self.source_format(address)))
        self.message_pool.spawn(self.send_message, address, m)
Пример #8
0
    def handle_message(self, data, address):
        """Parse received Message objects and pass them on to the correct handler"""

        # Try parsing the message
        try:
            message = Message.read(data)
        except KeyError, e:
            self.logger.error(
                "[{source}] Message malformed (missing {key})".format(
                    source=self.source_format(address), key=e))
            return
Пример #9
0
	def setUp(self):
		self.uuid = uuid4().hex
		self.change_time = datetime.datetime.now().isoformat()
		self.message_type = "change_notification"
		
		data = dict({
            "object_type": "Persona",
            "object_id": self.uuid,
            "change": "insert",
            "change_time": self.change_time
		})

		self.message = Message(message_type=self.message_type, data=data)
Пример #10
0
    def request_object(self, object_type, object_id, address):
        """ Request an object from a peer """
        self.logger.info(
            "Requesting <{object_type} {object_id}> from {source}".format(
                object_type=object_type,
                object_id=object_id[:6],
                source=self.source_format(address)))

        # Construct request
        data = {"object_type": object_type, "object_id": object_id}
        message = Message("object_request", data)

        # Send request
        self.send_message(address, message)
Пример #11
0
    def login(self, persona):
        """ Create session at login server """

        # Check current state
        url = "http://{host}/p/{persona_id}/".format(
            host=app.config['LOGIN_SERVER'], persona_id=persona.id)
        resp, errors = self.server_request(url)

        if errors:
            self.logger.error("Login failed with errors:\n{}".format(
                "\n".join(errors)))
            if not resp:
                return

            # Check error list for code 3 (persona not found) and register new persona if found
            if 3 in [t[0] for t in resp['data']['errors']]:
                self.register_persona(persona)
                return

        # Persona is already logged in
        elif 'session_id' in resp['data']:
            self.logger.info("Persona {} already logged in.".format(persona))
            self.sessions[persona.id] = {
                'session_id': resp['data']['session_id'],
                'timeout': resp['data']['timeout']
            }
            self.queue_keepalive(persona)
            return

        # Do login
        if 'auth' in resp['data']:
            data = {
                'auth_signed': persona.sign(resp['data']['auth']),
                'reply_to': app.config['SYNAPSE_PORT']
            }
            r, errors = self.server_request(url, Message('session', data))

            if errors:
                self.logger.error("Login failed:\n{}".format(
                    "\n".join(errors)))
            else:
                self.sessions[persona.id] = {
                    'session_id': r['data']['session_id'],
                    'timeout': r['data']['timeout'],
                }
                self.logger.info("Persona {} logged in until {}".format(
                    persona, dateutil_parse(r['data']['timeout'])))
                self.queue_keepalive(persona)
                self.update_peer_list(persona)
Пример #12
0
def create_persona():
    """ Render page for creating new persona """
    from uuid import uuid4

    form = Create_persona_form()
    if form.validate_on_submit():
        # This is a unique ID which identifies the persona across all contexts
        uuid = uuid4().hex

        # Save persona to DB
        p = Persona(uuid, request.form['name'], request.form['email'])

        # Create keypairs
        p.generate_keys(cache.get('password'))

        # TODO: Error message when user already exists
        db.session.add(p)
        db.session.commit()

        # Distribute "birth" certificate
        data = dict({
            "object_type": "Persona",
            "object_id": uuid,
            "change": "insert",
            "change_time": p.modified.isoformat()
        })

        message = Message(message_type="change_notification", data=data)
        persona_created.send(create_persona, message=message)

        flash("New persona {} created!".format(p.username))
        return redirect(url_for('persona', id=uuid))

    return render_template('create_persona.html',
                           form=form,
                           next=url_for('create_persona'))
Пример #13
0
    def handle_object_request(self, message, address):
        """ Serve an object to address in response to a request """
        object_id = message.data["object_id"]
        object_type = message.data["object_type"]

        # Load object
        obj = None
        if object_type == "Star":
            obj = Star.query.get(object_id)
        elif object_type == "Persona":
            obj = Persona.query.get(object_id)

        if obj is None:
            # TODO: Serve error message
            self.logger.error(
                "Requested object <{type} {id}> not found".format(
                    type=object_type, id=object_id[:6]))
            self.socket.sendto(str(), address)
            return

        # Construct response
        data = {
            "object": obj.export(exclude=["sign_private, crypt_private"]),
            "object_type": object_type
        }
        message = Message("object", data)

        # Sign message
        if object_type == "Star" and obj.creator.sign_private is not None:
            message.sign(obj.creator)
        elif object_type == "Persona" and obj.sign_private is not None:
            message.sign(obj)

        # Send response
        self.send_message(address, message)
        self.logger.info("Sent {object_type} {object_id} to {address}".format(
            object_type=object_type,
            object_id=object_id,
            address=self.source_format(address)))
Пример #14
0
 def request_inventory(self, address):
     """Request an starmap from the soma at address"""
     self.logger.info("Requesting starmap from {}".format(
         self.source_format(address)))
     m = Message("starmap_request", data=None)
     self.message_pool.spawn(self.send_message, address, m)
Пример #15
0
def create_star():
    from uuid import uuid4
    """ Create a new star """

    # Load author drop down contents
    controlled_personas = Persona.query.filter(
        Persona.sign_private != None).all()
    creator_choices = [(p.id, p.username) for p in controlled_personas]
    active_persona = Persona.query.get(session['active_persona'])

    form = Create_star_form(default_creator=session['active_persona'])
    form.creator.choices = creator_choices
    if form.validate_on_submit():
        uuid = uuid4().hex

        new_star = Star(uuid, request.form['text'], request.form['creator'])
        db.session.add(new_star)
        db.session.commit()

        flash('New star created!')
        app.logger.info('Created new star {}'.format(new_star.id))

        if 'picture' in request.files and request.files[
                'picture'].filename != "":
            # compute hash
            picture_hash = sha256(
                request.files['picture'].stream.read()).hexdigest()
            request.files['picture'].stream.seek(0)

            # create or get planet
            planet = Planet.query.filter_by(id=picture_hash[:32]).first()
            if not planet:
                app.logger.info("Storing submitted file")
                filename = attachments.save(request.files['picture'],
                                            folder=picture_hash[:2],
                                            name=picture_hash[2:] + ".")
                planet = PicturePlanet(id=picture_hash[:32],
                                       filename=os.path.join(
                                           attachments.name, filename))
                db.session.add(planet)

            # attach to star
            new_star.planets.append(planet)

            # commit
            db.session.add(new_star)
            db.session.commit()
            app.logger.info("Attached planet {} to new star".format(planet))

        if 'link' in request.form and request.form['link'] != "":
            link_hash = sha256(request.form['link']).hexdigest()[:32]
            planet = Planet.query.filter_by(id=link_hash).first()
            if not planet:
                app.logger.info("Storing new Link")
                planet = LinkPlanet(id=link_hash, url=request.form['link'])
                db.session.add(planet)

            new_star.planets.append(planet)
            db.session.add(new_star)
            db.session.commit()
            app.logger.info("Attached planet {} to new star".format(planet))

        # Create certificate
        data = dict({
            "object_type": "Star",
            "object_id": uuid,
            "change": "insert",
            "change_time": new_star.modified.isoformat()
        })

        message = Message(message_type="change_notification", data=data)
        message.sign(new_star.creator)

        star_created.send(create_star, message=new_star)

        return redirect(url_for('star', id=uuid))
    return render_template('create_star.html',
                           form=form,
                           active_persona=active_persona)