def put_discussion_roles_for_user(request): discussion_id = request.matchdict['discussion_id'] user_id = request.matchdict['user_id'] discussion = Discussion.get_instance(discussion_id) if not discussion: raise HTTPNotFound("Discussion %s does not exist" % (discussion_id,)) user = User.get_instance(user_id) if not user: raise HTTPNotFound("User id %s does not exist" % (user_id,)) try: data = json.loads(request.body) except Exception as e: raise HTTPBadRequest("Malformed Json") session = Discussion.db() if not isinstance(data, list): raise HTTPBadRequest("Not a list") if data and frozenset((type(x) for x in data)) != frozenset((str,)): raise HTTPBadRequest("not strings") roles = set(session.query(Role).filter(name in data).all()) data = set(data) if len(roles) != len(data): raise HTTPBadRequest("Not valid roles: %s" % (repr( data - set((p.name for p in roles))),)) known_lu_roles = session.query(LocalUserRole).join(Role).filter( user=user, discussion=discussion).all() lur_by_role = {lur.role.name: lur for lur in known_lu_roles} known_roles = set(lur_by_role.keys()) for role in known_roles - roles: session.query.delete(lur_by_role(role)) for role in roles - known_roles: session.add(LocalUserRole( user=user, role=role, discussion=discussion)) return {"added": list(roles - known_roles), "removed": list(known_roles - roles)}
def discussion(request, test_session, default_preferences): """An empty Discussion fixture with default preferences""" from assembl.models import Discussion with test_session.no_autoflush: d = Discussion(topic=u"Jack Layton", slug="jacklayton2", subscribe_to_notifications_on_signup=False, creator=None, session=test_session) d.discussion_locales = ['en', 'fr', 'de'] test_session.add(d) test_session.flush() def fin(): print "finalizer discussion" discussion = d if inspect(discussion).detached: # How did this happen? discussion = test_session.query(Discussion).get(d.id) test_session.delete(discussion.table_of_contents) test_session.delete(discussion.root_idea) test_session.delete(discussion.next_synthesis) preferences = discussion.preferences discussion.preferences = None discussion.preferences_id = None for ut in discussion.user_templates: for ns in ut.notification_subscriptions: ns.delete() ut.delete() test_session.delete(preferences) test_session.delete(discussion) test_session.flush() request.addfinalizer(fin) return d
def test_adding_a_discussion_automatically_adds_participant_user_template_for_notifications( test_session): discussion = Discussion( topic=u"How great is Assembl's notification architecture?", slug="notification-architecture", subscribe_to_notifications_on_signup=True, creator=None, session=test_session) # Creation of a discussion includes automatic creation of a default user template for role participant on this discussion, which is meant to be used for default notification subscriptions assert len(discussion.user_templates) > 0 participant_role = test_session.query(Role).filter_by( name=R_PARTICIPANT).one() user_templates_for_role_participant = test_session.query( UserTemplate).filter_by(discussion=discussion, for_role=participant_role).all() assert len(user_templates_for_role_participant) > 0 test_session.delete(discussion.table_of_contents) test_session.delete(discussion.root_idea) test_session.delete(discussion.next_synthesis) preferences = discussion.preferences discussion.preferences = None discussion.preferences_id = None for ut in discussion.user_templates: for ns in ut.notification_subscriptions: ns.delete() ut.delete() test_session.delete(preferences) test_session.delete(discussion) test_session.flush()
def discussion_admin(request): user_id = authenticated_userid(request) if not user_id: return HTTPFound(location='/login?next=/admin/discussions/') session = User.default_db context = dict( get_default_context(request), discussions=session.query(Discussion)) if request.method == 'POST': g = lambda x: request.POST.get(x, None) (topic, slug, name, host, port, ssl, folder, password, username, homepage) = ( g('topic'), g('slug'), g('mbox_name'), g('host'), g('port'), True if g('ssl') == 'on' else False, g('folder'), g('password'), g('username'), g('homepage') ) discussion = Discussion( topic=topic, slug=slug ) # Could raise an exception if there is no/incorrect scheme passed discussion.homepage = homepage session.add(discussion) create_default_permissions(session, discussion) mailbox_class = ( MailingList if g('mailing_list_address') else IMAPMailbox) mailbox = mailbox_class( name=name, host=host, port=int(port), username=username, use_ssl=ssl, folder=folder, password=password, ) if(g('mailing_list_address')): mailbox.post_email_address = g('mailing_list_address') mailbox.discussion = discussion return render_to_response( 'admin/discussions.jinja2', context, request=request)
def discussion_as_graph(self, discussion_id): from assembl.models import Discussion, AgentProfile local_uri = self.local_uri() discussion = Discussion.get(discussion_id) d_storage_name = self.discussion_storage_name() d_graph_iri = URIRef(self.discussion_graph_iri()) v = get_virtuoso(self.session, d_storage_name) discussion_uri = URIRef( Discussion.uri_generic(discussion_id, local_uri)) subjects = [s for (s,) in v.query( """SELECT DISTINCT ?s WHERE { ?s assembl:in_conversation %s }""" % (discussion_uri.n3()))] subjects.append(discussion_uri) participant_ids = list(discussion.get_participants(True)) profiles = {URIRef(AgentProfile.uri_generic(id, local_uri)) for id in participant_ids} subjects.extend(profiles) # add pseudo-accounts subjects.extend((URIRef("%sAgentAccount/%d" % (local_uri, id)) for id in participant_ids)) # print len(subjects) cg = ConjunctiveGraph(identifier=d_graph_iri) self.add_subject_data(v, cg, subjects) # add relationships of non-pseudo accounts for ((account, p, profile), g) in v.triples((None, SIOC.account_of, None)): if profile in profiles: cg.add((account, SIOC.account_of, profile, g)) # Tempting: simplify with this. # cg.add((profile, FOAF.account, account, g)) for (s, o, g) in v.query( '''SELECT ?s ?o ?g WHERE { GRAPH ?g {?s catalyst:expressesIdea ?o } . ?o assembl:in_conversation %s }''' % (discussion_uri.n3())): cg.add((s, CATALYST.expressesIdea, o, g)) return cg
def discussion2(request, test_session, default_preferences, test_adminuser_webrequest): """An non-empty Discussion fixture with default preferences""" from assembl.models import Discussion d = Discussion(topic=u"Second discussion", slug="testdiscussion2", creator=None) test_session.add(d) test_session.flush() d.apply_side_effects_without_json( request=test_adminuser_webrequest._base_pyramid_request) test_session.flush() def fin(): print("finalizer discussion2") test_session.delete(d.table_of_contents) test_session.delete(d.root_idea) test_session.delete(d.next_synthesis) for ut in d.user_templates: for ns in ut.notification_subscriptions: ns.delete() ut.delete() preferences = d.preferences d.preferences = None test_session.delete(preferences) test_session.delete(d) test_session.flush() request.addfinalizer(fin) return d
def discussion_from_request(request): from ..models import Discussion from assembl.views.traversal import TraversalContext if request.matchdict: if 'discussion_id' in request.matchdict: discussion_id = int(request.matchdict['discussion_id']) discussion = Discussion.get_instance(discussion_id) if not discussion: raise HTTPNotFound("No discussion ID %d" % (discussion_id, )) return discussion elif 'discussion_slug' in request.matchdict: slug = request.matchdict['discussion_slug'] discussion = find_discussion_from_slug(slug) if not discussion: raise HTTPNotFound("No discussion found for slug=%s" % (slug, )) return discussion if getattr(request, "context", None) and isinstance( request.context, TraversalContext): discussion_id = request.context.get_discussion_id() if discussion_id: return Discussion.get(discussion_id) if request.session.get("discussion", None): slug = request.session["discussion"] discussion = find_discussion_from_slug(slug) if not discussion: raise HTTPNotFound("No discussion found for slug=%s" % (slug, )) return discussion
def discussion(request, test_session, default_preferences): """An empty Discussion fixture with default preferences""" from assembl.models import Discussion, LangString from assembl.models import Discussion # from assembl.lib.migration import create_default_discussion_data with test_session.no_autoflush: d = Discussion(topic=u"Jack Layton", slug="jacklayton2", subscribe_to_notifications_on_signup=False, creator=None, session=test_session) d.discussion_locales = ['en', 'fr', 'de'] d.legal_notice = LangString.create( u"We need to input the optical HDD sensor!", "en") tac = LangString.create( u"You can't quantify the driver without quantifying the 1080p JSON protocol!", "en") tac.add_value( u"Vous ne pouvez pas mesurer le driver sans mesurer le protocole JSON en 1080p", u"fr") d.terms_and_conditions = tac test_session.add(d) # create_default_discussion_data(d) # Don't create default discussion data (permissions, sections) here # because it takes too much time to run all tests. # If you need sections or permissions in your tests, execute # create_default_discussion_data, create_default_discussion_sections # or create_default_permissions in your specific test or # use discussion_with_default_data fixture. # If you do permissions tests, be aware that the admin user # having R_SYSADMIN is actually a special case, see # auth/utils.py:get_permissions, it doesn't use discussion permissions # at all. So you need discussion permissions if you test with the # unauthenticated user Everyone or a user not having the R_SYSADMIN role. test_session.flush() def fin(): print "finalizer discussion" discussion = d if inspect(discussion).detached: # How did this happen? discussion = test_session.query(Discussion).get(d.id) test_session.delete(discussion.table_of_contents) test_session.delete(discussion.root_idea) test_session.delete(discussion.next_synthesis) preferences = discussion.preferences discussion.preferences = None discussion.preferences_id = None for ut in discussion.user_templates: for ns in ut.notification_subscriptions: ns.delete() ut.delete() test_session.delete(preferences) test_session.delete(discussion) test_session.flush() request.addfinalizer(fin) return d
def add_local_role(request): # Do not use check_permissions, this is a special case ctx = request.context user_id = request.authenticated_userid if not user_id: raise HTTPUnauthorized() discussion_id = ctx.get_discussion_id() discussion = Discussion.get(discussion_id) user_uri = User.uri_generic(user_id) if discussion_id is None: raise HTTPBadRequest() permissions = get_permissions(user_id, discussion_id) json = request.json_body if "discussion" not in json: json["discussion"] = Discussion.uri_generic(discussion_id) requested_user = json.get('user', None) if not requested_user: json['user'] = requested_user = user_uri elif requested_user != user_uri and P_ADMIN_DISC not in permissions: raise HTTPUnauthorized() if P_ADMIN_DISC not in permissions: if P_SELF_REGISTER in permissions: json['requested'] = False json['role'] = R_PARTICIPANT req_user = User.get_instance(requested_user) if not discussion.check_authorized_email(req_user): raise HTTPForbidden() elif P_SELF_REGISTER_REQUEST in permissions: json['requested'] = True else: raise HTTPUnauthorized() try: instances = ctx.create_object("LocalUserRole", json, user_id) except HTTPClientError as e: raise e except Exception as e: raise HTTPBadRequest(e) if instances: first = instances[0] db = first.db for instance in instances: db.add(instance) db.flush() # Side effect: materialize subscriptions. if not first.requested: # relationship may not be initialized user = first.user or User.get(first.user_id) user.get_notification_subscriptions(discussion_id, True) # Update the user's AgentStatusInDiscussion user.update_agent_status_subscribe(discussion) view = request.GET.get('view', None) or 'default' permissions = get_permissions( user_id, ctx.get_discussion_id()) return CreationResponse(first, user_id, permissions, view)
def test_cache_key(test_session): d = Discussion( topic=u"John Doe", slug="johndoe", subscribe_to_notifications_on_signup=False, creator=None, session=test_session) fn = test_cache_key result = d.generate_redis_key(fn) expected_result = "test_cache_key_" + str(d.id) + "_21_42" assert result(d, 21, 42) == expected_result
def test_cache_key(test_session): d = Discussion(topic=u"John Doe", slug="johndoe", subscribe_to_notifications_on_signup=False, creator=None, session=test_session) fn = test_cache_key result = d.generate_redis_key(fn) expected_result = "test_cache_key_" + str(d.id) + "_21_42" assert result(d, 21, 42) == expected_result
def add_local_role(request): # Do not use check_permissions, this is a special case ctx = request.context user_id = request.authenticated_userid if not user_id: raise HTTPUnauthorized() discussion_id = ctx.get_discussion_id() discussion = Discussion.get(discussion_id) user_uri = User.uri_generic(user_id) if discussion_id is None: raise HTTPBadRequest() permissions = get_permissions(user_id, discussion_id) json = request.json_body if "discussion" not in json: json["discussion"] = Discussion.uri_generic(discussion_id) requested_user = json.get('user', None) if not requested_user: json['user'] = requested_user = user_uri elif requested_user != user_uri and P_ADMIN_DISC not in permissions: raise HTTPUnauthorized() if P_ADMIN_DISC not in permissions: if P_SELF_REGISTER in permissions: json['requested'] = False json['role'] = R_PARTICIPANT req_user = User.get_instance(requested_user) if not discussion.check_authorized_email(req_user): raise HTTPForbidden() elif P_SELF_REGISTER_REQUEST in permissions: json['requested'] = True else: raise HTTPUnauthorized() try: instances = ctx.create_object("LocalUserRole", json, user_id) except HTTPClientError as e: raise e except Exception as e: raise HTTPBadRequest(e) if instances: first = instances[0] db = first.db for instance in instances: db.add(instance) db.flush() # Side effect: materialize subscriptions. if not first.requested: # relationship may not be initialized user = first.user or User.get(first.user_id) user.get_notification_subscriptions(discussion_id, True) # Update the user's AgentStatusInDiscussion user.update_agent_status_subscribe(discussion) view = request.GET.get('view', None) or 'default' permissions = get_permissions(user_id, ctx.get_discussion_id()) return CreationResponse(first, user_id, permissions, view)
def get_permissions_for_discussion(request): discussion_id = request.matchdict['discussion_id'] session = Discussion.db() discussion = session.query(Discussion).get(discussion_id) if not discussion: raise HTTPNotFound("Discussion %s does not exist" % (discussion_id,)) return discussion.get_permissions_by_role()
def discussion_as_graph(self, discussion_id): self.ensure_discussion_storage(None) from assembl.models import Discussion d_storage_name = self.discussion_storage_name() d_graph_iri = URIRef(self.discussion_graph_iri()) v = get_virtuoso(self.session, d_storage_name) discussion_uri = URIRef( Discussion.uri_generic(discussion_id, self.local_uri())) subjects = list(v.query( """SELECT DISTINCT ?s WHERE { ?s assembl:in_conversation %s }""" % (discussion_uri.n3()))) subjects.append([discussion_uri]) # print len(subjects) cg = ConjunctiveGraph(identifier=d_graph_iri) for (s,) in subjects: # Absurdly slow. DISTINCT speeds up a lot, but I get numbers. for p, o in v.query( 'SELECT ?p ?o WHERE { graph %s { %s ?p ?o }}' % ( d_graph_iri.n3(), s.n3())): cg.add((s, p, o)) for (s, o, g) in v.query( '''SELECT ?s ?o ?g WHERE { GRAPH ?g {?s catalyst:expressesIdea ?o } . ?o assembl:in_conversation %s }''' % (discussion_uri.n3())): cg.add((s, CATALYST.expressesIdea, o, g)) # TODO: Add roles return cg
def test_simultaneous_ajax_calls(request): g = lambda x: request.GET.get(x, None) session = User.default_db discussion_id = g('discussion_id') widget_id = g('widget_id') if not discussion_id: return HTTPBadRequest( explanation="Please provide a discussion_id parameter") if not widget_id: return HTTPBadRequest( explanation="Please provide a widget_id parameter") widget_id = int(widget_id) discussion_id = int(discussion_id) discussion = Discussion.get_instance(discussion_id) if not discussion: raise HTTPNotFound("Discussion with id '%d' not found." % ( discussion_id,)) user_id = authenticated_userid(request) assert user_id context = dict( get_default_context(request), discussion=discussion, discussion_id=discussion_id, widget_id=widget_id) return render_to_response( 'admin/test_simultaneous_ajax_calls.jinja2', context, request=request)
def save_synthesis(request): synthesis_id = request.matchdict['id'] discussion_id = int(request.matchdict['discussion_id']) if synthesis_id == 'next_synthesis': discussion = Discussion.get_instance(discussion_id) synthesis = discussion.get_next_synthesis() else: synthesis = Synthesis.get_instance(synthesis_id) if not synthesis: raise HTTPBadRequest("Synthesis with id '%s' not found." % synthesis_id) synthesis_data = json.loads(request.body) user_id = request.authenticated_userid permissions = get_permissions(user_id, discussion_id) for key in ('subject', 'introduction', 'conclusion'): if key in synthesis_data: ls_data = synthesis_data[key] if ls_data is None: continue assert isinstance(ls_data, dict) current = LangString.create_from_json( ls_data, user_id, permissions=permissions) setattr(synthesis, key, current) Synthesis.default_db.add(synthesis) Synthesis.default_db.flush() return {'ok': True, 'id': synthesis.uri()}
def save_synthesis(request): synthesis_id = request.matchdict['id'] discussion_id = int(request.matchdict['discussion_id']) if synthesis_id == 'next_synthesis': discussion = Discussion.get_instance(discussion_id) synthesis = discussion.get_next_synthesis() else: synthesis = Synthesis.get_instance(synthesis_id) if not synthesis: raise HTTPBadRequest("Synthesis with id '%s' not found." % synthesis_id) synthesis_data = json.loads(request.body) user_id = request.authenticated_userid permissions = get_permissions(user_id, discussion_id) for key in ('subject', 'introduction', 'conclusion'): if key in synthesis_data: ls_data = synthesis_data[key] if ls_data is None: continue assert isinstance(ls_data, dict) current = LangString.create_from_json(ls_data, user_id, permissions=permissions) setattr(synthesis, key, current) Synthesis.default_db.add(synthesis) Synthesis.default_db.flush() return {'ok': True, 'id': synthesis.uri()}
def discussion_edit(request): discussion_id = int(request.matchdict["discussion_id"]) discussion = Discussion.get_instance(discussion_id) user_id = authenticated_userid(request) assert user_id permissions = get_permissions(user_id, discussion_id) partners = json.dumps( [p.generic_json(user_id=user_id, permissions=permissions) for p in discussion.partner_organizations] ) if not discussion: raise HTTPNotFound("Discussion with id '%d' not found." % (discussion_id,)) context = dict( get_default_context(request), discussion=discussion, admin_discussion_permissions_url=request.route_url("discussion_permissions", discussion_id=discussion.id), partners=partners, ) if request.method == "POST": g = lambda x: request.POST.get(x, None) (topic, slug, objectives) = (g("topic"), g("slug"), g("objectives")) discussion.topic = topic discussion.slug = slug discussion.objectives = objectives return render_to_response("admin/discussion_edit.jinja2", context, request=request)
def get_user_has_permission(request): discussion_id = int(request.matchdict['discussion_id']) permission = request.matchdict['permission'] discussion = Discussion.get_instance(discussion_id) if not discussion: raise HTTPNotFound("Discussion %d does not exist" % (discussion_id, )) return a_users_with_permission(discussion_id, permission)
def put_permissions_for_role(request): discussion_id = request.matchdict['discussion_id'] role_name = request.matchdict['role_name'] session = Discussion.db() discussion = session.query(Discussion).get(discussion_id) if not discussion: raise HTTPNotFound("Discussion %s does not exist" % (discussion_id,)) role = Role.get(name=role_name) if not role: raise HTTPNotFound("Role %s does not exist" % (role_name,)) try: data = json.loads(request.body) except Exception as e: raise HTTPBadRequest("Malformed Json") if not isinstance(data, list): raise HTTPBadRequest("Not a list") if data and frozenset((type(x) for x in data)) != frozenset((str,)): raise HTTPBadRequest("not strings") permissions = set(session.query(Permission).filter(name in data).all()) data = set(data) if len(permissions) != len(data): raise HTTPBadRequest("Not valid permissions: %s" % (repr( data - set((p.name for p in permissions))),)) known_dp = session.query(DiscussionPermission).join(Permission).filter( role=role, discussion=discussion).all() dp_by_permission = {dp.permission.name: dp for dp in known_dp} known_permissions = set(dp.keys()) for permission in known_permissions - permissions: session.delete(dp_by_permission(permission)) for permission in permissions - known_permissions: session.add(DiscussionPermission( role=role, permission=permission, discussion=discussion)) return {"added": list(permissions - known_permissions), "removed": list(known_permissions - permissions)}
def delete_discussion(session, discussion_id): from assembl.models import Discussion, DiscussionBoundBase # First, delete the discussion. session.delete(Discussion.get(discussion_id)) session.flush() # See if anything is left... classes = DiscussionBoundBase._decl_class_registry.itervalues() classes_by_table = { cls.__dict__.get('__table__', None): cls for cls in classes} # Only direct subclass of abstract concrete_classes = set(filter(lambda cls: issubclass(cls, DiscussionBoundBase) and (not isabstract(cls)) and isabstract(cls.mro()[1]), classes_by_table.values())) tables = DiscussionBoundBase.metadata.sorted_tables tables.reverse() for table in tables: if table not in classes_by_table: continue cls = classes_by_table[table] if cls not in concrete_classes: continue print 'deleting', cls.__name__ query = session.query(cls.id) conds = cls.get_discussion_conditions(discussion_id) assert conds cond = and_(*conds) v = JoinColumnsVisitor(cls, query, classes_by_table) v.traverse(cond) query = v.final_query().filter(cond) if query.count(): print "*" * 20, "Not all deleted!" session.query(cls).filter( cls.id.in_(query.subquery())).delete(False)
def upload_file(request): """ POSTing a file upload is very different than any other endpoint in assembl API because all of the content will be passed in using a MULTIPART_HEADER, with all of data as well as the file (along with its metadata) """ # Testing purposes on front-end # raise Exception("Upload file exception occured!") db = Document.default_db ctx = request.context user_id = authenticated_userid(request) or Everyone discusison_id = ctx.get_discussion_id() discussion = Discussion.get(discusison_id) mime = request.POST['mime_type'] file_name = request.POST['name'] # Check if the file has previously existed, if so, change the name by appending "(n)" # to it's name try: blob = File(discussion=discussion, mime_type=mime, title=file_name) db.add(blob) with request.POST['file'].file as f: blob.add_file_data(f) db.flush() except Exception as e: raise HTTPServerError(e) view = 'default' return blob.generic_json(view, user_id, ctx.get_permissions())
def put_discussion_roles_for_user(request): discussion_id = int(request.matchdict['discussion_id']) discussion = Discussion.get_instance(discussion_id) if not discussion: raise HTTPNotFound("Discussion %d does not exist" % (discussion_id, )) user_id = request.matchdict['user_id'] user = User.get_instance(user_id) if not user: raise HTTPNotFound("User id %d does not exist" % (user_id, )) try: data = json.loads(request.body) except Exception as e: raise HTTPBadRequest("Malformed Json") session = Discussion.default_db if not isinstance(data, list): raise HTTPBadRequest("Not a list") if data and frozenset((type(x) for x in data)) != frozenset((str, )): raise HTTPBadRequest("not strings") roles = set(session.query(Role).filter(Role.name.in_(data)).all()) data = set(data) if len(roles) != len(data): raise HTTPBadRequest("Not valid roles: %s" % (repr(data - set((p.name for p in roles))), )) known_lu_roles = session.query(LocalUserRole).join(Role).filter( user=user, discussion=discussion).all() lur_by_role = {lur.role.name: lur for lur in known_lu_roles} known_roles = set(lur_by_role.keys()) for role in known_roles - roles: session.query.delete(lur_by_role[role]) for role in roles - known_roles: session.add(LocalUserRole(user=user, role=role, discussion=discussion)) return { "added": list(roles - known_roles), "removed": list(known_roles - roles) }
def test_simultaneous_ajax_calls(request): g = lambda x: request.GET.get(x, None) session = User.default_db discussion_id = g('discussion_id') widget_id = g('widget_id') if not discussion_id: return HTTPBadRequest( explanation="Please provide a discussion_id parameter") if not widget_id: return HTTPBadRequest( explanation="Please provide a widget_id parameter") widget_id = int(widget_id) discussion_id = int(discussion_id) discussion = Discussion.get_instance(discussion_id) if not discussion: raise HTTPNotFound("Discussion with id '%d' not found." % (discussion_id, )) user_id = authenticated_userid(request) assert user_id context = dict(get_default_context(request), discussion=discussion, discussion_id=discussion_id, widget_id=widget_id) return render_to_response('admin/test_simultaneous_ajax_calls.jinja2', context, request=request)
def discussion(request, test_session, default_preferences): from assembl.models import Discussion d = Discussion(topic=u"Jack Layton", slug="jacklayton2", session=test_session) test_session.add(d) test_session.add(d.next_synthesis) test_session.add(d.root_idea) test_session.add(d.table_of_contents) test_session.flush() def fin(): print "finalizer discussion" discussion = d if inspect(d).detached: # How did this happen? discussion = test_session.query(Discussion).get(d.id) test_session.delete(discussion.table_of_contents) test_session.delete(discussion.root_idea) test_session.delete(discussion.next_synthesis) preferences = discussion.preferences discussion.preferences = None test_session.delete(preferences) test_session.delete(discussion) test_session.flush() request.addfinalizer(fin) return d
def get_user_has_permission(request): discussion_id = int(request.matchdict['discussion_id']) permission = request.matchdict['permission'] discussion = Discussion.get_instance(discussion_id) if not discussion: raise HTTPNotFound("Discussion %d does not exist" % (discussion_id,)) return a_users_with_permission(discussion_id, permission)
def discussion_admin(request): user_id = authenticated_userid(request) if not user_id: return HTTPFound(location='/login?next=/admin/discussions/') session = User.default_db context = dict(get_default_context(request), discussions=session.query(Discussion)) if request.method == 'POST': g = lambda x: request.POST.get(x, None) (topic, slug, name, host, port, ssl, folder, password, username, homepage) = (g('topic'), g('slug'), g('mbox_name'), g('host'), g('port'), True if g('ssl') == 'on' else False, g('folder'), g('password'), g('username'), g('homepage')) discussion = Discussion(topic=topic, creator_id=user_id, slug=slug) # Could raise an exception if there is no/incorrect scheme passed discussion.homepage = homepage session.add(discussion) discussion.invoke_callbacks_after_creation() create_default_permissions(discussion) mailbox_class = (MailingList if g('mailing_list_address') else IMAPMailbox) mailbox = mailbox_class( name=name, host=host, port=int(port), username=username, use_ssl=ssl, folder=folder, password=password, ) if (g('mailing_list_address')): mailbox.post_email_address = g('mailing_list_address') mailbox.discussion = discussion return render_to_response('admin/discussions.jinja2', context, request=request)
def test_add_discussion(test_session): d = Discussion( topic=u"Education", slug="education", subscribe_to_notifications_on_signup=False, creator=None, session=test_session) d.discussion_locales = ['en', 'fr', 'de'] d.terms_and_conditions = LangString.create( u"Use the haptic JSON system, then you can quantify the cross-platform capacitor!", "en") d.legal_notice = LangString.create( u"Use the optical SCSI microchip, then you can generate the cross-platform pixel!", "en") test_session.flush() assert d.topic == u"Education" assert d.discussion_locales == ['en', 'fr', 'de'] assert d.terms_and_conditions.entries[0].value == u"Use the haptic JSON system, then you can quantify the cross-platform capacitor!" # noqa: E501 assert d.legal_notice.entries[0].value == u"Use the optical SCSI microchip, then you can generate the cross-platform pixel!" # noqa: E501 test_session.delete(d)
def get_agents(request, discussion_only=False): discussion_id = int(request.matchdict['discussion_id']) discussion = Discussion.get(int(discussion_id)) if not discussion: raise HTTPNotFound("Discussion with id '%s' not found." % discussion_id) view_def = request.GET.get('view') return _get_agents_real( discussion, authenticated_userid(request), view_def)
def get_ideas(request): discussion_id = request.matchdict['discussion_id'] discussion = Discussion.get(id=int(discussion_id)) if not discussion: raise HTTPNotFound("Discussion with id '%s' not found." % discussion_id) view_def = request.GET.get('view') ids = request.GET.getall('ids') return _get_ideas_real(discussion=discussion, view_def=view_def, ids=ids)
def get_agents(request, discussion_only=False): discussion_id = int(request.matchdict['discussion_id']) discussion = Discussion.get(int(discussion_id)) if not discussion: raise HTTPNotFound("Discussion with id '%s' not found." % discussion_id) view_def = request.GET.get('view') return _get_agents_real(discussion, request.authenticated_userid, view_def)
def test_add_discussion(test_session): d = Discussion(topic=u"Education", slug="education", subscribe_to_notifications_on_signup=False, creator=None, session=test_session) d.discussion_locales = ['en', 'fr', 'de'] d.terms_and_conditions = LangString.create( u"Use the haptic JSON system, then you can quantify the cross-platform capacitor!", "en") d.legal_notice = LangString.create( u"Use the optical SCSI microchip, then you can generate the cross-platform pixel!", "en") test_session.flush() assert d.topic == u"Education" assert d.discussion_locales == ['en', 'fr', 'de'] assert d.terms_and_conditions.entries[ 0].value == u"Use the haptic JSON system, then you can quantify the cross-platform capacitor!" # noqa: E501 assert d.legal_notice.entries[ 0].value == u"Use the optical SCSI microchip, then you can generate the cross-platform pixel!" # noqa: E501 test_session.delete(d.table_of_contents) test_session.delete(d.root_idea) test_session.delete(d.next_synthesis) preferences = d.preferences d.preferences = None d.preferences_id = None for ut in d.user_templates: for ns in ut.notification_subscriptions: ns.delete() ut.delete() test_session.delete(preferences) test_session.delete(d) test_session.flush()
def get_ideas(request): user_id = authenticated_userid(request) or Everyone discussion_id = int(request.matchdict["discussion_id"]) discussion = Discussion.get(int(discussion_id)) if not discussion: raise HTTPNotFound("Discussion with id '%s' not found." % discussion_id) view_def = request.GET.get("view") ids = request.GET.getall("ids") return _get_ideas_real(discussion=discussion, view_def=view_def, ids=ids, user_id=user_id)
def __acl__(self): if getattr(self._instance, '__acl__', None): return self._instance.__acl__ if getattr(self._instance, 'discussion', None): return self._instance.discussion.__acl__ discussion_id = self.get_discussion_id() if discussion_id: from assembl.models import Discussion return Discussion.get(discussion_id).__acl__ return self.__parent__.__acl__
def get_discussion_roles_for_user(request): discussion_id = request.matchdict['discussion_id'] user_id = get_database_id("User", request.matchdict['user_id']) session = Discussion.db() if not session.query(User).get(user_id): raise HTTPNotFound("User id %s does not exist" % (user_id,)) rolenames = session.query(Role.name).join( LocalUserRole).filter(LocalUserRole.user_id == user_id, LocalUserRole.discussion_id == discussion_id) return [x[0] for x in rolenames]
def delete_discussion(request): discussion_id = int(request.matchdict['discussion_id']) discussion = Discussion.get_instance(discussion_id) if not discussion: raise HTTPNotFound( "Discussion with id '%s' not found." % discussion_id) discussion.delete() return HTTPNoContent()
def get_ideas(request): user_id = authenticated_userid(request) or Everyone discussion_id = int(request.matchdict['discussion_id']) discussion = Discussion.get(int(discussion_id)) if not discussion: raise HTTPNotFound("Discussion with id '%s' not found." % discussion_id) view_def = request.GET.get('view') ids = request.GET.getall('ids') return _get_ideas_real(discussion=discussion, view_def=view_def, ids=ids, user_id=user_id)
def delete_discussion(request): discussion_id = int(request.matchdict['discussion_id']) discussion = Discussion.get_instance(discussion_id) if not discussion: raise HTTPNotFound("Discussion with id '%s' not found." % discussion_id) discussion.delete() return HTTPNoContent()
def serializable(self): from assembl.models import Discussion return { "@id": self.uri_generic(self.id), "@type": self.external_typename(), "name": self.name, "creation_date": self.creation_date.isoformat(), "last_import": self.last_import.isoformat() if self.last_import else None, "discussion_id": Discussion.uri_generic(self.discussion_id), }
def mark_post_read(request): discussion_id = int(request.matchdict["discussion_id"]) discussion = Discussion.get_instance(discussion_id) post_id = request.matchdict["id"] post = Post.get_instance(post_id) if not post: raise HTTPNotFound("Post with id '%s' not found." % post_id) post_id = post.id user_id = authenticated_userid(request) if not user_id: raise HTTPUnauthorized() read_data = json.loads(request.body) db = Discussion.db() change = False with transaction.manager: if read_data.get("read", None) is False: view = db.query(ViewPost).filter(ViewPost.post_id == post_id).filter(Action.actor_id == user_id).first() if view: change = True db.delete(view) else: count = db.query(ViewPost).filter(ViewPost.post_id == post_id).filter(Action.actor_id == user_id).count() if not count: change = True db.add(ViewPost(post=post, actor_id=user_id)) new_counts = [] if change: new_counts = Idea.idea_counts(discussion_id, post_id, user_id) return { "ok": True, "ideas": [ { "@id": Idea.uri_generic(idea_id), "@type": db.query(Idea).get(idea_id).external_typename(), "num_posts": total_posts, "num_read_posts": read_posts, } for (idea_id, total_posts, read_posts) in new_counts ], }
def get_discussion_roles_for_user(request): discussion_id = int(request.matchdict['discussion_id']) user_id = request.matchdict['user_id'] user = User.get_instance(user_id) session = Discussion.db() if not user: raise HTTPNotFound("User id %d does not exist" % (user_id,)) rolenames = session.query(Role.name).join( LocalUserRole).filter(LocalUserRole.user == user, LocalUserRole.discussion_id == discussion_id) return [x[0] for x in rolenames]
def get_extracts(request): discussion_id = int(request.matchdict['discussion_id']) discussion = Discussion.get(int(discussion_id)) if not discussion: raise HTTPNotFound( "Discussion with id '%s' not found." % discussion_id) view_def = request.GET.get('view') ids = request.GET.getall('ids') return _get_extracts_real( discussion, view_def, ids, authenticated_userid(request))
def get_extracts(request): discussion_id = int(request.matchdict['discussion_id']) discussion = Discussion.get(int(discussion_id)) if not discussion: raise HTTPNotFound("Discussion with id '%s' not found." % discussion_id) view_def = request.GET.get('view') ids = request.GET.getall('ids') return _get_extracts_real(discussion, view_def, ids, request.authenticated_userid)
def get_permissions_for_role(request): discussion_id = request.matchdict['discussion_id'] role_name = request.matchdict['role_name'] session = Discussion.db() discussion = session.query(Discussion).get(discussion_id) if not discussion: raise HTTPNotFound("Discussion %s does not exist" % (discussion_id,)) role = Role.get(name=role_name) if not role: raise HTTPNotFound("Role %s does not exist" % (role_name,)) return discussion.get_permissions_by_role().get(role_name, [])
def get_permissions_for_user(request): discussion_id = request.matchdict['discussion_id'] user_id = request.matchdict['user_id'] discussion = Discussion.get_instance(discussion_id) if not discussion: raise HTTPNotFound("Discussion %s does not exist" % (discussion_id,)) if user_id not in (Authenticated, Everyone): user = User.get_instance(user_id) if not user: raise HTTPNotFound("User id %s does not exist" % (user_id,)) return a_permissions_for_user(discussion_id, user_id)
def discussion(request, test_session, default_preferences, test_adminuser_webrequest): """An empty Discussion fixture with default preferences""" from assembl.models import Discussion from assembl.models.auth import create_default_permissions d = Discussion(topic=u"Jack Layton", slug="jacklayton2", subscribe_to_notifications_on_signup=False, creator=None) test_session.add(d) test_session.flush() d.apply_side_effects_without_json( request=test_adminuser_webrequest._base_pyramid_request) d.discussion_locales = ['en', 'fr', 'de'] create_default_permissions(d) test_session.flush() def fin(): print("finalizer discussion") discussion = d if inspect(discussion).detached: # How did this happen? discussion = test_session.query(Discussion).get(d.id) for acl in discussion.acls: test_session.delete(acl) test_session.delete(discussion.table_of_contents) test_session.delete(discussion.root_idea) test_session.delete(discussion.next_synthesis) preferences = discussion.preferences discussion.preferences = None discussion.preferences_id = None for ut in discussion.user_templates: for ns in ut.notification_subscriptions: ns.delete() ut.delete() test_session.delete(preferences) test_session.delete(discussion) test_session.flush() request.addfinalizer(fin) return d
def get_syntheses(request): discussion_id = int(request.matchdict['discussion_id']) discussion = Discussion.get(int(discussion_id)) if not discussion: raise HTTPNotFound("Discussion with id '%s' not found." % discussion_id) user_id = authenticated_userid(request) or Everyone permissions = get_permissions(user_id, discussion_id) syntheses = discussion.get_all_syntheses() view_def = request.GET.get('view') or 'default' res = [synthesis.generic_json(view_def, user_id, permissions) for synthesis in syntheses] return [x for x in res if x is not None]
def test_adding_a_discussion_automatically_adds_participant_user_template_for_notifications(test_session): discussion = Discussion( topic=u"How great is Assembl's notification architecture?", slug="notification-architecture", subscribe_to_notifications_on_signup=True, creator=None, session=test_session) # Creation of a discussion includes automatic creation of a default user template for role participant on this discussion, which is meant to be used for default notification subscriptions assert len(discussion.user_templates) > 0 participant_role = test_session.query(Role).filter_by(name=R_PARTICIPANT).one() user_templates_for_role_participant = test_session.query(UserTemplate).filter_by(discussion=discussion, for_role=participant_role).all() assert len(user_templates_for_role_participant) > 0
def get_discussion(request): discussion_id = int(request.matchdict['discussion_id']) discussion = Discussion.get_instance(discussion_id) view_def = request.GET.get('view') or 'default' user_id = authenticated_userid(request) or Everyone permissions = get_permissions(user_id, discussion_id) if not discussion: raise HTTPNotFound( "Discussion with id '%s' not found." % discussion_id) return discussion.generic_json(view_def, user_id, permissions)
def get_discussion(request): discussion_id = int(request.matchdict['discussion_id']) discussion = Discussion.get_instance(discussion_id) view_def = request.GET.get('view') or 'default' user_id = authenticated_userid(request) permissions = get_permissions(user_id, discussion_id) if not discussion: raise HTTPNotFound( "Discussion with id '%s' not found." % discussion_id) return discussion.generic_json(view_def, user_id, permissions)
def get_permissions_for_user(request): discussion_id = int(request.matchdict['discussion_id']) discussion = Discussion.get_instance(discussion_id) if not discussion: raise HTTPNotFound("Discussion %d does not exist" % (discussion_id, )) user_id = request.matchdict['user_id'] if user_id not in (Authenticated, Everyone): user = User.get_instance(user_id) if not user: raise HTTPNotFound("User id %s does not exist" % (user_id, )) user_id = user.id return get_permissions(user_id, discussion_id)
def get_user_has_permission(request): discussion_id = int(request.matchdict['discussion_id']) user_id = request.matchdict['user_id'] permission = request.matchdict['permission'] discussion = Discussion.get_instance(discussion_id) if not discussion: raise HTTPNotFound("Discussion %d does not exist" % (discussion_id,)) if user_id not in (Authenticated, Everyone): user = User.get_instance(user_id) if not user: raise HTTPNotFound("User id %s does not exist" % (user_id,)) user_id = user.id return a_user_has_permission(discussion_id, user_id, permission)
def get_discussion_semantic_analysis( discussion_id, num_topics=200, model_cls=gmodels.lsimodel.LsiModel, **model_kwargs): discussion = Discussion.get(discussion_id) lang = discussion.discussion_locales[0].split('_')[0] dirname = join(nlp_data, lang) dict_fname = join(dirname, DICTIONARY_FNAME) # rebuild dico in all cases to ensure complete corpus corpus = create_dictionaries(discussion_id) dictionary = corpora.Dictionary.load(dict_fname) post_ids = discussion.db.query(Content.id).filter_by( discussion_id=discussion_id) doc_count = post_ids.count() if doc_count < 10: return None, None post_ids = [x for (x,) in post_ids] subcorpus = corpus[post_ids] tfidf_model = gmodels.TfidfModel(id2word=dictionary) tfidf_fname = join(dirname, "tfidf_%d.model" % (discussion_id,)) model_fname = join(dirname, "model_%s_%d.model" % ( model_cls.__name__, discussion_id,)) gensim_model = model_cls( id2word=dictionary, num_topics=num_topics, **model_kwargs) if exists(tfidf_fname): tfidf_model = tfidf_model.load(tfidf_fname) # assumption: count implies identity. # Wrong in corner cases: hidden, etc. if tfidf_model.num_docs == doc_count: if exists(model_fname): gensim_model = gensim_model.load(model_fname) same_kwargs = all(( getattr(gensim_model, k) == v for (k, v) in model_kwargs.iteritems())) same_kwargs = same_kwargs and getattr( gensim_model, 'num_updates', doc_count) == doc_count if same_kwargs and gensim_model.num_topics == num_topics: return (subcorpus, tfidf_model, gensim_model) elif exists(tfidf_fname): unlink(tfidf_fname) if exists(model_fname): unlink(model_fname) if tfidf_model.num_docs != doc_count: tfidf_model.initialize(subcorpus) tfidf_model.save(tfidf_fname) tfidf_corpus = tfidf_model[subcorpus] if getattr(gensim_model, 'update', None): gensim_model.update(tfidf_corpus) elif getattr(gensim_model, 'add_documents', None): gensim_model.add_documents(tfidf_corpus) gensim_model.save(model_fname) return (subcorpus, tfidf_model, gensim_model)
def maybe_contextual_route(request, route_name, **args): discussion_slug = request.matchdict.get('discussion_slug', None) if discussion_slug is None: discussion_id = request.matchdict.get('discussion_id', None) if discussion_id is None: return request.route_url(route_name, **args) else: discussion = Discussion.get(int(discussion_id)) return request.route_url( 'contextual_'+route_name, discussion_slug=discussion.slug, **args) else: return request.route_url( 'contextual_'+route_name, discussion_slug=discussion_slug, **args)
def get_discussion(request): discussion_id = int(request.matchdict['discussion_id']) discussion = Discussion.get_instance(discussion_id) is_etalab_request = request.matched_route.name == 'etalab_discussion' view_def = request.GET.get('view', 'etalab' if is_etalab_request else 'default') user_id = request.authenticated_userid or Everyone permissions = get_permissions(user_id, discussion_id) if not discussion: raise HTTPNotFound("Discussion with id '%s' not found." % discussion_id) return discussion.generic_json(view_def, user_id, permissions)