Exemplo n.º 1
0
def get_participant(state,
                    restrict=True,
                    redirect_stub=True,
                    allow_member=False):
    """Given a Request, raise Response or return Participant.

    If restrict is True then we'll restrict access to owners and admins.

    """
    request = state['request']
    user = state['user']
    slug = request.line.uri.path['username']
    _ = state['_']

    if restrict and user.ANON:
        raise AuthRequired

    if slug.startswith('~'):
        thing = 'id'
        value = slug[1:]
        participant = user if user and str(user.id) == value else None
    else:
        thing = 'lower(username)'
        value = slug.lower()
        participant = user if user and user.username.lower() == value else None

    if participant is None:
        from liberapay.models.participant import Participant  # avoid circular import
        participant = Participant._from_thing(thing, value) if value else None
        if participant is None or participant.kind == 'community':
            raise Response(404)

    if request.method in ('GET', 'HEAD'):
        if slug != participant.username:
            canon = '/' + participant.username + request.line.uri[len(slug) +
                                                                  1:]
            raise Response(302, headers={'Location': canon})

    status = participant.status
    if status == 'closed':
        if user.is_admin:
            return participant
        raise Response(410)
    elif status == 'stub':
        if redirect_stub:
            to = participant.resolve_stub()
            assert to
            raise Response(302, headers={'Location': to})

    if restrict:
        if participant != user:
            if allow_member and participant.kind == 'group' and user.member_of(
                    participant):
                pass
            elif not user.is_admin:
                raise Response(
                    403, _("You are not authorized to access this page."))

    return participant
Exemplo n.º 2
0
def sign_in_with_form_data(body, state):
    p = None
    _, website = state['_'], state['website']

    if body.get('log-in.id'):
        id = body.pop('log-in.id')
        password = body.pop('log-in.password', None)
        k = 'email' if '@' in id else 'username'
        if password:
            p = Participant.authenticate(
                k, 'password',
                id, password,
            )
            if not p:
                state['log-in.error'] = _("Bad username or password.")
            if p and p.status == 'closed':
                p.update_status('active')
        elif k == 'username':
            state['log-in.error'] = _("\"{0}\" is not a valid email address.", id)
            return
        else:
            email = id
            p = Participant._from_thing('email', email)
            if p:
                p.start_session()
                qs = {'log-in.id': p.id, 'log-in.token': p.session_token}
                p.send_email(
                    'login_link',
                    email=email,
                    link=p.url('settings/', qs),
                    link_validity=SESSION_TIMEOUT,
                )
                state['log-in.email-sent-to'] = email
            else:
                state['log-in.error'] = _(
                    "We didn't find any account whose primary email address is {0}.",
                    email
                )
            p = None

    elif 'sign-in.email' in body:
        response = state['response']
        kind = body.pop('sign-in.kind')
        if kind not in ('individual', 'organization'):
            raise response.error(400, 'bad kind')
        email = body.pop('sign-in.email')
        if not email:
            raise response.error(400, 'email is required')
        with website.db.get_cursor() as c:
            p = Participant.make_active(
                kind, body.pop('sign-in.username', None),
                body.pop('sign-in.password', None), cursor=c,
            )
            p.set_email_lang(state['request'].headers.get(b'Accept-Language'), cursor=c)
            p.add_email(email, cursor=c)
        p.authenticated = True

    return p
Exemplo n.º 3
0
def get_participant(state, restrict=True, redirect_stub=True, allow_member=False):
    """Given a Request, raise Response or return Participant.

    If restrict is True then we'll restrict access to owners and admins.

    """
    request = state['request']
    user = state['user']
    slug = request.line.uri.path['username']
    _ = state['_']

    if restrict:
        if user.ANON:
            if request.method == 'GET':
                url = '/sign-in?back_to='+urlquote(request.line.uri)
                raise Response(302, headers={'Location': url})
            raise Response(403, _("You need to log in to access this page."))

    if slug.startswith('~'):
        thing = 'id'
        value = slug[1:]
        participant = user if user and str(user.id) == value else None
    else:
        thing = 'lower(username)'
        value = slug.lower()
        participant = user if user and user.username.lower() == value else None

    if participant is None:
        from liberapay.models.participant import Participant  # avoid circular import
        participant = Participant._from_thing(thing, value) if value else None
        if participant is None:
            raise Response(404)

    if request.method in ('GET', 'HEAD'):
        if slug != participant.username:
            canon = '/' + participant.username + request.line.uri[len(slug)+1:]
            raise Response(302, headers={'Location': canon})

    status = participant.status
    if status == 'closed':
        if user.is_admin:
            return participant
        raise Response(410)
    elif status == 'stub':
        if redirect_stub:
            to = participant.resolve_stub()
            assert to
            raise Response(302, headers={'Location': to})

    if restrict:
        if participant != user:
            if allow_member and participant.kind == 'group' and user.member_of(participant):
                pass
            elif not user.is_admin:
                raise Response(403, _("You are not authorized to access this page."))

    return participant
