def put_permissions_for_role(request): discussion = request.context role_name = request.matchdict['role_name'] session = Discussion.default_db role = Role.get_by(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(Permission.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_by_permission.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 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), 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 discussion_permissions(request): user_id = authenticated_userid(request) assert user_id db = Discussion.default_db discussion_id = int(request.matchdict['discussion_id']) discussion = Discussion.get_instance(discussion_id) error = '' 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] role_names.sort() permissions = db.query(Permission).all() perms_by_name = {p.name: p for p in permissions} permission_names = [p.name for p in permissions] permission_names.sort() 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) num_users = '' 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): a_user_id = int(name[len(prefix):]) if a_user_id not in user_ids: users.add(User.get_instance(a_user_id)) user_ids.add(a_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) # TODO revisit this if Roles and Subscription are # de-coupled if role == 'r:participant': user.update_agent_status_subscribe(discussion) 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) # TODO revisit this if Roles and Subscription are # de-coupled if role == 'r:participant': user.update_agent_status_unsubscribe(discussion) db.delete(lur) elif 'submit_look_for_user' in request.POST: search_string = '%' + request.POST['user_search'] + '%' other_users = db.query(User).outerjoin(Username).filter( AgentProfile.name.ilike(search_string) | Username.username.ilike(search_string) | User.preferred_email.ilike(search_string)).all() users.update(other_users) elif 'submit_user_file' in request.POST: role = request.POST['add_with_role'] or R_PARTICIPANT if role == R_SYSADMIN and not user_has_permission( discussion_id, user_id, P_SYSADMIN): role = R_ADMINISTRATOR if 'user_csvfile' in request.POST: try: num_users = add_multiple_users_csv( request, request.POST['user_csvfile'].file, discussion_id, role, request.POST.get('send_invite', False), request.POST['email_subject'], request.POST['text_email_message'], request.POST['html_email_message'], request.POST['sender_name'], request.POST.get('resend_notloggedin', False)) except Exception as e: error = repr(e) transaction.doom() else: error = request.localizer.translate(_('No file given.')) 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 users = list(users) users.sort(key=order_by_domain_and_name) context = dict(get_default_context(request), discussion=discussion, allowed=allowed, roles=role_names, permissions=permission_names, users=users, error=error, num_users=num_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)
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() elif raven_client: raven_client.captureException()