Ejemplo n.º 1
0
 def on_message(self, msg):
     try:
         if getattr(self, 'socket', None):
             print "closing old socket"
             self.loop.add_callback(self.do_close)
             return
         if msg.startswith('discussion:') and self.valid:
             self.discussion = msg.split(':', 1)[1]
         if msg.startswith('token:') and self.valid:
             try:
                 self.token = decode_token(
                     msg.split(':', 1)[1], TOKEN_SECRET)
                 self.userId = 'local:AgentProfile/' + str(
                     self.token['userId'])
             except TokenInvalid:
                 pass
         if self.token and self.discussion:
             # Check if token authorizes discussion
             r = requests.get(
                 '%s/api/v1/discussion/%s/permissions/read/u/%s' %
                 (SERVER_URL, self.discussion, self.token['userId']))
             print r.text
             if r.text != 'true':
                 return
             self.socket = context.socket(zmq.SUB)
             self.socket.connect(INTERNAL_SOCKET)
             self.socket.setsockopt(zmq.SUBSCRIBE, '*')
             self.socket.setsockopt(zmq.SUBSCRIBE, str(self.discussion))
             self.loop = zmqstream.ZMQStream(self.socket, io_loop=io_loop)
             self.loop.on_recv(self.on_recv)
             print "connected"
             self.send('[{"@type":"Connection"}]')
     except Exception:
         capture_exception()
         self.do_close()
Ejemplo n.º 2
0
def copy_discussion(source_config, dest_config, source_slug, dest_slug,
                    delete=False, debug=False, permissions=None):
    if (session_maker_is_initialized() and abspath(source_config) == get_config()["__file__"]):
        # not running from script
        dest_session = get_session_maker()()
        dest_metadata = get_metadata()
    else:
        dest_metadata, dest_session = engine_from_settings(
            dest_config, True)
    dest_tables = dest_metadata.sorted_tables
    if source_config != dest_config:
        from assembl.lib.sqla import _session_maker
        temp = _session_maker
        assert temp == dest_session
        source_metadata, source_session = engine_from_settings(
            source_config, False)
        source_tables_by_name = {
            table.name: table.tometadata(source_metadata, source_metadata.schema)
            for table in dest_tables
        }
        _session_maker = dest_session
    else:
        source_metadata, source_session = dest_metadata, dest_session
    try:
        init_key_for_classes(dest_session)
        from assembl.models import Discussion
        discussion = source_session.query(Discussion).filter_by(
            slug=source_slug).one()
        assert discussion, "No discussion named " + source_slug
        permissions = [x.split('+') for x in permissions or ()]
        for (role, permission) in permissions:
            assert role in SYSTEM_ROLES
            assert permission in ASSEMBL_PERMISSIONS
        existing = dest_session.query(Discussion).filter_by(slug=dest_slug).first()
        if existing:
            if delete:
                print("deleting", dest_slug)
                with transaction.manager:
                    delete_discussion(dest_session, existing.id)
            else:
                print("Discussion", dest_slug, end=' ')
                print("already exists! Add -d to delete it.")
                exit(0)
        from assembl.models import Role, Permission, DiscussionPermission
        with dest_session.no_autoflush:
            copy = clone_discussion(
                source_session, discussion.id, dest_session, dest_slug)
            for (role, permission) in permissions:
                role = dest_session.query(Role).filter_by(name=role).one()
                permission = dest_session.query(Permission).filter_by(
                    name=permission).one()
                # assumption: Not already defined.
                dest_session.add(DiscussionPermission(
                    discussion=copy, role=role, permission=permission))
    except Exception:
        traceback.print_exc()
        if debug:
            pdb.post_mortem()
        capture_exception()
    return dest_session
Ejemplo n.º 3
0
def error_view(exc, request):
    # from traceback import format_exc
    from datetime import datetime
    capture_exception(getattr(request, "exc_info", None))
    return HTTPInternalServerError(
        explanation=
        "Sorry, Assembl had an internal issue and you have to reload. Please send this to a discussion administrator.",
        detail=datetime.utcnow().isoformat() + "\n" + repr(request.exception))
Ejemplo n.º 4
0
 def on_close(self):
     if self.closing:
         return
     try:
         print "closing"
         self.do_close()
     except Exception:
         capture_exception()
         raise
