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()
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
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))
def on_close(self): if self.closing: return try: print "closing" self.do_close() except Exception: capture_exception() raise
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()
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
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()
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()
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()
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()
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
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()