def post(self): if not self.user.is_super_admin: raise HttpErrorException.not_found() if self.json_request.get('clear_indexes'): orgs = Organization.query().fetch() for org in orgs: indexes = org.get_indexes() for index in indexes: ttindex.clear_index(index) users = User.query(User.organization == None).fetch() for user in users: indexes = user.get_indexes() for index in indexes: ttindex.clear_index(index) project_ids = self.json_request.get('project_ids') if project_ids: if project_ids == 'all': self.project_keys = Project.query().fetch(keys_only=True) else: if type(project_ids) is not list: raise HttpErrorException.bad_request( 'project ids must be list') for pro_id in project_ids: pro = Project.get_by_id(pro_id) if not pro: raise HttpErrorException.bad_request( 'invalid project id given: ' + str(pro_id)) self.project_keys.append(pro.key) t = background_thread.BackgroundThread(target=self.index_project) t.start()
def post(self, project_id=None): self.get_channel_token() if not project_id and not Project.valid_id(project_id): raise HttpErrorException.bad_request('no project id') self.project = Project.get_by_id(project_id) if not self.project: raise HttpErrorException.bad_request('invalid project id') self.get_analytic_session() if self.json_request.get('permission'): self._add_perm() if not self.json_request.get('permission') and self.json_request.get( 'group_id'): self._rm_perm() if self.json_request.get('remove_group'): self._remove_group() if self.json_request.get('add_attribute'): self._add_attribute() if self.json_request.get('title'): self._set_title() if self.json_request.get('up_vote'): self._up_vote() if self.json_request.get('down_vote'): self._down_vote() if self.json_request.get('shared'): self._shared() self.project.pw_modified_ts = datetime.datetime.now() self.project.put() self.user.put() self.write_json_response(self.project.to_dict(self.user))
def delete(self, project_id=None): if self.request.get('token_id') is None: raise HttpErrorException.bad_request('no token id') self.user.current_token_id = self.request.get('token_id') if not project_id and not Project.valid_id(project_id): raise HttpErrorException.bad_request('no project id') project = Project.get_by_id(project_id) if not project: raise HttpErrorException.bad_request('invaild project id') if not project.has_permission_delete(self.user): raise HttpErrorException.forbidden() trans = Transaction(action='pro_del', user=self.user.key, artifact=project.key, project=project.key) trans.put() self.get_channel_token() channel_tokens = ChannelToken.get_by_project_key( project.key, self.user_channel_token) channel_tokens = ChannelToken.remove_unauthorized_users( channel_tokens, [project]) message = { 'user': self.get_user_channel_data(), 'transaction': trans.to_dict(self.user) } ChannelToken.broadcast_message(channel_tokens, message) project.delete(self.user)
def create_new_project(self, title): doc_perm = Permission(key=Permission.create_key(), permissions=Permission.init_perm_struct( Document.operations_list)) pro_perm = Permission(key=Permission.create_key(), permissions=Permission.init_perm_struct( Project.operations_list)) self.document = Document(key=Document.create_key(), title='Outline', owner=[self.user.key], permissions=doc_perm.key, subtitle='Outline', author=self.user.username, version='v0.1', date=str(datetime.datetime.now().year), copyright_text='', description='') self.project = Project(key=Project.create_key(), title=title, distilled_document=self.document.key, permissions=pro_perm.key, owner=[self.user.key]) self.document.project = self.project.key self.document.parent_perms.append(pro_perm.key) if self.user.in_org(): self.document.organization = self.user.organization self.project.organization = self.user.organization doc_perm.artifact = self.document.key doc_perm.project = self.project.key pro_perm.artifact = self.project.key pro_perm.project = self.project.key ndb.put_multi([doc_perm, pro_perm, self.document, self.project])
def get(self): if not self.request.get('project', None): raise HttpErrorException.bad_request('invalid project id') project = Project.get_by_id(self.request.get('project')) if not project: raise HttpErrorException.bad_request('invalid project id') channel_id = server.create_uuid() client_auth_token = auth.create_custom_token(self.user.key.id()) color = self.get_previous_color(project) if not color: color = ChannelToken.generate_color() channel_token = ChannelToken( key=ChannelToken.create_key(channel_id), project=project.key, user=self.user.key, color=color, ) channel_token.set_status(True) channel_token.send_message({'channel_op': 'ping'}) channel_token.put() self.write_json_response({ 'channel_id': channel_id, 'auth_token': client_auth_token, })
def get(self): self._create_analytic_session() projects = Project.get_user_projects(self.user) debug_level = 0 if os.environ.get('SERVER_SOFTWARE', '').startswith('Development'): debug_level = 3 try: debug_level = int(self.request.get('debug_level', debug_level)) except ValueError: debug_level = 0 template_data = { 'title': 'thinkTank', 'display_name': self.user.display_name, 'nav_bar_title': 'thinkTank', 'projects': projects, 'data': { 'page': 'home', 'user': json.dumps(self.user.to_dict(user=self.user)), 'projects': json.dumps(projects), 'an_token': self.analytic_session.key.id(), 'debug_level': debug_level, }, 'domain': self.request.host_url, } template_index = JINJA_ENVIRONMENT.get_template('index.html') self.response.write(template_index.render(template_data))
def put(self, project_id=None): if self.json_request.get('title') is None: raise HttpErrorException.bad_request('invalid project title') if self.json_request.get('distilled_document') is None: raise HttpErrorException.bad_request('invalid document') distilled_document = self.json_request.get('distilled_document') if not distilled_document.get('title'): raise HttpErrorException.bad_request('invalid document title') doc_perm = Permission(permissions=Permission.init_perm_struct( Document.operations_list), key=Permission.create_key()) doc = Document( key=Document.create_key(), title=distilled_document.get('title'), subtitle=distilled_document.get('subtitle'), author=distilled_document.get('author', self.user.full_name), version=distilled_document.get('version', 'v0.1'), date=distilled_document.get('date', datetime.datetime.now().year), copyright_text=distilled_document.get('copyright', ''), description=distilled_document.get('description', ''), owner=[self.user.key], permissions=doc_perm.key, ) doc_perm.artifact = doc.key pro_perm = Permission(permissions=Permission.init_perm_struct( Project.operations_list), key=Permission.create_key()) pro = Project( key=Project.create_key(), title=self.json_request.get('title'), distilled_document=doc.key, permissions=pro_perm.key, owner=[self.user.key], ) pro_perm.artifact = pro.key pro_perm.project = pro.key doc_perm.project = pro.key doc.project = pro.key doc.parent_perms.append(pro_perm.key) if self.user.in_org(): doc.organization = self.user.organization pro.organization = self.user.organization ndb.put_multi([doc_perm, doc, pro_perm, pro]) index = self.user.get_put_index() doc.index(index) pro.index(index) self.write_json_response(pro.to_dict(self.user))
def post(self): query_dict = self.json_request.get('query') if not query_dict: raise HttpErrorException.bad_request('no query given') if query_dict['return'] == 'project_ids': self.write_json_response( {'projects': Project.search_projects(query_dict, self.user)}) elif query_dict['return'] == 'concept_ids': self.write_json_response( {'concepts': Concept.search_concept(query_dict, self.user)})
def get(self, project_id=None): if project_id: if not Project.valid_id(project_id): raise HttpErrorException.bad_request('invalid project id') self.project = Project.get_by_id(project_id) if not self.project: raise HttpErrorException.bad_request('invalid project id') if not self.project.has_permission_read(self.user): lr = tt_logging.construct_log( msg_short= 'User does not have permission to access this project', log_type=tt_logging.SECURITY, request=self.request, artifact=self.project, request_user=self.user) log.info(lr['dict_msg']['msg'], extra=lr) self.redirect('/', abort=True) self._serve_page() elif self.request.get('type') == 'json': self._serve_json()
def get(self): if self.json_request.get('project') is None: raise HttpErrorException.bad_request('invalid project id') project = Project.get_by_id(self.json_request.get('project')) if not project: raise HttpErrorException.bad_request('invalid project id') if self.json_request.get('document') is None: raise HttpErrorException.bad_request('invalid document id') document = Document.get_by_id(self.json_request.get('document')) if not document: raise HttpErrorException.bad_request('invalid document id') if not document.has_permission_read(self.user): raise HttpErrorException.forbidden() try: limit = int(self.request.get('limit', 30)) except ValueError: raise HttpErrorException.bad_request('limit must be int') try: before_date = int(self.request.get('before_date', 0)) except ValueError: raise HttpErrorException.bad_request('before_date must be int') if limit > 100: limit = 100 if before_date and before_date > 0: before_date = datetime.fromtimestamp(before_date / 1000.0) chat_query = ChatMessage.query( ndb.AND(ChatMessage.project == project.key, ChatMessage.document == document.key, ChatMessage.created_ts < before_date)) else: chat_query = ChatMessage.query( ndb.AND(ChatMessage.project == project.key, ChatMessage.document == document.key)) chat_messages = chat_query.order( ChatMessage.created_ts).fetch(limit=limit) chat_messages_dict = [] for chat in chat_messages: chat_messages_dict.append(chat.to_dict()) self.write_json_response(chat_messages_dict)
def post(self, project, concept, action): project = Project.get_by_id(project) if not project: raise HttpErrorException.bad_request('invalid project id') concept = Concept.get_by_id(concept) if not concept: raise HttpErrorException.bad_request('invalid concept id') if action.rstrip() == '' or not Analytics.is_valid_action(action): raise HttpErrorException.bad_request('invalid action') self.get_analytic_session() concept.record_analytic(action, self.analytic_session, project=project.key)
def _serve_org_project_json(self): organization = Organization.get_by_id( self.request.get('organization_id')) if not self.user.is_admin: lr = tt_logging.construct_log( msg_short='Non-Admin User Attemped to Access all Org Projects', log_type=tt_logging.SECURITY, request=self.request, artifact=organization, request_user=self.user) log.warning(lr['dict_msg']['msg'], extra=lr) raise HttpErrorException.forbidden() else: project_arry = Project.get_org_projects(organization, self.user) self.write_json_response(project_arry)
def get(self, selected_phrasing_id=None): selected_phrasing_dict = {} q = SelectedPhrasing.query() if self.request.get('project_id').strip() != '': q = q.filter(SelectedPhrasing.project == Project.get_by_id( self.request.get('project_id').strip()).key) if self.request.get('document_id').strip() != '': q = q.filter(SelectedPhrasing.document == Document.get_by_id( self.request.get('document_id').strip()).key) if self.request.get('phrasing_id').strip() != '': q = q.filter(SelectedPhrasing.phrasing == Phrasing.get_by_id( self.request.get('phrasing_id').strip()).key) for phrase in q.iter(): phrase_dict = phrase.to_dict() selected_phrasing_dict[phrase.key.id()] = phrase_dict self.write_json_response(selected_phrasing_dict)
def post(self): if self.json_request.get('project') is None: raise HttpErrorException.bad_request('invalid project id') project = Project.get_by_id(self.json_request.get('project')) if not project: raise HttpErrorException.bad_request('invalid project id') if self.json_request.get('document') is None: raise HttpErrorException.bad_request('invalid document id') document = Document.get_by_id(self.json_request.get('document')) if not document: raise HttpErrorException.bad_request('invalid document id') if not document.has_permission_read(self.user): raise HttpErrorException.forbidden() msg = self.json_request.get('msg') if not msg or msg.strip() == '': raise HttpErrorException.bad_request('no message given') chat = ChatMessage(key=ChatMessage.create_key(), project=project.key, document=document.key, user=self.user.key, message=msg) chat.put() self.get_channel_token() channel_tokens = ChannelToken.get_by_project_key( project.key, self.user_channel_token) channel_tokens = ChannelToken.remove_unauthorized_users( channel_tokens, [project, document]) message = { 'user': self.get_user_channel_data(), 'chat': chat.to_dict() } ChannelToken.broadcast_message(channel_tokens, message)
def get(self): if not self.request.get('project', None): raise HttpErrorException.bad_request('invalid project id') project = Project.get_by_id(self.request.get('project')) if not project: raise HttpErrorException.bad_request('invalid project id') self.get_user_channel_data() channel_tokens = ChannelToken.get_by_project_key( project.key, self.user_channel_token) channel_tokens_list = [] for channel_token in channel_tokens: user = channel_token.user.get() if channel_token: channel_tokens_list.append({ 'username': user.username, 'display_name': user.display_name, 'channel_id': channel_token.id, 'link_id': channel_token.link_id, 'color': channel_token.color, 'concept': channel_token.concept.id() if channel_token.concept else '', 'document': channel_token.document.id() if channel_token.document else '', }) self.write_json_response(channel_tokens_list) self.ping_test(project)
def put(self): pro = Project.get_by_id(self.json_request.get('project', 'none')) if not pro: raise HttpErrorException.bad_request('invalid project id') doc = Document.get_by_id(self.json_request.get('document', 'none')) if not doc: raise HttpErrorException.bad_request('invalid document id') if not doc.has_permission_write(self.user): raise HttpErrorException.forbidden() if doc.key != pro.distilled_document and doc.key not in pro.documents: raise HttpErrorException.bad_request( 'document does not belong to project') pres_doc = PresentationDocument(key=PresentationDocument.create_key(), project=pro.key, document=doc.key) doc.presentation_document = pres_doc.key pro.pw_modified_ts = datetime.datetime.now() ndb.put_multi([pres_doc, doc, pro]) self.write_json_response(pres_doc.to_dict())
def get(self, project, document, group): if not project: raise HttpErrorException.bad_request('invalid project given') project = Project.get_by_id(project) if not project: raise HttpErrorException.bad_request('invalid project given') if not project.has_permission_read(self.user): raise HttpErrorException.forbidden() if not document: raise HttpErrorException.bad_request('invalid document given') document = Document.get_by_id(document) if not document: raise HttpErrorException.bad_request('invalid document given') if not document.has_permission_read(self.user): raise HttpErrorException.forbidden() if not group: raise HttpErrorException.bad_request('invalid group given') group = Group.get_by_id(group) if not group: raise HttpErrorException.bad_request('invalid group given') temp_user = User() temp_user.groups = [group.key, Group.get_worldshare().key] org = self.user.organization if self.user.organization else None if org: temp_user.organization = org if not document.has_permission_read(temp_user): raise HttpErrorException.bad_request( 'Group does not have permission to read the document') if document.key not in project.documents and document.key != project.distilled_document: raise HttpErrorException.bad_request( 'document does not belong to project') pubs = document.get_published(group=group) version_int = PublishDocument.get_largest_version(pubs) if version_int is None: version_int = 1 else: version_int += 1 version = self.request.get('version', str(version_int)) if version == 'latest': raise HttpErrorException.bad_request('invalid version given') pubs = document.get_published(group=group) for pub in pubs: if pub.version == version: raise HttpErrorException.bad_request( 'version name already taken') publisher = DocumentPublisherThread() publisher.id = server.create_uuid() publisher.request = self publisher.project = project publisher.document = document publisher.group = group publisher.user = self.user publisher.version = version if publisher.is_lock(): raise HttpErrorException.bad_request('publisher already running') publisher.start() self.write_json_response({'id': publisher.id}) self.get_analytic_session() document.record_analytic('doc_publish', self.analytic_session, project=project.key)
def put(self, document_id=None): if not self.json_request.get('project') and not Project.valid_id( self.json_request.get('project')): raise HttpErrorException.bad_request('invalid project id') pro = Project.get_by_id(self.json_request.get('project')) if not pro: raise HttpErrorException.bad_request('invalid project id') if not pro.has_permission_read(self.user): raise HttpErrorException.forbidden() if not self.json_request.get('title'): raise HttpErrorException.bad_request('invalid title') doc = Document(key=Document.create_key()) doc.project = pro.key doc.title = self.json_request.get('title') doc.subtitle = self.json_request.get('subtitle') doc.author = self.json_request.get('author') doc.version = self.json_request.get('version') doc.date = self.json_request.get('date') doc.copyright_text = self.json_request.get('copyright') doc.description = self.json_request.get('description') doc.owner.append(self.user.key) doc_perm = Permission(permissions=Permission.init_perm_struct( Document.operations_list), key=Permission.create_key(), project=pro.key) doc_perm.artifact = doc.key doc_perm.put() doc.permissions = doc_perm.key if self.user.in_org(): doc.organization = self.user.organization doc.parent_perms = [ pro.permissions, pro.distilled_document.get().permissions ] doc.put() pro.documents.append(doc.key) indexes = self.user.get_put_index() doc.index(indexes) pro.pw_modified_ts = datetime.datetime.now() pro.put() self.write_json_response(doc.to_dict(self.user)) action_data = {'document': doc.to_dict(self.user)} trans = Transaction(action='doc_new', user=self.user.key, artifact=doc.key, project=pro.key, action_data=action_data) trans.put() self.get_channel_token() channel_tokens = ChannelToken.get_by_project_key( pro.key, self.user_channel_token) channel_tokens = ChannelToken.remove_unauthorized_users( channel_tokens, [doc]) for channel_token in channel_tokens: trans.action_data['document'] = doc.to_dict( channel_token.user.get()) message = { 'user': self.get_user_channel_data(), 'transaction': trans.to_dict(self.user) } ChannelToken.broadcast_message([channel_token], message)
def post(self): query_dict = self.json_request.get('query') if not query_dict: raise HttpErrorException.bad_request('no query given') if not query_dict['pro']: raise HttpErrorException.bad_request('no project id given') project = Project.get_by_id(query_dict['pro']) if not project: raise HttpErrorException.bad_request('invalid project id given') if not project.has_permission(self.user, 'read'): raise HttpErrorException.forbidden() index = project.get_indexes(create_new=False) self.get_analytic_session() query_string = 'pro=%s typ=(phr OR anno_reply) (reply=(%s) OR phr=(%s))' % ( project.key.id(), query_dict.get('string', ''), query_dict.get('string', '')) if index is not None and len(index) > 0: search_results = ttindex.ttsearch(index, query_string, limit=1000, use_cursor=False, user=self.user) concepts = [] concept_ids = [] while len(concepts) < 20 and search_results is not None: for sr in search_results: if sr['fields']['con'] not in concept_ids: concept_ids.append(sr['fields']['con']) if sr['fields']['typ'] == 'phr': concept = Concept.get_by_id(sr['fields']['con']) phrasing = Phrasing.get_by_id(sr['id']) if concept.has_permission_read( self.user ) and phrasing.has_permission_read(self.user): concepts.append({ 'con_id': sr['fields']['con'], 'phr_text': sr['fields']['phr'] }) elif sr['fields']['typ'] == 'anno_reply': concept = Concept.get_by_id(sr['fields']['con']) document = Document.get_by_id(sr['fields']['doc']) if concept.has_permission_read(self.user) and \ document.has_permission_read(self.user) and \ document.has_permission_annotation_read(self.user): concepts.append({ 'con_id': sr['fields']['con'], 'phr_text': sr['fields']['reply'] }) if len(concepts) >= 20: break else: search_results = ttindex.ttsearch(index, query_dict, limit=1000, user=self.user) self.write_json_response({'concepts': concepts}) else: self.write_json_response({'concepts': ''}) project.record_analytic('pro_search', self.analytic_session, meta_data={'sch_query': str(query_dict)})
def restore_v1(self, project_json, request_user, zip_file): doc_perm = Permission(key=Permission.create_key(), permissions=Permission.init_perm_struct( Document.operations_list)) pro_perm = Permission(key=Permission.create_key(), permissions=Permission.init_perm_struct( Project.operations_list)) document = Document( key=Document.create_key(), title=project_json['distilled_document']['title'], author=project_json['distilled_document']['author'], subtitle=project_json['distilled_document']['subtitle'], date=project_json['distilled_document']['date'], copyright_text=project_json['distilled_document'] ['copyright_text'], description=project_json['distilled_document']['description'], owner=[request_user.key], permissions=doc_perm.key) project = Project(key=Project.create_key(), title=project_json['title'], distilled_document=document.key, permissions=pro_perm.key, owner=[request_user.key]) document.project = project.key document.parent_perms.append(pro_perm.key) if request_user.in_org(): document.organization = request_user.organization project.organization = request_user.organization doc_perm.artifact = document.key doc_perm.project = project.key pro_perm.artifact = project.key pro_perm.project = project.key ndb.put_multi([doc_perm, pro_perm, document, project]) # We do not want to re-use the old project, document, concept, ... ids so we will create a mapping # from old to new :) id_mapping = { project_json['id']: project.key.id(), project_json['distilled_document']['id']: project.distilled_document.id() } documents = { project.distilled_document.id(): project.distilled_document.get() } for doc_json in project_json['documents']: doc_json['project_id'] = project.key.id() doc_perm = Permission(key=Permission.create_key(), project=project.key, permissions=Permission.init_perm_struct( Document.operations_list)) doc_obj = Document(key=Document.create_key(), title=doc_json['title'], author=doc_json['author'], subtitle=doc_json['subtitle'], date=doc_json['date'], copyright_text=doc_json['copyright_text'], description=doc_json['description'], owner=[request_user.key], permissions=doc_perm.key, project=project.key) doc_perm.artifact = doc_obj.key doc_obj.put() doc_perm.put() project.documents.append(doc_obj.key) id_mapping[doc_json['id']] = doc_obj.key.id() documents[doc_obj.key.id()] = doc_obj project.put() model_array = [] project.children = self.restore_concept_from_json_v1( project, project_json['concepts'], id_mapping, request_user, model_array, None, documents, zip_file) ndb.put_multi(model_array) Phrasing.index_multi(model_array, request_user) project.put() return project
def _serve_project_json(self): depth = 0 if self.request.get('depth').strip() != '': depth = self._to_int(self.request.get('depth')) if self.request.get('project_id').strip() != '': project = Project.get_by_id(self.request.get('project_id').strip()) if not project.has_permission_read(self.user): lr = tt_logging.construct_log( msg_short= 'User does not have permission to access this project', log_type=tt_logging.SECURITY, request=self.request, artifact=project, request_user=self.user) log.info(lr['dict_msg']['msg'], extra=lr) raise HttpErrorException.forbidden() project_dict = project.to_dict( depth, self.user, get_treeview=self.request.get('get_treeview')) else: q = Project.query(Project.owner == self.user.key) projects = [] for results in q.iter(): if results.has_permission_read(self.user): projects.append(results) groups = ndb.get_multi(self.user.groups) for group in groups: pros = ndb.get_multi(group.artifacts) index = 0 for pro in pros: if pro is None: group.artifacts.remove(group.artifacts[index]) lr = tt_logging.construct_log( msg_short='Found Broken Project Key', msg= 'Found broken project key (%s) in group artifact list' '\n Key has been removed' % group.artifacts[index], log_type=tt_logging.SECURITY, request=self.request, request_user=self.user) log.info(lr['dict_msg']['msg'], extra=lr) if pro.has_permission_read(self.user): if pro not in projects: projects.append(pro) index += 1 project_dict = [] for project in projects: project_dict.append(project.to_dict(self.user)) self.write_json_response(project_dict)
def get(self, project, document, group): if not project: raise HttpErrorException.bad_request('invalid project given') project = Project.get_by_id(project) if not project: raise HttpErrorException.bad_request('invalid project given') if not project.has_permission_read(self.user): raise HttpErrorException.forbidden() if not document: raise HttpErrorException.bad_request('invalid document given') document = Document.get_by_id(document) if not document: raise HttpErrorException.bad_request('invalid document given') if not document.has_permission_read(self.user): raise HttpErrorException.forbidden() if not group: raise HttpErrorException.bad_request('invalid group given') group = Group.get_by_id(group) if not group: raise HttpErrorException.bad_request('invalid group given') if document.key not in project.documents and document.key != project.distilled_document: raise HttpErrorException.bad_request( 'document does not belong to project') temp_user = User() temp_user.groups = [group.key, Group.get_worldshare().key] org = self.user.organization if self.user.organization else None if org: temp_user.organization = org if not document.has_permission_read(temp_user): raise HttpErrorException.bad_request( 'Group does not have permission to read the document') pubs = document.get_presentation_published(group=group) version_int = PublishDocument.get_largest_version(pubs) if version_int is None: version_int = 1 else: version_int += 1 version = self.request.get('version', str(version_int)) if version == 'latest': raise HttpErrorException.bad_request('invalid version given') for pub in pubs: if pub.version == version: raise HttpErrorException.bad_request( 'version name already taken') try: slide_count = int(self.request.get('slide_count', 15)) except ValueError: raise HttpErrorException.bad_request( 'invalid slide count, must be integer') if slide_count < 1: raise HttpErrorException.bad_request( 'invalid slide_count given min 1') if slide_count > 100: raise HttpErrorException.bad_request( 'invalid slide_count given max 100') try: min_bullet = int(self.request.get('min_bullet', 4)) except ValueError: raise HttpErrorException.bad_request( 'invalid min bullet, must be integer') if min_bullet < 1: raise HttpErrorException.bad_request( 'invalid min_bullet given min 1') if min_bullet > 15: raise HttpErrorException.bad_request( 'invalid min_bullet given max 15') try: max_bullet = int(self.request.get('max_bullet', 6)) except ValueError: raise HttpErrorException.bad_request( 'invalid max bullet, must be integer') if max_bullet < 1: raise HttpErrorException.bad_request( 'invalid max_bullet given min 1') if max_bullet > 15: raise HttpErrorException.bad_request( 'invalid max_bullet given max 15') if min_bullet > max_bullet: raise HttpErrorException.bad_request( 'min_bullet can not be greater than max_bullet') publisher = PresentationPublisherThread() publisher.id = server.create_uuid() publisher.request = self publisher.project = project publisher.document = document publisher.slide_count = slide_count publisher.min_bullet = min_bullet publisher.max_bullet = max_bullet publisher.group = group publisher.user = self.user publisher.version = version if publisher.is_lock(): raise HttpErrorException.bad_request('publisher already running') publisher.start() self.write_json_response({'id': publisher.id}) self.get_analytic_session() document.record_analytic('pres_publish', self.analytic_session, project=project.key)