Exemplo n.º 4
0
def sign_in_with_form_data(body, state):
    p = None
    _, website = state['_'], state['website']

    if body.get('log-in.id'):
        id = body.pop('log-in.id')
        k = 'email' if '@' in id else 'username'
        p = Participant.authenticate(
            k, 'password',
            id, body.pop('log-in.password')
        )
        if not p:
            state['sign-in.error'] = _("Bad username or password.")
        if p and p.status == 'closed':
            p.update_status('active')

    elif body.get('sign-in.username'):
        if body.pop('sign-in.terms') != 'agree':
            raise Response(400, 'you have to agree to the terms')
        kind = body.pop('sign-in.kind')
        if kind not in ('individual', 'organization'):
            raise Response(400, 'bad kind')
        with website.db.get_cursor() as c:
            p = Participant.make_active(
                body.pop('sign-in.username'), kind, body.pop('sign-in.password'),
                cursor=c
            )
            p.add_email(body.pop('sign-in.email'), cursor=c)
        p.authenticated = True

    elif body.get('email-login.email'):
        email = body.pop('email-login.email')
        p = Participant._from_thing('email', email)
        if p:
            p.start_session()
            qs = {'log-in.id': p.id, 'log-in.token': p.session_token}
            p.send_email(
                'password_reset',
                email=email,
                link=p.url('settings/', qs),
                link_validity=SESSION_TIMEOUT,
            )
            state['email-login.sent-to'] = email
        else:
            state['sign-in.error'] = _(
                "We didn't find any account whose primary email address is {0}.",
                email
            )
        p = None

    return p
Exemplo n.º 5
0
def sign_in_with_form_data(body, state):
    p = None
    _, website = state['_'], state['website']

    if body.get('log-in.id'):
        id = body.pop('log-in.id')
        k = 'email' if '@' in id else 'username'
        p = Participant.authenticate(k, 'password', id,
                                     body.pop('log-in.password'))
        if not p:
            state['sign-in.error'] = _("Bad username or password.")
        if p and p.status == 'closed':
            p.update_status('active')

    elif body.get('sign-in.username'):
        if body.pop('sign-in.terms') != 'agree':
            raise Response(400, 'you have to agree to the terms')
        kind = body.pop('sign-in.kind')
        if kind not in ('individual', 'organization'):
            raise Response(400, 'bad kind')
        with website.db.get_cursor() as c:
            p = Participant.make_active(body.pop('sign-in.username'),
                                        kind,
                                        body.pop('sign-in.password'),
                                        cursor=c)
            p.add_email(body.pop('sign-in.email'), cursor=c)
        p.authenticated = True

    elif body.get('email-login.email'):
        email = body.pop('email-login.email')
        p = Participant._from_thing('email', email)
        if p:
            p.start_session()
            qs = {'log-in.id': p.id, 'log-in.token': p.session_token}
            p.send_email(
                'password_reset',
                email=email,
                link=p.url('settings/', qs),
                link_validity=SESSION_TIMEOUT,
            )
            state['email-login.sent-to'] = email
        else:
            state['sign-in.error'] = _(
                "We didn't find any account whose primary email address is {0}.",
                email)
        p = None

    return p
