Esempio n. 1
0
def add_multiple_users_csv(
        request, csv_file, discussion_id, with_role,
        send_password_change=False, message_subject=None,
        text_message=None, html_message=None):
    r = reader(csv_file)
    localizer = request.localizer
    for i, l in enumerate(r):
        if not len(l):
            # tolerate empty lines
            continue
        l = [x.decode('utf-8').strip() for x in l]
        if send_password_change:
            if len(l) != 2:
                raise RuntimeError(localizer.translate(_(
                    "The CSV file must have two columns")))
            (name, email) = l
            password = base64.urlsafe_b64encode(urandom(8))
        else:
            if len(l) != 3:
                raise RuntimeError(localizer.translate(_(
                    "The CSV file must have three columns")))
            (name, email, password) = l
        if not is_email(email):
            if i == 0:
                # Header
                continue
            raise RuntimeError(localizer.translate(_(
                "Not an email: <%s> at line %d")) % (email, i))
        if len(name) < 5:
            raise RuntimeError(localizer.translate(_(
                "Name too short: <%s> at line %d")) % (name, i))
        if len(password) < 4:
            raise RuntimeError(localizer.translate(_(
                "Password too short: <%s> at line %d")) % (password, i))
        (user, is_new) = add_user(
            name, email, password, None, True, localrole=with_role,
            discussion=discussion_id, change_old_password=False)
        if is_new and send_password_change:
            from assembl.views.auth.views import send_change_password_email
            from assembl.models import Discussion
            discussion = Discussion.get(discussion_id)
            send_change_password_email(
                request, user, email, subject=message_subject,
                text_body=text_message, html_body=html_message,
                discussion=discussion)
    return i
Esempio n. 2
0
def add_multiple_users_csv(
        request, csv_file, discussion_id, with_role,
        send_password_change=False, message_subject=None,
        text_message=None, html_message=None, sender_name=None,
        resend_if_not_logged_in=False):
    csv_file = TextIOWrapper(BytesIO(csv_file.read()), 'utf-8')
    r = reader(csv_file, skipinitialspace=True)
    localizer = request.localizer
    for i, l in enumerate(r):
        if not len(l):
            # tolerate empty lines
            continue
        l = [x.strip() for x in l]
        if len(l) != 2:
            raise RuntimeError(localizer.translate(_(
                "The CSV file must have two columns")))
        (name, email) = l
        if not is_email(email):
            if i == 0:
                # Header
                continue
            raise RuntimeError(localizer.translate(_(
                "Not an email: <%s> at line %d")) % (email, i))
        if len(name) < 5:
            raise RuntimeError(localizer.translate(_(
                "Name too short: <%s> at line %d")) % (name, i))
        (user, created_user, created_localrole) = add_user(
            name, email, None, None, True, localrole=with_role,
            discussion=discussion_id, change_old_password=False)
        status_in_discussion = None
        if send_password_change and not (created_user or created_localrole):
            status_in_discussion = user.get_status_in_discussion(discussion_id)
        if send_password_change and (
                created_user or created_localrole or (
                    resend_if_not_logged_in and (
                        status_in_discussion is None or
                        not status_in_discussion.first_visit))):
            from assembl.views.auth.views import send_change_password_email
            from assembl.models import Discussion
            discussion = Discussion.get(discussion_id)
            send_change_password_email(
                request, user, email, subject=message_subject,
                text_body=text_message, html_body=html_message,
                discussion=discussion, sender_name=sender_name, welcome=True)
    return i