Ejemplo n.º 5
0
 async def on_message(self, msg):
     try:
         if msg.startswith('discussion:') and self.valid:
             self.discussion = msg.split(':', 1)[1]
             log.debug('discussion_id: %s', self.discussion)
         if msg.startswith('token:') and self.valid:
             try:
                 self.raw_token = msg.split(':', 1)[1]
                 self.token = decode_token(self.raw_token,
                                           self.token_secret)
                 if self.token['userId'] != Everyone:
                     self.userId = 'local:Agent/' + str(
                         self.token['userId'])
                 else:
                     self.userId = Everyone
                 log.info('userId: %s', self.userId)
             except TokenInvalid:
                 pass
         if self.token and self.discussion:
             # Check if token authorizes discussion
             async with self.http_client.get(
                     '%s/api/v1/discussion/%s/permissions/Conversation.R/u/%s'
                     %
                 (self.server_url, self.discussion, self.token['userId']),
                     headers={"Accept": "application/json"}) as resp:
                 text = await resp.text()
             log.debug(text)
             if text != 'true':
                 return
             log.info("connected")
             if self.userId == Everyone:
                 self.roles = {Everyone}
             else:
                 async with self.http_client.get(
                         '%s/api/v1/discussion/%s/roles/allfor/%s' %
                     (self.server_url, self.discussion,
                      self.token['userId']),
                         headers={"Accept": "application/json"}) as resp:
                     text = await resp.text()
                     self.roles = set(json.loads(text))
                     self.roles.add(Everyone)
                     self.roles.add(Authenticated)
                     self.roles.add('local:Agent/' +
                                    str(self.token['userId']))
             self.task = self.loop.create_task(self.connect())
             self.session.send('[{"@type":"Connection"}]')
             if self.token and self.raw_token and self.discussion and self.userId != Everyone:
                 async with self.http_client.post(
                         '%s/data/Discussion/%s/all_users/%d/connecting' %
                     (self.server_url, self.discussion,
                      self.token['userId']),
                         data={'token': self.raw_token}) as resp:
                     await resp.text()
     except Exception:
         capture_exception()
         await self.close()
Ejemplo n.º 6
0
 def on_close(self):
     if self.closing:
         return
     try:
         log.info("closing")
         if self.raw_token and self.discussion and self.userId != Everyone:
             requests.post(
                 '%s/data/Discussion/%s/all_users/%d/disconnecting' %
                 (SERVER_URL, self.discussion, self.token['userId']),
                 data={'token': self.raw_token})
         self.do_close()
     except Exception:
         capture_exception()
         raise
Ejemplo n.º 7
0
    def new_error(self, reader_error, status=None, expected=True):
        import traceback
        from assembl.models import ContentSource
        log.error(traceback.format_exc())
        if not expected:
            capture_exception()
        status = status or reader_error.status
        if status != self.last_error_status:
            # Counter-intuitive, but either lighter or more severe errors
            # reset the count.
            self.error_count = 1
        elif status == self.last_error_status:
            self.error_count += 1
            # escalate errors with repetition
            if status == ReaderStatus.TRANSIENT_ERROR:
                if self.error_count > self.transient_error_numlimit:
                    status = ReaderStatus.CLIENT_ERROR
                    self.error_count = 1
            elif status == ReaderStatus.CLIENT_ERROR:
                if self.error_count > self.client_error_numlimit:
                    status = ReaderStatus.IRRECOVERABLE_ERROR
                    self.error_count = 1
            else:
                assert False
        if status == ReaderStatus.TRANSIENT_ERROR:
            error_backoff = self.transient_error_backoff
        elif status == ReaderStatus.CLIENT_ERROR:
            error_backoff = self.client_error_backoff
        elif status == ReaderStatus.IRRECOVERABLE_ERROR:
            error_backoff = self.irrecoverable_error_backoff
        else:
            assert False
        # double backoff every time
        error_backoff *= 2 ** (self.error_count - 1)

        self.last_error_status = status
        self.source.db.rollback()
        self.refresh_source()
        self.source.connection_error = status.value
        self.source.error_description = str(reader_error)
        if (status > ReaderStatus.TRANSIENT_ERROR and
                self.status != ReaderStatus.SHUTDOWN):
            self.set_status(status)
            self.reimporting = False
        self.error_backoff_until = datetime.utcnow() + error_backoff
        self.source.error_backoff_until = self.error_backoff_until
        self.source.db.commit()
        self.refresh_source()
Ejemplo n.º 8
0
 def on_recv(self, data):
     try:
         data = data[-1]
         if b'@private' in data:
             jsondata = json.loads(data)
             jsondata = [
                 x for x in jsondata
                 if x.get('@private', self.userId) == self.userId
             ]
             if not jsondata:
                 return
             data = json.dumps(jsondata)
         self.send(data)
     except Exception:
         capture_exception()
         self.do_close()
