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 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 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 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 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_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 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 create_idea(request): discussion_id = int(request.matchdict['discussion_id']) session = Discussion.db() discussion = session.query(Discussion).get(int(discussion_id)) idea_data = json.loads(request.body) new_idea = Idea( short_title=idea_data['shortTitle'], long_title=idea_data['longTitle'], discussion=discussion, ) session.add(new_idea) if idea_data['parentId']: parent = Idea.get_instance(idea_data['parentId']) else: parent = discussion.root_idea session.add(IdeaLink(source=parent, target=new_idea, order=idea_data.get('order', 0.0))) session.flush() return {'ok': True, '@id': new_idea.uri()}
def add_user(name, email, password, role, force=False, username=None, localrole=None, discussion=None, **kwargs): from assembl.models import ( Role, UserRole, LocalUserRole, EmailAccount, Discussion, Username, AgentProfile, User) db = Discussion.db() # refetch within transaction all_roles = {r.name: r for r in Role.db.query(Role).all()} user = None if discussion and localrole: discussion_ob = db.query(Discussion).filter_by(slug=discussion).first() assert discussion_ob,\ "Discussion with slug %s does not exist" % (discussion,) discussion = discussion_ob existing_email = db.query(EmailAccount).filter( EmailAccount.email == email).first() assert force or not existing_email,\ "User with email %s already exists" % (email,) if username: existing_username = db.query(Username).filter_by( username=username).first() assert force or not existing_username,\ "User with username %s already exists" % (username,) assert not existing_email or not existing_username or \ existing_username.user == existing_email.profile,\ "Two different users already exist with "\ "username %s and email %s." % (username, email) if existing_email: user = existing_email.profile elif username and existing_username: user = existing_username.user old_user = isinstance(user, User) if old_user: user.preferred_email = email user.name = name user.verified = True user.set_password(password) if username: if user.username: user.username.username = username else: db.add(Username(username=username, user=user)) else: if user: # Profile may have come from userless existing AgentProfile user = User( id = user.id, preferred_email=email, verified=True, password=password, creation_date=datetime.now()) else: user = User( name=name, preferred_email=email, verified=True, password=password, creation_date=datetime.now()) db.add(user) if username: db.add(Username(username=username, user=user)) for account in user.accounts: if isinstance(account, EmailAccount) and account.email == email: account.verified = True account.preferred = True break else: account = EmailAccount( profile=user, email=email, preferred=True, verified=True) db.add(account) if role: role = all_roles[role] ur = None if old_user: ur = db.query(UserRole).filter_by(user=user, role=role).first() if not ur: db.add(UserRole(user=user, role=role)) if localrole: localrole = all_roles[localrole] lur = None if old_user: lur = db.query(LocalUserRole).filter_by( user=user, discussion=discussion, role=role).first() if not lur: db.add(LocalUserRole( user=user, role=localrole, discussion=discussion))
def discussion_permissions(request): user_id = authenticated_userid(request) db = Discussion.db() discussion_id = int(request.matchdict['discussion_id']) discussion = Discussion.get_instance(discussion_id) if not discussion: raise HTTPNotFound("Discussion with id '%d' not found." % ( discussion_id,)) roles = db.query(Role).all() roles_by_name = {r.name: r for r in roles} role_names = [r.name for r in roles] permissions = db.query(Permission).all() perms_by_name = {p.name: p for p in permissions} permission_names = [p.name for p in permissions] disc_perms = db.query(DiscussionPermission).filter_by( discussion_id=discussion_id).join(Role, Permission).all() disc_perms_as_set = set((dp.role.name, dp.permission.name) for dp in disc_perms) disc_perms_dict = {(dp.role.name, dp.permission.name): dp for dp in disc_perms} local_roles = db.query(LocalUserRole).filter_by( discussion_id=discussion_id).join(Role, User).all() local_roles_as_set = set((lur.user.id, lur.role.name) for lur in local_roles) local_roles_dict = {(lur.user.id, lur.role.name):lur for lur in local_roles} users = set(lur.user for lur in local_roles) if request.POST: if 'submit_role_permissions' in request.POST: for role in role_names: if role == R_SYSADMIN: continue for permission in permission_names: allowed_text = 'allowed_%s_%s' % (role, permission) if (role, permission) not in disc_perms_as_set and \ allowed_text in request.POST: dp = DiscussionPermission( role=roles_by_name[role], permission=perms_by_name[permission], discussion_id=discussion_id) disc_perms_dict[(role, permission)] = dp disc_perms_as_set.add((role, permission)) db.add(dp) elif (role, permission) in disc_perms_as_set and \ allowed_text not in request.POST: dp = disc_perms_dict[(role, permission)] del disc_perms_dict[(role, permission)] disc_perms_as_set.remove((role, permission)) db.delete(dp) if not role in SYSTEM_ROLES and\ 'delete_'+role in request.POST: db.delete(roles_by_name[role]) del roles_by_name[role] role_names.remove(role) elif 'submit_add_role' in request.POST: #TODO: Sanitize role role = Role(name='r:'+request.POST['new_role']) roles_by_name[role.name] = role role_names.append(role.name) db.add(role) elif 'submit_user_roles' in request.POST: user_ids = {u.id for u in users} for role in role_names: if role == R_SYSADMIN: continue prefix = 'has_'+role+'_' for name in request.POST: if name.startswith(prefix): user_id = int(name[len(prefix):]) if user_id not in user_ids: users.add(User.get_instance(user_id)) user_ids.add(user_id) for user in users: has_role_text = 'has_%s_%d' % (role, user.id) if (user.id, role) not in local_roles_as_set and \ has_role_text in request.POST: lur = LocalUserRole( role=roles_by_name[role], user=user, discussion_id=discussion_id) local_roles.append(lur) local_roles_dict[(user.id, role)] = lur local_roles_as_set.add((user.id, role)) db.add(lur) elif (user.id, role) in local_roles_as_set and \ has_role_text not in request.POST: lur = local_roles_dict[(user.id, role)] del local_roles_dict[(user.id, role)] local_roles_as_set.remove((user.id, role)) local_roles.remove(lur) db.delete(lur) elif 'submit_look_for_user' in request.POST: search_string = '%' + request.POST['user_search'] + '%' other_users = db.query(User).join(AgentProfile).filter(AgentProfile.name.ilike(search_string)).union( db.query(User).outerjoin(Username).filter(Username.username.ilike(search_string))).union( db.query(User).filter(User.preferred_email.ilike(search_string))).all() users.update(other_users) def allowed(role, permission): if role == R_SYSADMIN: return True return (role, permission) in disc_perms_as_set def has_local_role(user_id, role): return (user_id, role) in local_roles_as_set context = dict( discussion=discussion, allowed=allowed, roles=role_names, permissions=permission_names, users=users, has_local_role=has_local_role, is_system_role=lambda r: r in SYSTEM_ROLES ) return render_to_response( 'admin/discussion_permissions.jinja2', context, request=request)
def general_permissions(request): user_id = authenticated_userid(request) db = Discussion.db() roles = db.query(Role).all() roles_by_name = {r.name: r for r in roles} role_names = [r.name for r in roles] permissions = db.query(Permission).all() perms_by_name = {p.name: p for p in permissions} permission_names = [p.name for p in permissions] user_roles = db.query(UserRole).join(Role, User).all() user_roles_as_set = set((lur.user.id, lur.role.name) for lur in user_roles) user_roles_dict = {(lur.user.id, lur.role.name):lur for lur in user_roles} users = set(lur.user for lur in user_roles) if request.POST: if 'submit_user_roles' in request.POST: user_ids = {u.id for u in users} for role in role_names: if role == R_SYSADMIN: continue prefix = 'has_'+role+'_' for name in request.POST: if name.startswith(prefix): user_id = int(name[len(prefix):]) if user_id not in user_ids: users.add(User.get_instance(user_id)) user_ids.add(user_id) for user in users: has_role_text = 'has_%s_%d' % (role, user.id) if (user.id, role) not in user_roles_as_set and \ has_role_text in request.POST: ur = UserRole( role=roles_by_name[role], user=user) user_roles.append(ur) user_roles_dict[(user.id, role)] = ur user_roles_as_set.add((user.id, role)) db.add(ur) elif (user.id, role) in user_roles_as_set and \ has_role_text not in request.POST: ur = user_roles_dict[(user.id, role)] del user_roles_dict[(user.id, role)] user_roles_as_set.remove((user.id, role)) user_roles.remove(ur) db.delete(ur) elif 'submit_look_for_user' in request.POST: search_string = '%' + request.POST['user_search'] + '%' other_users = db.query(User).join(AgentProfile).filter(AgentProfile.name.ilike(search_string)).union( db.query(User).outerjoin(Username).filter(Username.username.ilike(search_string))).union( db.query(User).filter(User.preferred_email.ilike(search_string))).all() users.update(other_users) def has_role(user_id, role): return (user_id, role) in user_roles_as_set context = dict( roles=role_names, permissions=permission_names, users=users, has_role=has_role, is_system_role=lambda r: r in SYSTEM_ROLES ) return render_to_response( 'admin/global_permissions.jinja2', context, request=request)
def home_view(request): user_id = authenticated_userid(request) or Everyone context = get_default_context(request) discussion = context["discussion"] canRead = user_has_permission(discussion.id, user_id, P_READ) if not canRead and user_id == Everyone: # User isn't logged-in and discussion isn't public: # redirect to login page login_url = request.route_url( 'contextual_login', discussion_slug=discussion.slug) return HTTPSeeOther(login_url) elif not canRead: # User is logged-in but doesn't have access to the discussion return HTTPUnauthorized() # if the route asks for a post, get post content (because this is needed for meta tags) route_name = request.matched_route.name if route_name == "purl_posts": post_id = FrontendUrls.getRequestedPostId(request) if post_id: post = Post.get_instance(post_id) if post and post.discussion_id == discussion.id: context['post'] = post elif route_name == "purl_idea": idea_id = FrontendUrls.getRequestedIdeaId(request) if idea_id: idea = Idea.get_instance(idea_id) if idea and idea.discussion_id == discussion.id: context['idea'] = idea canAddExtract = user_has_permission(discussion.id, user_id, P_ADD_EXTRACT) context['canAddExtract'] = canAddExtract context['canDisplayTabs'] = True if user_id != Everyone: from assembl.models import AgentProfile user = AgentProfile.get(user_id) # TODO: user may not exist. Case of session with BD change. user.is_visiting_discussion(discussion.id) session = Discussion.db() current_prefs = session.query(UserLanguagePreference).\ filter_by(user_id = user_id).all() user = session.query(User).filter_by(id = user_id).first() if '_LOCALE_' in request.cookies: locale = request.cookies['_LOCALE_'] posix_locale = to_posix_format(locale) process_locale(posix_locale,user_id, current_prefs, session, LanguagePreferenceOrder.Cookie) elif '_LOCALE_' in request.params: locale = request.params['_LOCALE_'] posix_locale = to_posix_format(locale) process_locale(posix_locale, user_id, current_prefs, session, LanguagePreferenceOrder.Parameter) else: locale = default_locale_negotiator(request) posix_locale = to_posix_format(locale) process_locale(posix_locale, user_id, current_prefs, session, LanguagePreferenceOrder.OS_Default) response = render_to_response('../../templates/index.jinja2', context, request=request) # Prevent caching the home, especially for proper login/logout response.cache_control.max_age = 0 response.cache_control.prevent_auto = True return response