Esempio n. 3
0
def add_multiple_users_csv(
        request, csv_file, discussion_id, with_role,
        send_password_change=False, message_subject=None,
        text_message=None, html_message=None, sender_name=None,
        resend_if_not_logged_in=False):
    r = reader(csv_file, skipinitialspace=True)
    localizer = request.localizer
    for i, row in enumerate(r):
        if not len(row):
            # tolerate empty lines
            continue
        row = [x.decode('utf-8').strip() for x in row]
        if len(row) != 2:
            raise RuntimeError(localizer.translate(_(
                "The CSV file must have two columns")))
        (name, email) = row
        if not is_email(email):
            if i == 0:
                # Header
                continue
            raise RuntimeError(localizer.translate(_(
                "Not an email: <%s> at line %d")) % (email, i))
        if len(name) < 5:
            raise RuntimeError(localizer.translate(_(
                "Name too short: <%s> at line %d")) % (name, i))
        (user, created_user, created_localrole) = add_user(
            name, email, None, None, True, localrole=with_role,
            discussion=discussion_id, change_old_password=False)
        status_in_discussion = None
        if send_password_change and not (created_user or created_localrole):
            status_in_discussion = user.get_status_in_discussion(discussion_id)
        if send_password_change and (
                created_user or created_localrole or (
                    resend_if_not_logged_in and (
                        status_in_discussion is None or
                        not status_in_discussion.first_visit))):
            from assembl.views.auth.views import send_change_password_email
            from assembl.models import Discussion
            discussion = Discussion.get(discussion_id)
            send_change_password_email(
                request, user, email, subject=message_subject,
                text_body=text_message, html_body=html_message,
                discussion=discussion, sender_name=sender_name, welcome=True)
    return i
Esempio n. 4
0
def add_user(name,
             email,
             password=None,
             role=R_SYSADMIN,
             force=False,
             username=None,
             localrole=None,
             discussion=None,
             change_old_password=True,
             send_password_change=False,
             resend_if_not_logged_in=False,
             text_message=None,
             html_message=None,
             sender_name=None,
             message_subject=None,
             db=None,
             request=None,
             flush=True,
             **kwargs):
    from assembl.models import Discussion, Username
    db = db or Discussion.default_db
    # refetch within transaction
    all_roles = {r.name: r for r in db.query(Role).all()}
    user = None
    created_user = True
    if discussion and not isinstance(discussion, Discussion):
        if isinstance(discussion, (str, unicode)):
            discussion = db.query(Discussion).filter_by(
                slug=discussion).first()
            assert discussion,\
                "Discussion with slug %s does not exist" % (discussion,)
        elif isinstance(discussion, int):
            discussion = db.query(Discussion).get(discussion)
            assert discussion

    existing_email = None
    if email:
        existing_email = db.query(EmailAccount).filter(
            EmailAccount.email_ci == 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
        created_user = False
        if change_old_password:
            if password is None:
                user.password = None
            else:
                user.password_p = 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.change_class(User,
                                     None,
                                     preferred_email=email,
                                     verified=True,
                                     creation_date=datetime.utcnow(),
                                     is_machine=kwargs.get(
                                         'is_machine', False))
            if password is not None:
                user.password_p = password
        else:
            user = User(name=name,
                        preferred_email=email,
                        verified=True,
                        password=password,
                        creation_date=datetime.utcnow(),
                        is_machine=kwargs.get('is_machine', False))
            db.add(user)
        if username:
            db.add(Username(username=username, user=user))

    for account in user.accounts:
        if isinstance(account, EmailAccount) and account.email_ci == 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))

    created_localrole = False
    if localrole and discussion:
        localrole = all_roles[localrole]
        lur = None
        if old_user:
            lur = db.query(LocalUserRole).filter_by(user=user,
                                                    discussion=discussion,
                                                    role=localrole).first()
        if not lur:
            created_localrole = True
            db.add(
                LocalUserRole(user=user, role=localrole,
                              discussion=discussion))

    if flush:
        db.flush()

    status_in_discussion = None
    if resend_if_not_logged_in and discussion and not (created_user
                                                       or created_localrole):
        status_in_discussion = user.get_status_in_discussion(discussion.id)
    if send_password_change and (created_user or created_localrole or
                                 (resend_if_not_logged_in and
                                  (status_in_discussion is None
                                   or not status_in_discussion.first_visit))):
        from assembl.views.auth.views import send_change_password_email
        closer = None
        request = request or get_current_request()
        if not request:
            request, closer = _make_fake_request(discussion)

        send_change_password_email(request,
                                   user,
                                   email,
                                   subject=message_subject,
                                   text_body=text_message,
                                   html_body=html_message,
                                   discussion=discussion,
                                   sender_name=sender_name,
                                   welcome=True)
        if closer:
            closer()

    return (user, created_user, created_localrole)