def verify_password_change_token(token, max_age=None): data, valid = verify_data_token(token, max_age=max_age) if valid == Validity.BAD_HASH: try: data = int(data) except: return None, Validity.INVALID_FORMAT user = User.get(data) if not user: return None, Validity.DATA_NOT_FOUND password = user.password.decode( 'iso-8859-1') if user.password else 'empty' data, valid = verify_data_token(token, password, max_age) return user, valid # Try decoding legacy try: id, hash = token.split('e', 1) id = int(id) user = User.get(id) if not user: return user, Validity.DATA_NOT_FOUND age = datetime.utcnow() - user.last_login if age > timedelta(days=3): return user, Validity.EXPIRED check = str(id) + user.last_login.isoformat()[:19] valid = verify_password(check, hash, HashEncoding.HEX) if not valid: return user, Validity.BAD_HASH return user, Validity.VALID except: return None, Validity.INVALID_FORMAT
def put_global_roles_for_user(request): user_id = request.matchdict['user_id'] user = User.get_instance(user_id) session = User.db() 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") 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_gu_roles = session.query(UserRole).join(Role).filter( user=user).all() gur_by_role = {gur.role.name: gur for gur in known_gu_roles} known_roles = set(gur_by_role.keys()) for role in known_roles - roles: session.query.delete(gur_by_role(role)) for role in roles - known_roles: session.add(UserRole(user=user, role=role)) return {"added": list(roles - known_roles), "removed": list(known_roles - roles)}
def admin_user(request, test_session): """A User fixture with R_SYSADMIN role""" from assembl.models import User, Username, UserRole, Role u = User(name=u"Mr. Administrator", type="user", verified=True, last_assembl_login=datetime.utcnow()) u.username_p = "mr_admin_user" from assembl.models import EmailAccount account = EmailAccount(email="*****@*****.**", profile=u, verified=True) test_session.add(u) test_session.add(account) r = Role.get_role(R_SYSADMIN, test_session) ur = UserRole(user=u, role=r) test_session.add(ur) test_session.flush() uid = u.id def fin(): print "finalizer admin_user" # I often get expired objects here, and I need to figure out why user = test_session.query(User).get(uid) user_role = user.roles[0] test_session.delete(user_role) test_session.delete(account) test_session.delete(user.username) test_session.delete(user) test_session.flush() request.addfinalizer(fin) return u
def participant1_user(request, test_session, discussion): """A User fixture with R_PARTICIPANT global role and with R_PARTICIPANT local role in discussion `discussion`""" from assembl.models import User, UserRole, Role, EmailAccount u = User(name=u"A. Barking Loon", type="user", password="******", verified=True, last_assembl_login=datetime.utcnow()) email = EmailAccount(email="*****@*****.**", profile=u, verified=True) test_session.add(u) r = Role.get_role(R_PARTICIPANT, test_session) ur = UserRole(user=u, role=r) test_session.add(ur) u.subscribe(discussion) test_session.flush() def fin(): print "finalizer participant1_user" test_session.delete(u) test_session.flush() request.addfinalizer(fin) return u
def verify_password_change_token(token, max_age=None): data, valid = verify_data_token(token, max_age=max_age) if valid == Validity.BAD_HASH: try: data = int(data) except: return None, Validity.INVALID_FORMAT user = User.get(data) if not user: return None, Validity.DATA_NOT_FOUND password = user.password.decode('iso-8859-1') if user.password else 'empty' data, valid = verify_data_token(token, password, max_age) return user, valid # Try decoding legacy try: id, hash = token.split('e', 1) id = int(id) user = User.get(id) if not user: return user, Validity.DATA_NOT_FOUND age = datetime.utcnow() - user.last_login if age > timedelta(days=3): return user, Validity.EXPIRED check = str(id) + user.last_login.isoformat()[:19] valid = verify_password( check, hash, HashEncoding.HEX) if not valid: return user, Validity.BAD_HASH return user, Validity.VALID except: return None, Validity.INVALID_FORMAT
def discussion_sysadmin_user(request, test_app, test_session, discussion): """A User fixture with R_SYSADMIN role in a discussion""" from datetime import datetime from assembl.auth import R_SYSADMIN from assembl.models import User from assembl.models.auth import Role, LocalUserRole, UserRole u = User(name=u"Maximilien de Robespierre 3", type="user", last_assembl_login=datetime.utcnow()) test_session.add(u) u.update_agent_status_last_visit(discussion) role = Role.get_role(R_SYSADMIN, test_session) test_session.add(UserRole(user=u, role=role)) test_session.flush() def fin(): print "finalizer discussion_sysadmin_user" test_session.delete(u) test_session.flush() request.addfinalizer(fin) return u
def admin_user(request, test_session): """A User fixture with R_SYSADMIN role""" from assembl.models import User, Username, UserRole, Role u = User(name=u"Mr. Administrator", type="user", verified=True, last_assembl_login=datetime.utcnow()) u.username_p = "mr_admin_user" from assembl.models import EmailAccount account = EmailAccount(email="*****@*****.**", profile=u, verified=True) test_session.add(u) test_session.add(account) r = Role.get_role(R_SYSADMIN, test_session) ur = UserRole(user=u, role=r) test_session.add(ur) test_session.flush() uid = u.id def fin(): print("finalizer admin_user") # I often get expired objects here, and I need to figure out why user = test_session.query(User).get(uid) user_role = user.roles[0] test_session.delete(user_role) account = user.accounts[0] test_session.delete(account) test_session.delete(user.username) test_session.delete(user) test_session.flush() request.addfinalizer(fin) return u
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 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 add_local_role(request): # Do not use check_permissions, this is a special case ctx = request.context user_id = authenticated_userid(request) if user_id == Everyone: raise HTTPUnauthorized() discussion_id = ctx.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 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) view = request.GET.get('view', None) or 'default' permissions = get_permissions( user_id, ctx.get_discussion_id()) return Response( dumps(first.generic_json(view, user_id, permissions)), location=first.uri_generic(first.id), status_code=201)
def voting_widget_view(request): user_id = authenticated_userid(request) or Everyone ctx = request.context view = (request.matchdict or {}).get('view', None)\ or ctx.get_default_view() or 'default' widget = ctx._instance permissions = get_permissions(user_id, ctx.get_discussion_id()) json = widget.generic_json(view, user_id, permissions) #json['discussion'] = ... if user_id != Everyone: user = User.get(user_id) json['user'] = user.generic_json(view, user_id, permissions) json['user_permissions'] = get_permissions(user_id, widget.get_discussion_id()) user_state = widget.get_user_state(user_id) if user_state is not None: json['user_state'] = user_state target_id = request.GET.get('target', None) if target_id and Idea.get_database_id(target_id): json['user_votes_url'] = widget.get_user_votes_url(target_id) json['voting_urls'] = widget.get_voting_urls(target_id) json['criteria'] = [ idea.generic_json(view, user_id, permissions) for idea in widget.criteria ] return json
def widget_view(request): # IF_OWNED not applicable for widgets... so far ctx = request.context user_id = authenticated_userid(request) or Everyone permissions = get_permissions(user_id, ctx.get_discussion_id()) check_permissions(ctx, user_id, permissions, CrudPermissions.READ) view = (request.matchdict or {}).get('view', None)\ or ctx.get_default_view() or 'default' json = ctx._instance.generic_json(view, user_id, permissions) # json['discussion'] = ... if user_id != Everyone: user = User.get(user_id) user_state = ctx._instance.get_user_state(user_id) json['user'] = user.generic_json(view, user_id, permissions) json['user_permissions'] = get_permissions( user_id, ctx._instance.get_discussion_id()) if user_state is not None: json['user_state'] = user_state target_id = request.GET.get('target', None) if target_id: idea = Idea.get_instance(target_id) if idea: json['target'] = idea.generic_json(view, user_id, permissions) else: return HTTPNotFound("No idea " + target_id) return json
def request_password_change(request): localizer = request.localizer identifier = request.params.get('identifier') or '' user_id = request.params.get('user_id') or '' error = request.params.get('error') or '' user = None if user_id: try: user = User.get(int(user_id)) identifier = identifier or user.get_preferred_email() or '' except: error = error or localizer.translate(_("This user cannot be found")) elif identifier: user, account = from_identifier(identifier) if user: user_id = user.id else: error = error or localizer.translate(_("This user cannot be found")) if error or not user: context = get_default_context(request) get_route = context['get_route'] request.session.flash(error) return HTTPFound(location=get_route('react_request_password_change')) discussion_slug = request.matchdict.get('discussion_slug', None) route = 'password_change_sent' if discussion_slug: route = 'contextual_' + route return HTTPFound(location=maybe_contextual_route( request, 'password_change_sent', profile_id=user_id, _query=dict(email=identifier if '@' in identifier else '')))
def votes_collection_add_json(request): ctx = request.context user_id = authenticated_userid(request) permissions = get_permissions( user_id, ctx.get_discussion_id()) check_permissions(ctx, user_id, permissions, CrudPermissions.CREATE) typename = ctx.collection_class.external_typename() typename = request.json_body.get( '@type', ctx.collection_class.external_typename()) json = request.json_body json['voter'] = User.uri_generic(user_id) try: instances = ctx.create_object(typename, json, user_id) except Exception as e: raise HTTPBadRequest(e) if instances: first = instances[0] db = first.db() for instance in instances: db.add(instance) db.flush() view = request.GET.get('view', None) or 'default' return Response( dumps(first.generic_json(view, user_id, permissions)), location=first.uri_generic(first.id), status_code=201)
def maybe_merge( backend, details, user=None, other_users=None, *args, **kwargs): # If we do not already have a user, see if we're in a situation # where we're adding an account to an existing user, and maybe # even merging request = backend.strategy.request adding_account = request.session.get("add_account", None) if adding_account is not None: del request.session["add_account"] # current discussion and next? logged_in = request.authenticated_userid if logged_in: logged_in = User.get(logged_in) if adding_account: if user and user != logged_in: # logged_in presumably newer? logged_in.merge(user) logged_in.db.delete(user) logged_in.db.flush() user = logged_in else: forget(request) if other_users: if not user: user = other_users.pop(0) # Merge other accounts with same verified email for profile in other_users: user.merge(profile) profile.delete() return {"user": user}
def set_local_role(request): # Do not use check_permissions, this is a special case ctx = request.context instance = ctx._instance user_id = authenticated_userid(request) if not user_id: raise HTTPUnauthorized() discussion_id = ctx.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 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 elif P_SELF_REGISTER_REQUEST in permissions: json['requested'] = True else: raise HTTPUnauthorized() updated = instance.update_from_json(json, user_id, ctx) view = request.GET.get('view', None) or 'default' if view == 'id_only': return [updated.uri()] else: return updated.generic_json(view, user_id, permissions)
def widget_view(request): # IF_OWNED not applicable for widgets... so far ctx = request.context user_id = authenticated_userid(request) or Everyone permissions = get_permissions( user_id, ctx.get_discussion_id()) check_permissions(ctx, user_id, permissions, CrudPermissions.READ) view = (request.matchdict or {}).get('view', None)\ or ctx.get_default_view() or 'default' json = ctx._instance.generic_json(view, user_id, permissions) # json['discussion'] = ... if user_id != Everyone: user = User.get(user_id) user_state = ctx._instance.get_user_state(user_id) json['user'] = user.generic_json(view, user_id, permissions) json['user_permissions'] = get_permissions( user_id, ctx._instance.get_discussion_id()) if user_state is not None: json['user_state'] = user_state target_id = request.GET.get('target', None) if target_id: idea = Idea.get_instance(target_id) if idea: json['target'] = idea.generic_json(view, user_id, permissions) else: return HTTPNotFound("No idea "+target_id) return json
def voting_widget_view(request): user_id = authenticated_userid(request) or Everyone ctx = request.context view = (request.matchdict or {}).get('view', None)\ or ctx.get_default_view() or 'default' widget = ctx._instance permissions = get_permissions( user_id, ctx.get_discussion_id()) json = widget.generic_json(view, user_id, permissions) #json['discussion'] = ... if user_id != Everyone: user = User.get(user_id) json['user'] = user.generic_json(view, user_id, permissions) json['user_permissions'] = get_permissions( user_id, widget.get_discussion_id()) user_state = widget.get_user_state(user_id) if user_state is not None: json['user_state'] = user_state target_id = request.GET.get('target', None) if target_id and Idea.get_database_id(target_id): json['user_votes_url'] = widget.get_user_votes_url(target_id) json['voting_urls'] = widget.get_voting_urls(target_id) json['criteria'] = [idea.generic_json(view, user_id, permissions) for idea in widget.criteria] return json
def participant1_user(request, test_session, discussion): from assembl.models import User, UserRole, Role u = User(name=u"A. Barking Loon", type="user") test_session.add(u) r = Role.get_role(test_session, R_PARTICIPANT) ur = UserRole(user=u, role=r) test_session.add(ur) u.subscribe(discussion) test_session.flush() def fin(): print "finalizer participant1_user" test_session.delete(u) test_session.flush() request.addfinalizer(fin) return u
def finish_password_change(request): logged_in = authenticated_userid(request) if not logged_in: raise HTTPUnauthorized() user = User.get(logged_in) localizer = request.localizer discussion_slug = request.matchdict.get('discussion_slug', None) error = None p1, p2 = (request.params.get('password1', '').strip(), request.params.get('password2', '').strip()) if p1 != p2: error = localizer.translate(_('The passwords are not identical')) elif p1: user.password_p = p1 return HTTPFound(location=request.route_url( 'home' if discussion_slug else 'discussion_list', discussion_slug=discussion_slug, _query=dict( message=localizer.translate(_( "Password changed"))))) slug_prefix = "/" + discussion_slug if discussion_slug else "" return dict( get_default_context(request), slug_prefix=slug_prefix, error=error)
def do_password_change(request): localizer = request.localizer token = request.matchdict.get('ticket') (verified, user_id) = verify_password_change_token(token, 24) if not verified: if not user_id: raise HTTPBadRequest( localizer.translate(_("Wrong password token."))) else: return HTTPFound(location=maybe_contextual_route( request, 'password_change_sent', profile_id=user_id, _query=dict(sent=True, error=localizer.translate( _("This token is expired. " "Do you want us to send another?"))))) user = User.get(user_id) headers = remember(request, user_id) request.response.headerlist.extend(headers) user.last_login = datetime.utcnow() slug = request.matchdict.get('discussion_slug', None) slug_prefix = "/" + slug if slug else "" return dict(get_default_context(request), slug_prefix=slug_prefix, title=localizer.translate(_('Change your password')))
def discussion_list_view(request): request.session.pop('discussion') user_id = authenticated_userid(request) or Everyone user = None if user_id != Everyone: user = User.get(user_id) roles = get_roles(user_id) context = get_default_context(request) context['discussions'] = [] # Show even anonymous users every discussion one has access to if # authenticated, so they can login and read them discussions = discussions_with_access(Authenticated if user_id == Everyone else user_id) for discussion in discussions: discussionFrontendUrls = FrontendUrls(discussion) discussion_context = { 'topic': discussion.topic, 'slug': discussion.slug, 'url': discussionFrontendUrls.get_discussion_url() } if user_has_permission(discussion.id, user_id, P_ADMIN_DISC): discussion_context[ 'admin_url'] = discussionFrontendUrls.get_discussion_edition_url( ) discussion_context['permissions_url'] = request.route_url( 'discussion_permissions', discussion_id=discussion.id) context['discussions'].append(discussion_context) if R_SYSADMIN in roles: context['discussions_admin_url'] = request.route_url( 'discussion_admin') context['permissions_admin_url'] = request.route_url( 'general_permissions') context['user'] = user return context
def discussion_list_view(request): user_id = authenticated_userid(request) or Everyone user = None if user_id != Everyone: user = User.get(user_id) roles = get_roles(user_id) context = get_default_context(request) context['discussions'] = [] #Show even anonymous users every discussion one has access to if #authenticated, so they can login and read them discussions = discussions_with_access(Authenticated if user_id == Everyone else user_id) for discussion in discussions: discussionFrontendUrls = FrontendUrls(discussion) discussion_context = { 'topic': discussion.topic, 'slug': discussion.slug, 'url': discussionFrontendUrls.get_discussion_url() } if user_has_permission(discussion.id, user_id, P_ADMIN_DISC): discussion_context['admin_url'] = discussionFrontendUrls.get_discussion_edition_url() discussion_context['permissions_url'] = request.route_url( 'discussion_permissions', discussion_id=discussion.id) context['discussions'].append(discussion_context) if R_SYSADMIN in roles: context['discussions_admin_url'] = request.route_url('discussion_admin') context['permissions_admin_url'] = request.route_url('general_permissions') context['user'] = user return context
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.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 maybe_merge(backend, details, user=None, other_users=None, *args, **kwargs): # If we do not already have a user, see if we're in a situation # where we're adding an account to an existing user, and maybe # even merging request = backend.strategy.request adding_account = request.session.get("add_account", None) if adding_account is not None: del request.session["add_account"] # current discussion and next? logged_in = request.authenticated_userid if logged_in: logged_in = User.get(logged_in) if adding_account: if user and user != logged_in: # logged_in presumably newer? logged_in.merge(user) logged_in.db.delete(user) logged_in.db.flush() user = logged_in else: forget(request) if other_users: if not user: user = other_users.pop(0) # Merge other accounts with same verified email for profile in other_users: user.merge(profile) profile.delete() return {"user": user}
def put_discussion_roles_for_user(request): discussion = request.context 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 do_password_change(request): localizer = request.localizer token = request.matchdict.get('ticket') (verified, user_id) = verify_password_change_token(token, 24) if not verified: if not user_id: raise HTTPBadRequest(localizer.translate(_( "Wrong password token."))) else: return HTTPFound(location=maybe_contextual_route( request, 'password_change_sent', profile_id=user_id, _query=dict( sent=True, error=localizer.translate(_( "This token is expired. " "Do you want us to send another?"))))) user = User.get(user_id) headers = remember(request, user_id) request.response.headerlist.extend(headers) user.last_login = datetime.utcnow() slug = request.matchdict.get('discussion_slug', None) slug_prefix = "/" + slug if slug else "" return dict( get_default_context(request), slug_prefix=slug_prefix, title=localizer.translate(_('Change your password')))
def get_global_roles_for_user(request): user_id = request.matchdict['user_id'] session = User.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( UserRole).filter(UserRole.user_id == user_id) return [x[0] for x in rolenames]
def post_put_json(request): json_data = request.json_body if has_moderation(json_data): raise_if_cannot_moderate(request) json_data['moderated_on'] = datetime.utcnow().isoformat()+"Z" json_data['moderator'] = User.uri_generic( authenticated_userid(request)) return instance_put_json(request, json_data)
def get_global_roles_for_user(request): user_id = request.matchdict['user_id'] user = User.get_instance(user_id) if not user: raise HTTPNotFound("User id %s does not exist" % (user_id,)) rolenames = User.default_db.query(Role.name).join( UserRole).filter(UserRole.user == user) return [x[0] for x in rolenames]
def get_global_roles_for_user(request): user_id = request.matchdict['user_id'] user = User.get_instance(user_id) if not user: raise HTTPNotFound("User id %s does not exist" % (user_id,)) rolenames = User.db.query(Role.name).join( UserRole).filter(UserRole.user == user) return [x[0] for x in rolenames]
def participant1_user(request, test_session, discussion): from assembl.models import User, UserRole, Role, EmailAccount u = User(name=u"A. Barking Loon", type="user", password="******", verified=True) email = EmailAccount(email="*****@*****.**", profile=u, verified=True) test_session.add(u) r = Role.get_role(R_PARTICIPANT, test_session) ur = UserRole(user=u, role=r) test_session.add(ur) u.subscribe(discussion) test_session.flush() def fin(): print "finalizer participant1_user" test_session.delete(u) test_session.flush() request.addfinalizer(fin) return u
def discussion_list_view(request): user_id = authenticated_userid(request) or Everyone user = None if user_id != Everyone: user = User.get(id=user_id) context = get_default_context() context['discussions'] = discussions_with_access(user_id) context['user'] = user return context
def post_put(request): form_data = request.params if has_moderation(form_data): raise_if_cannot_moderate(request) form_data = dict(form_data) form_data['moderated_on'] = datetime.utcnow().isoformat()+"Z" form_data['moderator'] = User.uri_generic( authenticated_userid(request)) return instance_put_form(request, form_data)
def get_user_has_permission(request): discussion = request.context user_id = request.matchdict['user_id'] permission = request.matchdict['permission'] 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_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_discussion_roles_for_user(request): discussion = request.context user_id = request.matchdict['user_id'] user = User.get_instance(user_id) session = Discussion.default_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_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 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 votes_collection_add_json(request): ctx = request.context user_id = authenticated_userid(request) if not user_id: raise HTTPUnauthorized permissions = ctx.get_permissions() check_permissions(ctx, user_id, CrudPermissions.CREATE) spec = ctx.get_instance_of_class(AbstractVoteSpecification) if spec: required = spec.get_vote_class() else: required = ctx.collection_class widget = ctx.get_instance_of_class(VotingWidget) if not widget and spec: widget = spec.widget if not widget: raise HTTPBadRequest("Please provide a reference to a widget") if widget.activity_state != 'active': raise HTTPUnauthorized("Not in voting period") typename = request.json_body.get('@type', None) if typename: cls = get_named_class(typename) if not issubclass(cls, required): raise HTTPBadRequest("@type is %s, should be in %s" % ( typename, spec.get_vote_class().__name__)) else: typename = required.external_typename() json = request.json_body json['voter'] = User.uri_generic(user_id) if "@type" not in json: json["@type"] = typename else: pass # TODO: Check subclass try: instances = ctx.create_object(typename, json) except Exception as e: raise HTTPBadRequest(e) if instances: first = instances[0] db = first.db for instance in instances: db.add(instance) db.flush() # validate after flush so we can check validity with DB constraints if not first.is_valid(): raise HTTPBadRequest("Invalid vote") view = request.GET.get('view', None) or 'default' return Response( dumps(first.generic_json(view, user_id, permissions)), location=first.uri_generic(first.id), status_code=201)
def get_all_roles_for_user(request): discussion = request.context user_id = request.matchdict['user_id'] user = User.get_instance(user_id) db = Discussion.default_db if not user: raise HTTPNotFound("User id %d does not exist" % (user_id,)) rolenames = db.query(Role.name ).join(LocalUserRole ).filter(LocalUserRole.user == user, LocalUserRole.discussion_id == discussion.id ).union(db.query(Role.name).join( UserRole).filter(UserRole.user == user)).distinct() return [x for (x,) in rolenames]
def admin_user(request, test_session, db_default_data): from assembl.models import User, UserRole, Role u = User(name=u"Mr. Administrator", type="user") test_session.add(u) r = Role.get_role(R_SYSADMIN, test_session) ur = UserRole(user=u, role=r) test_session.add(ur) test_session.flush() def fin(): print "finalizer admin_user" test_session.delete(u) test_session.flush() request.addfinalizer(fin) return u
def moderator_user(request, test_session, discussion): """A User fixture with R_MODERATOR role""" from assembl.models import User, UserRole, Role, EmailAccount u = User(name=u"Jane Doe", type="user", password="******", verified=True, last_assembl_login=datetime.utcnow()) email = EmailAccount(email="*****@*****.**", profile=u, verified=True) test_session.add(u) r = Role.get_role(R_MODERATOR, test_session) ur = UserRole(user=u, role=r) test_session.add(ur) u.subscribe(discussion) test_session.flush() def fin(): print "finalizer moderator_user" test_session.delete(u) test_session.flush() request.addfinalizer(fin) return u
def participant2_user(request, test_session): from assembl.models import User, UserRole, Role u = User(name=u"James T. Expert", type="user") test_session.add(u) r = Role.get_role(R_PARTICIPANT, test_session) ur = UserRole(user=u, role=r) test_session.add(ur) test_session.flush() def fin(): print "finalizer participant2_user" test_session.delete(u) test_session.flush() request.addfinalizer(fin) return u
def participant2_user(request, test_session): """A User fixture with R_PARTICIPANT role""" from assembl.models import User, UserRole, Role u = User(name=u"James T. Expert", type="user", last_idealoom_login=datetime.utcnow()) test_session.add(u) r = Role.get_role(R_PARTICIPANT, test_session) ur = UserRole(user=u, role=r) test_session.add(ur) test_session.flush() def fin(): print("finalizer participant2_user") test_session.delete(u) test_session.flush() request.addfinalizer(fin) return u
def votes_collection_add_json(request): ctx = request.context user_id = authenticated_userid(request) if not user_id: raise HTTPUnauthorized permissions = get_permissions( user_id, ctx.get_discussion_id()) check_permissions(ctx, user_id, permissions, CrudPermissions.CREATE) widget = ctx.get_instance_of_class(MultiCriterionVotingWidget) if widget.activity_state != 'active': raise HTTPUnauthorized("Not in voting period") spec = ctx.get_instance_of_class(AbstractVoteSpecification) if spec: required = spec.get_vote_class() else: required = ctx.collection_class typename = request.json_body.get('@type', None) if typename: cls = get_named_class(typename) if not issubclass(cls, required): raise HTTPBadRequest("@type is %s, should be in %s" % ( typename, spec.get_vote_class().__name__)) else: typename = required.external_typename() json = request.json_body json['voter'] = User.uri_generic(user_id) try: instances = ctx.create_object(typename, json, user_id) except Exception as e: raise HTTPBadRequest(e) if instances: first = instances[0] db = first.db for instance in instances: db.add(instance) db.flush() # validate after flush so we can check validity with DB constraints if not first.is_valid(): raise HTTPBadRequest("Invalid vote") view = request.GET.get('view', None) or 'default' return Response( dumps(first.generic_json(view, user_id, permissions)), location=first.uri_generic(first.id), status_code=201)
def votes_collection_add_json(request): ctx = request.context user_id = authenticated_userid(request) if not user_id: raise HTTPUnauthorized permissions = get_permissions( user_id, ctx.get_discussion_id()) check_permissions(ctx, user_id, permissions, CrudPermissions.CREATE) widget = ctx.get_instance_of_class(MultiCriterionVotingWidget) if widget.activity_state != 'active': raise HTTPUnauthorized("Not in voting period") spec = ctx.get_instance_of_class(AbstractVoteSpecification) if spec: required = spec.get_vote_class() else: required = ctx.collection_class typename = request.json_body.get('@type', None) if typename: cls = get_named_class(typename) if not issubclass(cls, required): raise HTTPBadRequest("@type is %s, should be in %s" % ( typename, spec.get_vote_class().__name__)) else: typename = required.external_typename() json = request.json_body json['voter'] = User.uri_generic(user_id) try: instances = ctx.create_object(typename, json, user_id) except Exception as e: raise HTTPBadRequest(e) if instances: first = instances[0] if not first.is_valid(): raise HTTPBadRequest("Invalid vote") db = first.db for instance in instances: db.add(instance) db.flush() view = request.GET.get('view', None) or 'default' return Response( dumps(first.generic_json(view, user_id, permissions)), location=first.uri_generic(first.id), status_code=201)
def admin_user(request, test_session, db_default_data): """A User fixture with R_SYSADMIN role""" from assembl.models import User, UserRole, Role u = User(name=u"Mr. Administrator", type="user") test_session.add(u) r = Role.get_role(R_SYSADMIN, test_session) ur = UserRole(user=u, role=r) test_session.add(ur) test_session.flush() uid = u.id def fin(): print("finalizer admin_user") # I often get expired objects here, and I need to figure out why user = test_session.query(User).get(uid) user_role = user.roles[0] test_session.delete(user_role) test_session.delete(user) test_session.flush() request.addfinalizer(fin) return u
def post_put(request): form_data = request.params if has_moderation(form_data): raise_if_cannot_moderate(request) form_data = dict(form_data) form_data['moderated_on'] = datetime.utcnow().isoformat()+"Z" form_data['moderator'] = User.uri_generic( request.authenticated_userid) ctx = request.context user_id = request.authenticated_userid or Everyone permissions = get_permissions( user_id, ctx.get_discussion_id()) post = ctx._instance discussion = post.discussion if (post.publication_state == models.PublicationStates.PUBLISHED and P_MODERATE not in permissions and discussion.preferences['with_moderation']): raise HTTPUnauthorized() # TODO: apply guess_languages return instance_put_form(request, form_data)
def delete_local_role(request): ctx = request.context instance = ctx._instance user_id = request.authenticated_userid if not user_id: raise HTTPUnauthorized() discussion_id = ctx.get_discussion_id() if discussion_id is None: raise HTTPBadRequest() permissions = get_permissions(user_id, discussion_id) requested_user = instance.user if requested_user.id != user_id and P_ADMIN_DISC not in permissions: raise HTTPUnauthorized() user = User.get(user_id) discussion = Discussion.get(discussion_id) instance.db.delete(instance) # Update the user's AgentStatusInDiscussion user.update_agent_status_unsubscribe(discussion) instance.db.flush() # maybe unnecessary return {}
def maybe_social_logout(request): """If the user has a an account with the default social provider, and that account has a logout URL, redirect there. Maybe the next argument should be carried?""" discussion = discussion_from_request(request) if not discussion: return backend_name = discussion.preferences['authorization_server_backend'] if not backend_name: return user_id = request.authenticated_userid if not user_id: return user = User.get(user_id) for account in user.accounts: if getattr(account, 'provider_with_idp', None) == backend_name: break else: return # TODO: tell the account that the login has expired. # Also check if already expired? return config.get('SOCIAL_AUTH_%s_LOGOUT_URL' % ( account.provider.upper(),))
def request_password_change(request): localizer = request.localizer identifier = request.params.get('identifier') or '' user_id = request.params.get('user_id') or '' error = request.params.get('error') or '' user = None if user_id: try: user = User.get(int(user_id)) identifier = identifier or user.get_preferred_email() or '' except: error = error or localizer.translate(_("This user cannot be found")) elif identifier: user, account = from_identifier(identifier) if user: user_id = user.id else: error = error or localizer.translate(_("This user cannot be found")) if error or not user: slug = request.matchdict.get('discussion_slug', None) return dict( get_default_context(request), error=error, user_id=user_id, identifier=identifier, slug_prefix="/" + slug if slug else "", title=localizer.translate(_('I forgot my password'))) discussion_slug = request.matchdict.get('discussion_slug', None) route = 'password_change_sent' if discussion_slug: route = 'contextual_' + route return HTTPFound(location=maybe_contextual_route( request, 'password_change_sent', profile_id=user_id, _query=dict(email=identifier if '@' in identifier else '')))