def sign_in_with_form_data(body, state):
    p = None
    _, website = state['_'], state['website']

    if body.get('log-in.id'):
        id = body.pop('log-in.id')
        password = body.pop('log-in.password', None)
        k = 'email' if '@' in id else 'username'
        if password:
            p = Participant.authenticate(
                k, 'password',
                id, password,
            )
            if not p:
                state['log-in.error'] = _("Bad username or password.")
        elif k == 'username':
            state['log-in.error'] = _("\"{0}\" is not a valid email address.", id)
            return
        else:
            email = id
            p = Participant._from_thing('lower(email)', email.lower())
            if p and p.kind == 'group':
                state['log-in.error'] = _(
                    "{0} is linked to a team account. It's not possible to log in as a team.",
                    email
                )
            elif p:
                if not p.get_email(email).verified:
                    website.db.hit_rate_limit('log-in.email.not-verified', TooManyLoginEmails)
                website.db.hit_rate_limit('log-in.email', p.id, TooManyLoginEmails)
                p.start_session()
                qs = {'log-in.id': p.id, 'log-in.token': p.session_token}
                p.send_email(
                    'login_link',
                    email,
                    link=p.url('settings/', qs),
                    link_validity=SESSION_TIMEOUT,
                )
                state['log-in.email-sent-to'] = email
                raise LoginRequired
            else:
                state['log-in.error'] = _(
                    "We didn't find any account whose primary email address is {0}.",
                    email
                )
            p = None

    elif 'sign-in.email' in body:
        response = state['response']
        kind = body.pop('sign-in.kind', 'individual')
        if kind not in ('individual', 'organization'):
            raise response.error(400, 'bad kind')
        email = body.pop('sign-in.email')
        if not email:
            raise response.error(400, 'email is required')
        currency = body.pop('sign-in.currency', state.get('currency'))
        if currency and currency not in CURRENCIES:
            raise response.error(400, "`currency` value '%s' is invalid of non-supported" % currency)
        src_addr = state['request'].source
        website.db.hit_rate_limit('sign-up.ip-addr', str(src_addr), TooManySignUps)
        website.db.hit_rate_limit('sign-up.ip-net', get_ip_net(src_addr), TooManySignUps)
        website.db.hit_rate_limit('sign-up.ip-version', src_addr.version, TooManySignUps)
        with website.db.get_cursor() as c:
            p = Participant.make_active(
                kind, body.pop('sign-in.username', None),
                body.pop('sign-in.password', None), currency=currency, cursor=c,
            )
            p.set_email_lang(state['request'].headers.get(b'Accept-Language'), cursor=c)
            p.add_email(email, cursor=c)
        p.authenticated = True

    return p
Exemplo n.º 7
0
def get_participant(state,
                    restrict=True,
                    redirect_stub=True,
                    allow_member=False,
                    block_suspended_user=False,
                    redirect_canon=True):
    """Given a Request, raise Response or return Participant.

    If restrict is True then we'll restrict access to owners and admins.

    """
    request = state['request']
    response = state['response']
    user = state['user']
    slug = request.line.uri.path['username']
    _ = state['_']

    if restrict and user.ANON:
        raise LoginRequired

    if slug.startswith('~'):
        thing = 'id'
        value = slug[1:]
        if not value.isdigit():
            raise response.error(404)
        participant = user if user and str(user.id) == value else None
    else:
        thing = 'lower(username)'
        value = slug.lower()
        participant = user if user and user.username.lower() == value else None

    if participant is None:
        from liberapay.models.participant import Participant  # avoid circular import
        participant = Participant._from_thing(thing, value) if value else None
        if participant is None:
            if thing == 'lower(username)':
                look_up_redirections(request, response)
            raise response.error(404)
        elif participant.kind == 'community':
            c_name = Participant.db.one(
                """
                SELECT name
                  FROM communities
                 WHERE participant = %s
            """, (participant.id, ))
            raise response.redirect('/for/%s' % c_name)

    if redirect_canon and request.method in ('GET', 'HEAD'):
        if slug != participant.username:
            canon = '/' + participant.username + request.line.uri[len(slug) +
                                                                  1:]
            raise response.redirect(canon)

    status = participant.status
    if status == 'closed':
        if user.is_admin:
            return participant
        state['closed_account'] = participant
        response.html_template = 'templates/account-closed.html'
        raise response.error(410)
    elif status == 'stub':
        if redirect_stub:
            to = participant.resolve_stub()
            if not to:
                # Account has been taken over
                raise response.error(404)
            raise response.redirect(to)

    if restrict:
        if participant != user:
            if allow_member and participant.kind == 'group' and user.member_of(
                    participant):
                pass
            elif not user.is_admin:
                raise response.error(
                    403, _("You are not authorized to access this page."))

    if block_suspended_user and participant.is_suspended and participant == user:
        raise AccountSuspended()

    return participant