Ejemplo n.º 9
0
 def on_message(self, msg):
     try:
         if getattr(self, 'socket', None):
             log.info("closing old socket")
             self.loop.add_callback(self.do_close)
             return
         if msg.startswith('discussion:') and self.valid:
             self.discussion = msg.split(':', 1)[1]
         if msg.startswith('token:') and self.valid:
             try:
                 self.raw_token = msg.split(':', 1)[1]
                 self.token = decode_token(self.raw_token, TOKEN_SECRET)
                 if self.token['userId'] != Everyone:
                     self.userId = 'local:Agent/' + str(
                         self.token['userId'])
                 else:
                     self.userId = Everyone
             except TokenInvalid:
                 pass
         if self.token and self.discussion:
             # Check if token authorizes discussion
             r = requests.get(
                 '%s/api/v1/discussion/%s/permissions/read/u/%s' %
                 (SERVER_URL, self.discussion, self.token['userId']),
                 headers={"Accept": "application/json"})
             log.debug(r.text)
             if r.text != 'true':
                 return
             self.socket = context.socket(zmq.SUB)
             self.socket.connect(INTERNAL_SOCKET)
             self.socket.setsockopt(zmq.SUBSCRIBE, b'*')
             self.socket.setsockopt(
                 zmq.SUBSCRIBE, native_str_to_bytes(str(self.discussion)))
             self.loop = zmqstream.ZMQStream(self.socket, io_loop=io_loop)
             self.loop.on_recv(self.on_recv)
             log.info("connected")
             self.send('[{"@type":"Connection"}]')
             if self.token and self.raw_token and self.discussion and self.userId != Everyone:
                 requests.post(
                     '%s/data/Discussion/%s/all_users/%d/connecting' %
                     (SERVER_URL, self.discussion, self.token['userId']),
                     data={'token': self.raw_token})
     except Exception:
         capture_exception()
         self.do_close()
Ejemplo n.º 10
0
 async def on_recv(self, data):
     try:
         data = data[-1].decode('utf-8')
         if ("r:sysadmin" not in self.roles) and '@private' in data:
             jsondata = json.loads(data)
             allowed = []
             for x in jsondata:
                 if '@private' in x:
                     private = x['@private']
                     if private is not None and not self.roles.intersection(
                             set(private)):
                         continue
                 allowed.append(x)
             if not allowed:
                 return
             data = json.dumps(allowed)
         self.session.send(data)
         log.debug('sent:' + data)
     except Exception:
         capture_exception()
         await self.close()
Ejemplo n.º 11
0
        user_settings={"websocket_allow_origin": SERVER_URL})
    routes = sockjs_router.urls
    web_app = web.Application(routes, debug=False)

    def term(*_ignore):
        web_server.stop()
        io_loop.add_timeout(time.time() + 0.3, io_loop.stop)

    signal.signal(signal.SIGTERM, term)

    web_server = HTTPServer(web_app)
    web_server.listen(websocket_port)

    try:
        if changes_socket.startswith('ipc://'):
            sname = changes_socket[6:]
            for i in range(5):
                if exists(sname):
                    break
                sleep(0.1)
            else:
                raise RuntimeError("could not create socket " + sname)
            if not access(sname, R_OK | W_OK):
                raise RuntimeError(sname + " cannot be accessed")
        io_loop.start()
    except KeyboardInterrupt:
        term()
    except Exception:
        capture_exception()
        raise
Ejemplo n.º 12
0
        permissions = [x.split('+') for x in args.permissions]
        for (role, permission) in permissions:
            assert role in SYSTEM_ROLES
            assert permission in ASSEMBL_PERMISSIONS
        existing = to_session.query(Discussion).filter_by(slug=new_slug).first()
        if existing:
            if args.delete:
                print "deleting", new_slug
                with transaction.manager:
                    delete_discussion(to_session, existing.id)
            else:
                print "Discussion", new_slug,
                print "already exists! Add -d to delete it."
                exit(0)
        with transaction.manager:
            from assembl.models import Role, Permission, DiscussionPermission
            copy = clone_discussion(
                from_session, discussion.id, to_session, new_slug)
            for (role, permission) in permissions:
                role = to_session.query(Role).filter_by(name=role).one()
                permission = to_session.query(Permission).filter_by(
                    name=permission).one()
                # assumption: Not already defined.
                to_session.add(DiscussionPermission(
                    discussion=copy, role=role, permission=permission))
    except Exception:
        traceback.print_exc()
        if args.debug:
            pdb.post_mortem()
        capture_exception()