Exemplo n.º 8
0
def get_participant(state, restrict=True, redirect_stub=True, allow_member=False,
                    block_suspended_user=False, redirect_canon=True):
    """Given a Request, raise Response or return Participant.

    If restrict is True then we'll restrict access to owners and admins.

    """
    request = state['request']
    response = state['response']
    user = state['user']
    slug = request.line.uri.path['username']
    _ = state['_']

    if restrict and user.ANON:
        raise LoginRequired

    if slug.startswith('~'):
        thing = 'id'
        value = slug[1:]
        if not value.isdigit():
            raise response.error(404)
        participant = user if user and str(user.id) == value else None
    else:
        thing = 'lower(username)'
        value = slug.lower()
        participant = user if user and user.username.lower() == value else None

    if participant is None:
        from liberapay.models.participant import Participant  # avoid circular import
        participant = Participant._from_thing(thing, value) if value else None
        if participant is None:
            if thing == 'lower(username)':
                look_up_redirections(request, response)
            raise response.error(404)
        elif participant.kind == 'community':
            c_name = Participant.db.one("""
                SELECT name
                  FROM communities
                 WHERE participant = %s
            """, (participant.id,))
            raise response.redirect('/for/%s' % c_name)

    if redirect_canon and request.method in ('GET', 'HEAD'):
        if slug != participant.username:
            canon = '/' + participant.username + request.line.uri[len(slug)+1:]
            raise response.redirect(canon)

    status = participant.status
    if status == 'closed':
        if user.is_admin:
            return participant
        state['closed_account'] = participant
        response.html_template = 'templates/account-closed.html'
        raise response.error(410)
    elif status == 'stub':
        if redirect_stub:
            to = participant.resolve_stub()
            if not to:
                # Account has been taken over
                raise response.error(404)
            raise response.redirect(to)

    if restrict:
        if participant != user:
            if allow_member and participant.kind == 'group' and user.member_of(participant):
                pass
            elif not user.is_admin:
                raise response.error(403, _("You are not authorized to access this page."))

    if block_suspended_user and participant.is_suspended and participant == user:
        raise AccountSuspended()

    return participant
Exemplo n.º 9
0
def sign_in_with_form_data(body, state):
    p = None
    _, website = state['_'], state['website']

    if body.get('log-in.id'):
        id = body.pop('log-in.id')
        password = body.pop('log-in.password', None)
        k = 'email' if '@' in id else 'username'
        if password:
            p = Participant.authenticate(
                k, 'password',
                id, password,
            )
            if not p:
                state['log-in.error'] = _("Bad username or password.")
        elif k == 'username':
            state['log-in.error'] = _("\"{0}\" is not a valid email address.", id)
            return
        else:
            email = id
            p = Participant._from_thing('lower(email)', email.lower())
            if p and p.kind == 'group':
                state['log-in.error'] = _(
                    "{0} is linked to a team account. It's not possible to log in as a team.",
                    email
                )
            elif p:
                if not p.get_email(email).verified:
                    website.db.hit_rate_limit('log-in.email.not-verified', TooManyLoginEmails)
                website.db.hit_rate_limit('log-in.email', p.id, TooManyLoginEmails)
                p.start_session()
                qs = {'log-in.id': p.id, 'log-in.token': p.session_token}
                p.send_email(
                    'login_link',
                    email,
                    link=p.url('settings/', qs),
                    link_validity=SESSION_TIMEOUT,
                )
                state['log-in.email-sent-to'] = email
                raise LoginRequired
            else:
                state['log-in.error'] = _(
                    "We didn't find any account whose primary email address is {0}.",
                    email
                )
            p = None

    elif 'sign-in.email' in body:
        response = state['response']
        kind = body.pop('sign-in.kind', 'individual')
        if kind not in ('individual', 'organization'):
            raise response.error(400, 'bad kind')
        email = body.pop('sign-in.email')
        if not email:
            raise response.error(400, 'email is required')
        currency = body.pop('sign-in.currency', state.get('currency'))
        if currency and currency not in CURRENCIES:
            raise response.error(400, "`currency` value '%s' is invalid of non-supported" % currency)
        src_addr = state['request'].source
        website.db.hit_rate_limit('sign-up.ip-addr', str(src_addr), TooManySignUps)
        website.db.hit_rate_limit('sign-up.ip-net', get_ip_net(src_addr), TooManySignUps)
        website.db.hit_rate_limit('sign-up.ip-version', src_addr.version, TooManySignUps)
        with website.db.get_cursor() as c:
            p = Participant.make_active(
                kind, body.pop('sign-in.username', None),
                body.pop('sign-in.password', None), currency=currency, cursor=c,
            )
            p.set_email_lang(state['request'].headers.get(b'Accept-Language'), cursor=c)
            p.add_email(email, cursor=c)
        p.authenticated = True

    return p