Beispiel #1
0
    def validate_email(email):
        if not (email and re.match(r'.*@.*\..*', email)):
            return _('Must be a valid email address')

        ol_account = OpenLibraryAccount.get(email=email)
        if ol_account:
            return _('Email already registered')
Beispiel #2
0
    def POST(self):
        f = forms.ChangeEmail()
        i = web.input()

        if not f.validates(i):
            return render["account/email"](self.get_email(), f)
        else:
            username = web.ctx.site.get_user().key.split("/")[-1]

            code = _generate_salted_hash(get_secret_key(), username + "," + i.email)
            link = (
                web.ctx.home
                + "/account/email/verify"
                + "?"
                + urllib.urlencode({"username": username, "email": i.email, "code": code})
            )

            msg = render["email/email/verify"](username=username, email=i.email, link=link)
            sendmail(i.email, msg)

            title = _("Hi %(user)s", user=username)
            message = _(
                "We've sent an email to %(email)s. You'll need to read that and click on the verification link to update your email.",
                email=i.email,
            )
            return render.message(title, message)
Beispiel #3
0
 def POST(self, key):
     edition = web.ctx.site.get(key)
     if edition is None:
         raise web.notfound()
     if edition.works:
         work = edition.works[0]
     else:
         work = None
         
     add = (edition.revision == 1 and work and work.revision == 1 and work.edition_count == 1)
         
     try:    
         helper = SaveBookHelper(work, edition)
         helper.save(web.input())
         
         if add:
             add_flash_message("info", _("Thank you very much for adding that new book!"))
         else:
             add_flash_message("info", _("Thank you very much for improving that record!"))
         
         raise web.seeother(edition.url())
     except (ClientException, ValidationException), e:
         raise
         add_flash_message('error', str(e))
         return self.GET(key)
Beispiel #4
0
 def validate_username(username):
     if not 3 <= len(username) <= 20:
         return _('Username must be between 3-20 characters')
     if not re.match('^[A-Za-z0-9-_]{3,20}$', username):
         return _('Username may only contain numbers and letters')
     ol_account = OpenLibraryAccount.get(username=username)
     if ol_account:
         return _("Username unavailable")
Beispiel #5
0
class account_login(delegate.page):
    """Account login.

    Login can fail because of the following reasons:

    * account_not_found: Error message is displayed.
    * account_bad_password: Error message is displayed with a link to reset password.
    * account_not_verified: Error page is dispalyed with button to "resend verification email".
    """
    path = "/account/login"

    def render_error(self, error_key, i):
        f = forms.Login()
        f.fill(i)
        f.note = LOGIN_ERRORS[error_key]
        return render.login(f)

    def GET(self):
        referer = web.ctx.env.get('HTTP_REFERER', '/')
        i = web.input(redirect=referer)
        f = forms.Login()
        f['redirect'].value = i.redirect
        return render.login(f)

    def POST(self):
        i = web.input(username="", connect=None, password="", remember=False,
                      redirect='/', test=False, access=None, secret=None)
        email = i.username  # XXX username is now email
        audit = audit_accounts(email, i.password, require_link=True,
                               s3_access_key=i.access,
                               s3_secret_key=i.secret, test=i.test)
        error = audit.get('error')
        if error:
            return self.render_error(error, i)

        expires = (i.remember and 3600 * 24 * 7) or ""
        web.setcookie(config.login_cookie_name, web.ctx.conn.get_auth_token(),
                      expires=expires)
        blacklist = ["/account/login", "/account/password", "/account/email",
                     "/account/create"]
        if i.redirect == "" or any([path in i.redirect for path in blacklist]):
            i.redirect = "/"
        raise web.seeother(i.redirect)

    def POST_resend_verification_email(self, i):
        try:
            ol_login = OpenLibraryAccount.authenticate(i.email, i.password)
        except ClientException, e:
            code = e.get_data().get("code")
            if code != "account_not_verified":
                return self.error("account_incorrect_password", i)

        account = OpenLibraryAccount.get(email=i.email)
        account.send_verification_email()

        title = _("Hi %(user)s", user=account.displayname)
        message = _("We've sent the verification email to %(email)s. You'll need to read that and click on the verification link to verify your email.", email=account.email)
        return render.message(title, message)
Beispiel #6
0
def get_status_for_view(status_code: int) -> str:
    """Returns localized status string that corresponds with the given status code."""
    if status_code == CommunityEditsQueue.STATUS['DECLINED']:
        return _('Declined')
    if status_code == CommunityEditsQueue.STATUS['PENDING']:
        return _('Pending')
    if status_code == CommunityEditsQueue.STATUS['MERGED']:
        return _('Merged')
    return _('Unknown')
Beispiel #7
0
 def update_email(self, username, email):
     if accounts.find(email=email):
         title = _("Email address is already used.")
         message = _("Your email address couldn't be updated. The specified email address is already used.")
     else:
         logger.info("updated email of %s to %s", username, email)
         accounts.update_account(username=username, email=email, status="active")
         title = _("Email verification successful.")
         message = _('Your email address has been successfully verified and updated in your account.')
     return render.message(title, message)
Beispiel #8
0
 def update_email(self, username, email):
     if accounts.find(email=email):
         title = _("Email address is already used.")
         message = _("Your email address couldn't be updated. The specified email address is already used.")
     else:
         logger.info("updated email of %s to %s", username, email)
         accounts.update_account(username=username, email=email, status="active")
         title = _("Email verification successful.")
         message = _('Your email address has been successfully verified and updated in your account.')
     return render.message(title, message)
Beispiel #9
0
    def POST_resend_verification_email(self, i):
        try:
            ol_login = OpenLibraryAccount.authenticate(i.email, i.password)
        except ClientException as e:
            code = e.get_data().get("code")
            if code != "account_not_verified":
                return self.error("account_incorrect_password", i)

        account = OpenLibraryAccount.get(email=i.email)
        account.send_verification_email()

        title = _("Hi, %(user)s", user=account.displayname)
        message = _("We've sent the verification email to %(email)s. You'll need to read that and click on the verification link to verify your email.", email=account.email)
        return render.message(title, message)
Beispiel #10
0
    def POST_resend_verification_email(self, i):
        try:
            ol_login = OpenLibraryAccount.authenticate(i.email, i.password)
        except ClientException as e:
            code = e.get_data().get("code")
            if code != "account_not_verified":
                return self.error("account_incorrect_password", i)

        account = OpenLibraryAccount.get(email=i.email)
        account.send_verification_email()

        title = _("Hi, %(user)s", user=account.displayname)
        message = _("We've sent the verification email to %(email)s. You'll need to read that and click on the verification link to verify your email.", email=account.email)
        return render.message(title, message)
Beispiel #11
0
 def POST(self, code=None):
     """Called to regenerate account verification code.
     """
     i = web.input(email=None)
     account = accounts.find(email=i.email)
     if not account:
         return render_template("account/verify/failed", email=i.email)
     elif account['status'] != "pending":
         return render['account/verify/activated'](account)
     else:
         account.send_verification_email()
         title = _("Hi %(user)s", user=account.displayname)
         message = _("We've sent the verification email to %(email)s. You'll need to read that and click on the verification link to verify your email.", email=account.email)
         return render.message(title, message)
Beispiel #12
0
 def POST(self, code=None):
     """Called to regenerate account verification code.
     """
     i = web.input(email=None)
     account = accounts.find(email=i.email)
     if not account:
         return render_template("account/verify/failed", email=i.email)
     elif account['status'] != "pending":
         return render['account/verify/activated'](account)
     else:
         account.send_verification_email()
         title = _("Hi, %(user)s", user=account.displayname)
         message = _("We've sent the verification email to %(email)s. You'll need to read that and click on the verification link to verify your email.", email=account.email)
         return render.message(title, message)
Beispiel #13
0
 def POST(self):
     user = accounts.get_current_user()
     user.save_preferences(web.input())
     add_flash_message(
         'note',
         _("Notification preferences have been updated successfully."))
     web.seeother("/account")
Beispiel #14
0
    def POST(self):
        f = forms.ChangeEmail()
        i = web.input()

        if not f.validates(i):
            return render['account/email'](self.get_email(), f)
        else:
            user = accounts.get_current_user()
            username = user.key.split('/')[-1]

            displayname = user.displayname or username

            send_email_change_email(username, i.email)

            title = _("Hi %(user)s", user=user.displayname or username)
            message = _("We've sent an email to %(email)s. You'll need to read that and click on the verification link to update your email.", email=i.email)
            return render.message(title, message)
Beispiel #15
0
    def POST(self):
        f = forms.ChangeEmail()
        i = web.input()

        if not f.validates(i):
            return render['account/email'](self.get_email(), f)
        else:
            user = accounts.get_current_user()
            username = user.key.split('/')[-1]

            displayname = user.displayname or username

            send_email_change_email(username, i.email)

            title = _("Hi %(user)s", user=user.displayname or username)
            message = _("We've sent an email to %(email)s. You'll need to read that and click on the verification link to update your email.", email=i.email)
            return render.message(title, message)
Beispiel #16
0
def datestr(then, now=None, lang=None):
    """Internationalized version of web.datestr."""
    result = web.datestr(then, now)
    if result[0] in string.digits: # eg: 2 milliseconds ago
        t, message = result.split(' ', 1)
        return _("%d " + message) % int(t)
    else:
        return format_date(then, lang=lang)
Beispiel #17
0
def datestr(then, now=None):
    """Internationalized version of web.datestr."""
    result = web.datestr(then, now)
    if result[0] in string.digits: # eg: 2 milliseconds ago
        t, message = result.split(' ', 1)
        return _("%d " + message) % int(t)
    else:
        return babel.dates.format_date(then, format="long", locale=get_locale())
Beispiel #18
0
class RegisterForm(Form):
    INPUTS = [
        Textbox('email', description=_('Your email address'),
            klass='required',
            id='emailAddr',
            validators=[vemail, email_not_already_used, email_not_disposable, email_domain_not_blocked]),
        Textbox('username', description=_('Choose a screen name'),
            klass='required',
            help=_("Letters and numbers only please, and at least 3 characters."),
            autocapitalize="off",
            validators=[vlogin, username_validator]),
        Password('password', description=_('Choose a password'),
            klass='required',
            validators=[vpass]),
        Password('password2', description=_('Confirm password'),
            klass='required',
            validators=[vpass, EqualToValidator('password', _("Passwords didn't match."))]),
        Checkbox('ia_newsletter', description=_("""Send me a monthly newsletter from the <a href="https://archive.org/">Internet Archive</a>, the non-profit that runs Open Library""")),
    ]
    def __init__(self):
        Form.__init__(self, *self.INPUTS)

    def validates(self, source):
        # Set form in each validator so that validators
        # like EqualToValidator can work
        for input in self.inputs:
            for validator in input.validators:
                validator.form = self
        return Form.validates(self, source)
Beispiel #19
0
    def POST(self):
        i = web.input(username='', code='')

        try:
            web.ctx.site.check_reset_code(i.username, i.code)
        except ClientException, e:
            title = _("Password reset failed.")
            message = web.safestr(e)
            return render.message(title, message)
Beispiel #20
0
    def POST(self):
        i = web.input(username='', code='')

        try:
            web.ctx.site.check_reset_code(i.username, i.code)
        except ClientException, e:
            title = _("Password reset failed.")
            message = web.safestr(e)
            return render.message(title, message)
Beispiel #21
0
    def GET(self, code):
        docs = web.ctx.site.store.values(type="account-link", name="code", value=code)
        if not docs:
            title = _("Password reset failed.")
            message = "Your password reset link seems invalid or expired."
            return render.message(title, message)

        f = forms.ResetPassword()
        return render['account/password/reset'](f)
Beispiel #22
0
    def GET(self, code):
        docs = web.ctx.site.store.values(type="account-link", name="code", value=code)
        if not docs:
            title = _("Password reset failed.")
            message = "Your password reset link seems invalid or expired."
            return render.message(title, message)

        f = forms.ResetPassword()
        return render['account/password/reset'](f)
Beispiel #23
0
    def POST(self):
        f = forms.ChangeEmail()
        i = web.input()
        
        if not f.validates(i):
            return render['account/email'](self.get_email(), f)
        else:
            user = web.ctx.site.get_user()
            username = user.key.split('/')[-1]
            
            code = _generate_salted_hash(get_secret_key(), username + ',' + i.email)
            link = web.ctx.home + '/account/email/verify' + '?' + urllib.urlencode({"username": username, 'email': i.email, 'code': code})

            msg = render['email/email/verify'](username=username, email=i.email, link=link)
            sendmail(i.email, msg)
            
            title = _("Hi %(user)s", user=user.displayname or username)
            message = _("We've sent an email to %(email)s. You'll need to read that and click on the verification link to update your email.", email=i.email)
            return render.message(title, message)
Beispiel #24
0
def datestr(then, now=None, lang=None):
    """Internationalized version of web.datestr."""
    result = web.datestr(then, now)
    if not result:
        return result
    elif result[0] in string.digits:  # eg: 2 milliseconds ago
        t, message = result.split(' ', 1)
        return _("%d " + message) % int(t)
    else:
        return format_date(then, lang=lang)
Beispiel #25
0
    def POST(self):
        key = context.user.key + '/preferences'
        prefs = web.ctx.site.get(key)

        d = (prefs and prefs.dict()) or {'key': key, 'type': {'key': '/type/object'}}

        d['notifications'] = web.input()

        web.ctx.site.save(d, 'save notifications')

        add_flash_message('note', _("Notification preferences have been updated successfully."))
        web.seeother("/account")
Beispiel #26
0
    def POST(self):
        key = context.user.key + "/preferences"
        prefs = web.ctx.site.get(key)

        d = (prefs and prefs.dict()) or {"key": key, "type": {"key": "/type/object"}}

        d["notifications"] = web.input()

        web.ctx.site.save(d, "save notifications")

        add_flash_message("note", _("Notification preferences have been updated successfully."))
        web.seeother("/account")
Beispiel #27
0
class RegisterForm(Form):
    INPUTS = [
        Textbox('email', description=_('Your email address'),
            klass='required',
            validators=[vemail, email_not_already_used, email_not_disposable, email_domain_not_blocked]),
        Textbox('username', description=_('Choose a screen name'),
            klass='required',
            help=_("Only letters and numbers, please, and at least 3 characters."),
            validators=[vlogin, username_validator]),
        Password('password', description=_('Choose a password'),
            klass='required',
            validators=[vpass]),
        Textbox('password2', description=_('Confirm password'),
            klass='required',
            validators=[vpass, EqualToValidator('password', _("Passwords didn't match."))]),
    ]
    def __init__(self):
        Form.__init__(self, *self.INPUTS)

    def validates(self, source):
        # Set form in each validator so that validators
        # like EqualToValidator can work
        for input in self.inputs:
            for validator in input.validators:
                validator.form = self
        return Form.validates(self, source)
Beispiel #28
0
    def POST(self):
        user = accounts.get_current_user()
        key = user.key + '/preferences'
        prefs = web.ctx.site.get(key)

        d = (prefs and prefs.dict()) or {'key': key, 'type': {'key': '/type/object'}}

        d['notifications'] = web.input()

        web.ctx.site.save(d, 'save notifications')

        add_flash_message('note', _("Notification preferences have been updated successfully."))
        web.seeother("/account")
Beispiel #29
0
def datestr(then, now=None, lang=None, relative = True):
    """Internationalized version of web.datestr."""
    if not relative:
        result = then.strftime("%b %d %Y")
    else:
        result = web.datestr(then, now)
    if not result:
        return result
    elif result[0] in string.digits: # eg: 2 milliseconds ago
        t, message = result.split(' ', 1)
        return _("%d " + message) % int(t)
    else:
        return format_date(then, lang=lang)
Beispiel #30
0
    def POST(self, key):
        work = web.ctx.site.get(key)
        if work is None:
            raise web.notfound()

        try:
            helper = SaveBookHelper(work, None)
            helper.save(web.input())
            add_flash_message("info", _("Thank you very much for improving that record!"))            
            raise web.seeother(work.url())
        except (ClientException, ValidationException), e:
            add_flash_message('error', str(e))
            return self.GET(key)
Beispiel #31
0
    def POST(self, code):
        link = accounts.get_link(code)
        if not link:
            title = _("Password reset failed.")
            message = "The password reset link seems invalid or expired."
            return render.message(title, message)

        username = link['username']
        i = web.input()

        accounts.update_account(username, password=i.password)
        link.delete()
        return render_template("account/password/reset_success", username=username)
Beispiel #32
0
    def POST(self, code):
        link = accounts.get_link(code)
        if not link:
            title = _("Password reset failed.")
            message = "The password reset link seems invalid or expired."
            return render.message(title, message)

        username = link['username']
        i = web.input()

        accounts.update_account(username, password=i.password)
        link.delete()
        return render_template("account/password/reset_success", username=username)
Beispiel #33
0
    def POST(self, code):
        docs = web.ctx.site.store.values(type="account-link", name="code", value=code)
        if not docs:
            title = _("Password reset failed.")
            message = "The password reset link seems invalid or expired."
            return render.message(title, message)

        doc = docs[0]
        username = doc['username']
        i = web.input()
        
        web.ctx.site.update_account(username, password=i.password)
        del web.ctx.site.store[doc['_key']]
        return render_template("account/password/reset_success", username=username)
Beispiel #34
0
    def POST(self):
        f = forms.ChangePassword()
        i = web.input()

        if not f.validates(i):
            return render['account/password'](f)

        user = accounts.get_current_user()
        username = user.key.split("/")[-1]

        if self.try_login(username, i.password):
            accounts.update_account(username, password=i.new_password)
            add_flash_message('note', _('Your password has been updated successfully.'))
            raise web.seeother('/account')
        else:
            f.note = "Invalid password"
            return render['account/password'](f)
Beispiel #35
0
    def POST(self, code):
        docs = web.ctx.site.store.values(type="account-link",
                                         name="code",
                                         value=code)
        if not docs:
            title = _("Password reset failed.")
            message = "The password reset link seems invalid or expired."
            return render.message(title, message)

        doc = docs[0]
        username = doc['username']
        i = web.input()

        web.ctx.site.update_account(username, password=i.password)
        del web.ctx.site.store[doc['_key']]
        return render_template("account/password/reset_success",
                               username=username)
Beispiel #36
0
    def POST(self):
        f = forms.ChangePassword()
        i = web.input()

        if not f.validates(i):
            return render['account/password'](f)

        user = accounts.get_current_user()
        username = user.key.split("/")[-1]

        if self.try_login(username, i.password):
            accounts.update_account(username, password=i.new_password)
            add_flash_message('note', _('Your password has been updated successfully.'))
            raise web.seeother('/account')
        else:
            f.note = "Invalid password"
            return render['account/password'](f)
Beispiel #37
0
 def GET(self):
     i = web.input(username='', email='', code='')
     
     verified = _verify_salted_hash(get_secret_key(), i.username + ',' + i.email, i.code)
     if verified:
         if web.ctx.site.find_user_by_email(i.email) is not None:
             title = _("Email address is already used.")
             message = _("Your email address couldn't be updated. The specified email address is already used.")
         else:
             web.ctx.site.update_user_details(i.username, email=i.email)
             title = _("Email verification successful.")
             message = _('Your email address has been successfully verified and updated in your account.')
     else:
         title = _("Email address couldn't be verified.")
         message = _("Your email address couldn't be verified. The verification link seems invalid.")
         
     return render.message(title, message)
Beispiel #38
0
class RegisterForm(Form):
    INPUTS = [
        Textbox("displayname", description=_("Your Full Name")),
        Textbox(
            'email',
            description=_('Your Email Address'),
            klass='required',
            validators=[vemail, email_not_already_used, email_not_disposable]),
        Textbox('email2',
                description=_('Confirm Your Email Address'),
                klass='required',
                validators=[
                    EqualToValidator(
                        'email',
                        _('Your emails do not match. Please try again.'))
                ]),
        Textbox(
            'username',
            description=_('Choose a Username'),
            klass='required',
            help=_(
                "Only letters and numbers, please, and at least 3 characters."
            ),
            validators=[vlogin, username_validator]),
        Password('password',
                 description=_('Choose a Password'),
                 klass='required',
                 validators=[vpass])
    ]

    def __init__(self):
        Form.__init__(self, *self.INPUTS)

    def validates(self, source):
        # Set form in each validator so that validators
        # like EqualToValidator can work
        for input in self.inputs:
            for validator in input.validators:
                validator.form = self
        return Form.validates(self, source)
Beispiel #39
0
def get_monthly_reads(month):
    """Generates i18n'd monthly carousel for templated/home/index.html

    To be replaced with QueryCarousel macro for cached Lists
    """
    return {
        2: {
            "title": _("Books for February"),
            "url": "/collections/february",
            "query": "key:(%s)"
            % (
                " OR ".join(
                    (
                        "/works/OL18181363W",
                        "/works/OL3481095W",
                        "/works/OL4360244W",
                        "/works/OL20017931W",
                        "/works/OL20615204W",
                        "/works/OL2363176W",
                        "/works/OL17869588W",
                        "/works/OL17784026W",
                        "/works/OL21179764W",
                        "/works/OL8870595W",
                        "/works/OL21054973W",
                        "/works/OL21673730W",
                        "/works/OL20548582W",
                        "/works/OL15279153W",
                        "/works/OL19992836W",
                        "/works/OL15691480W",
                        "/works/OL16305795W",
                        "/works/OL19923407W",
                        "/works/OL16529029W",
                        "/works/OL9242636W",
                        "/works/OL17529769W",
                        "/works/OL3345332W",
                        "/works/OL20013209W",
                        "/works/OL20015483W",
                        "/works/OL19987474W",
                        "/works/OL19992114W",
                        "/works/OL17893900W",
                        "/works/OL18435803W",
                        "/works/OL17314666W",
                        "/works/OL17358927W",
                        "/works/OL15933199W",
                        "/works/OL17858931W",
                        "/works/OL18187603W",
                        "/works/OL16853133W",
                        "/works/OL16894393W",
                        "/works/OL19976062W",
                        "/works/OL20037832W",
                        "/works/OL16885033W",
                        "/works/OL19708155W",
                        "/works/OL17921756W",
                        "/works/OL21037237W",
                        "/works/OL17786027W",
                        "/works/OL17345141W",
                        "/works/OL21294275W",
                        "/works/OL9582417W",
                        "/works/OL9357555W",
                        "/works/OL20907853W",
                        "/works/OL20005568W",
                        "/works/OL3296483W",
                        "/works/OL11983310W",
                        "/works/OL7159886W",
                        "/works/OL1662667W",
                        "/works/OL19990553W",
                        "/works/OL15285884W",
                        "/works/OL6888879W",
                        "/works/OL17900435W",
                        "/works/OL5706069W",
                        "/works/OL2977589W",
                        "/works/OL1593701W",
                        "/works/OL16451688W",
                        "/works/OL16910779W",
                        "/works/OL18215336W",
                        "/works/OL17371695W",
                        "/works/OL3521634W",
                        "/works/OL17355199W",
                        "/works/OL5739152W",
                        "/works/OL20016962W",
                        "/works/OL3191599W",
                        "/works/OL20896695W",
                        "/works/OL19752490W",
                        "/works/OL18335154W",
                        "/works/OL4582875W",
                        "/works/OL16515210W",
                        "/works/OL16868407W",
                        "/works/OL3459949W",
                        "/works/OL16025481W",
                        "/works/OL1928280W",
                        "/works/OL6208302W",
                        "/works/OL17566265W",
                        "/works/OL20652811W",
                        "/works/OL22059158W",
                        "/works/OL4370955W",
                        "/works/OL19998526W",
                        "/works/OL6218060W",
                        "/works/OL16813953W",
                        "/works/OL21179974W",
                        "/works/OL7213898W",
                        "/works/OL17872185W",
                        "/works/OL17340085W",
                        "/works/OL21584979W",
                        "/works/OL21078916W",
                        "/works/OL158519W",
                        "/works/OL4114499W",
                        "/works/OL19638041W",
                        "/works/OL16844793W",
                        "/works/OL20940485W",
                        "/works/OL17392121W",
                        "/works/OL20030448W",
                        "/works/OL15920474W",
                        "/works/OL20544657W",
                    )
                )
            ),
        },
        3: {
            "title": _("Books for March"),
            "url": "/collections/march",
            "query": "key:(%s)"
            % (
                " OR ".join(
                    (
                        "/works/OL5184754W",
                        "/works/OL133486W",
                        "/works/OL1112900W",
                        "/works/OL15302479W",
                        "/works/OL5353481W",
                        "/works/OL1684657W",
                        "/works/OL16612125W",
                        "/works/OL2987652W",
                        "/works/OL15243975W",
                        "/works/OL5827897W",
                        "/works/OL237034W",
                        "/works/OL20916117W",
                        "/works/OL1881592W",
                        "/works/OL16561534W",
                        "/works/OL17893247W",
                        "/works/OL7000994W",
                        "/works/OL16247899W",
                        "/works/OL19163127W",
                        "/works/OL1146619W",
                        "/works/OL2231866W",
                        "/works/OL1853601W",
                        "/works/OL1794792W",
                        "/works/OL2750502W",
                        "/works/OL1825970W",
                        "/works/OL17991110W",
                        "/works/OL34442W",
                        "/works/OL20886755W",
                        "/works/OL1880057W",
                        "/works/OL9221039W",
                        "/works/OL4782577W",
                        "/works/OL15230140W",
                        "/works/OL7899614W",
                        "/works/OL508764W",
                        "/works/OL18165887W",
                        "/works/OL17538396W",
                        "/works/OL53994W",
                        "/works/OL11817902W",
                        "/works/OL5118902W",
                        "/works/OL68789W",
                        "/works/OL8874375W",
                        "/works/OL158240W",
                        "/works/OL3474021W",
                        "/works/OL3352379W",
                        "/works/OL1826369W",
                        "/works/OL106972W",
                        "/works/OL20623337W",
                        "/works/OL2624393W",
                        "/works/OL47755W",
                        "/works/OL514392W",
                        "/works/OL18820761W",
                        "/works/OL85496W",
                        "/works/OL21625058W",
                        "/works/OL1833297W",
                        "/works/OL15162472W",
                        "/works/OL16289374W",
                        "/works/OL15100036W",
                        "/works/OL17311133W",
                        "/works/OL1826373W",
                        "/works/OL3255337W",
                        "/works/OL7113090W",
                        "/works/OL5408044W",
                        "/works/OL4702292W",
                        "/works/OL8269570W",
                        "/works/OL2626142W",
                        "/works/OL9399062W",
                        "/works/OL6670269W",
                        "/works/OL890505W",
                        "/works/OL523724W",
                        "/works/OL6218068W",
                        "/works/OL1469543W",
                        "/works/OL1001250W",
                        "/works/OL20004703W",
                        "/works/OL679942W",
                        "/works/OL2044569W",
                        "/works/OL15980420W",
                        "/works/OL20016033W",
                        "/works/OL565273W",
                        "/works/OL20019003W",
                        "/works/OL18820945W",
                        "/works/OL3945614W",
                        "/works/OL64468W",
                        "/works/OL5754207W",
                        "/works/OL6218046W",
                        "/works/OL18183638W",
                        "/works/OL21182317W",
                        "/works/OL169921W",
                        "/works/OL6384123W",
                        "/works/OL1870681W",
                        "/works/OL16245602W",
                        "/works/OL17676089W",
                        "/works/OL20848500W",
                        "/works/OL4304829W",
                        "/works/OL17873811W",
                        "/works/OL4968024W",
                        "/works/OL20001088W",
                        "/works/OL3142310W",
                        "/works/OL142101W",
                        "/works/OL19396225W",
                        "/works/OL1230977W",
                        "/works/OL17332299W",
                    )
                )
            ),
        },
        4: {
            "title": _("Books for April"),
            "url": "/collections/april",
            "query": "key:(%s)"
            % (
                " OR ".join(
                    (
                        "/works/OL6934547W",
                        "/works/OL2000340W",
                        "/works/OL2746188W",
                        "/works/OL2921990W",
                        "/works/OL11476041W",
                        "/works/OL8676892W",
                        "/works/OL1895089W",
                        "/works/OL8463108W",
                        "/works/OL1916767W",
                        "/works/OL17328163W",
                        "/works/OL34364W",
                        "/works/OL2384851W",
                        "/works/OL79422W",
                        "/works/OL142101W",
                        "/works/OL5719058W",
                        "/works/OL548264W",
                        "/works/OL15120217W",
                        "/works/OL14952471W",
                        "/works/OL15188310W",
                        "/works/OL1855830W",
                        "/works/OL3147556W",
                        "/works/OL5843701W",
                        "/works/OL20479918W",
                        "/works/OL17864309W",
                        "/works/OL5857644W",
                        "/works/OL18174472W",
                        "/works/OL13750798W",
                        "/works/OL14869488W",
                        "/works/OL15844569W",
                        "/works/OL510286W",
                        "/works/OL2650512W",
                        "/works/OL83989W",
                        "/works/OL1914072W",
                        "/works/OL5097914W",
                        "/works/OL1927820W",
                        "/works/OL112630W",
                        "/works/OL6218052W",
                        "/works/OL12992964W",
                        "/works/OL8460319W",
                        "/works/OL308951W",
                        "/works/OL14909580W",
                        "/works/OL17077479W",
                        "/works/OL4445284W",
                        "/works/OL17437756W",
                        "/works/OL8193508W",
                        "/works/OL5590179W",
                        "/works/OL166683W",
                        "/works/OL83989W",
                        "/works/OL45869W",
                        "/works/OL3840897W",
                        "/works/OL15289753W",
                        "/works/OL22056274W",
                        "/works/OL2279297W",
                        "/works/OL71856W",
                        "/works/OL45790W",
                        "/works/OL6704886W",
                        "/works/OL9770557W",
                        "/works/OL524611W",
                        "/works/OL45709W",
                        "/works/OL66562W",
                        "/works/OL8455191W",
                        "/works/OL15065463W",
                        "/works/OL1173603W",
                        "/works/OL15692492W",
                        "/works/OL25860W",
                        "/works/OL53908W",
                        "/works/OL2342157W",
                        "/works/OL17324165W",
                        "/works/OL261405W",
                        "/works/OL17324092W",
                        "/works/OL263663W",
                        "/works/OL2695471W",
                        "/works/OL587092W",
                        "/works/OL2695710W",
                        "/works/OL20892865W",
                        "/works/OL15392519W",
                        "/works/OL138536W",
                        "/works/OL88641W",
                        "/works/OL151924W",
                        "/works/OL15021422W",
                        "/works/OL9355810W",
                        "/works/OL5097109W",
                        "/works/OL3368666W",
                        "/works/OL50625W",
                        "/works/OL8076534W",
                        "/works/OL17059208W",
                        "/works/OL3974810W",
                        "/works/OL1910135W",
                        "/works/OL201059W",
                        "/works/OL100672W",
                        "/works/OL17900251W",
                        "/works/OL54031W",
                        "/works/OL76590W",
                        "/works/OL17063120W",
                        "/works/OL3288436W",
                        "/works/OL997592W",
                        "/works/OL19360441W",
                        "/works/OL17857052W",
                        "/works/OL1993508W",
                        "/works/OL17872769W",
                    )
                )
            ),
        },
        5: {
            "title": _("Books for May"),
            "url": "/collections/may",
            "query": "key:(%s)"
            % (
                " OR ".join(
                    (
                        "/works/OL450777W",
                        "/works/OL362289W",
                        "/works/OL4077051W",
                        "/works/OL2715009W",
                        "/works/OL2205289W",
                        "/works/OL158953W",
                        "/works/OL4662884W",
                        "/works/OL222799W",
                        "/works/OL5859708W",
                        "/works/OL19659784W",
                        "/works/OL2765935W",
                        "/works/OL15834136W",
                        "/works/OL513969W",
                        "/works/OL98501W",
                        "/works/OL464991W",
                        "/works/OL8193418W",
                        "/works/OL61324W",
                        "/works/OL1870400W",
                        "/works/OL50829W",
                        "/works/OL66531W",
                        "/works/OL5717098W",
                        "/works/OL61921W",
                        "/works/OL5475081W",
                        "/works/OL875437W",
                        "/works/OL6034514W",
                        "/works/OL523452W",
                        "/works/OL7711724W",
                        "/works/OL1854080W",
                        "/works/OL9347808W",
                        "/works/OL2676023W",
                        "/works/OL6218070W",
                        "/works/OL10432709W",
                        "/works/OL804244W",
                        "/works/OL12497W",
                        "/works/OL77792W",
                        "/works/OL2721005W",
                        "/works/OL4661335W",
                        "/works/OL831059W",
                        "/works/OL2731827W",
                        "/works/OL21522W",
                        "/works/OL482313W",
                        "/works/OL97440W",
                        "/works/OL3943151W",
                        "/works/OL3521874W",
                        "/works/OL2715015W",
                        "/works/OL66544W",
                        "/works/OL433123W",
                        "/works/OL2068683W",
                        "/works/OL6322288W",
                        "/works/OL1971683W",
                        "/works/OL1069667W",
                        "/works/OL2438133W",
                        "/works/OL17272376W",
                        "/works/OL16482241W",
                        "/works/OL15860364W",
                        "/works/OL151996W",
                        "/works/OL6740249W",
                        "/works/OL15040422W",
                        "/works/OL16069155W",
                        "/works/OL508163W",
                        "/works/OL3291229W",
                        "/works/OL61003W",
                        "/works/OL98491W",
                        "/works/OL5888555W",
                        "/works/OL5827913W",
                        "/works/OL17933404W",
                        "/works/OL1095427W",
                        "/works/OL54915W",
                        "/works/OL13114894W",
                        "/works/OL24338132W",
                        "/works/OL1872916W",
                        "/works/OL15840480W",
                        "/works/OL184431W",
                        "/works/OL2940316W",
                        "/works/OL2647505W",
                        "/works/OL259028W",
                        "/works/OL14915863W",
                        "/works/OL29462W",
                        "/works/OL1734184W",
                        "/works/OL675449W",
                        "/works/OL18591W",
                        "/works/OL221675W",
                        "/works/OL5704260W",
                        "/works/OL15717066W",
                        "/works/OL3863998W",
                        "/works/OL2619717W",
                        "/works/OL64151W",
                        "/works/OL12826W",
                        "/works/OL547889W",
                        "/works/OL66534W",
                        "/works/OL15952404W",
                        "/works/OL2155632W",
                        "/works/OL69503W",
                        "/works/OL61215W",
                        "/works/OL112890W",
                        "/works/OL66562W",
                        "/works/OL15837476W",
                        "/works/OL15178362W",
                        "/works/OL2046569W",
                        "/works/OL2031517W",
                    )
                )
            ),
        },
        6: {
            "title": _("Books for June"),
            "url": "/collections/june",
            "query": "key:(%s)"
            % (
                " OR ".join(
                    (
                        "/works/OL4452160W",
                        "/works/OL5804905W",
                        "/works/OL7597278W",
                        "/works/OL706761W",
                        "/works/OL1115461W",
                        "/works/OL3350425W",
                        "/works/OL7717951W",
                        "/works/OL77792W",
                        "/works/OL3374551W",
                        "/works/OL15118371W",
                        "/works/OL13845723W",
                        "/works/OL1474735W",
                        "/works/OL249219W",
                        "/works/OL202359W",
                        "/works/OL61981W",
                        "/works/OL1176834W",
                        "/works/OL2295019W",
                        "/works/OL13727180W",
                        "/works/OL5684730W",
                        "/works/OL195165W",
                        "/works/OL503666W",
                        "/works/OL224894W",
                        "/works/OL16248853W",
                        "/works/OL4056537W",
                        "/works/OL8138326W",
                        "/works/OL8268194W",
                        "/works/OL362706W",
                        "/works/OL3753201W",
                        "/works/OL6560544W",
                        "/works/OL4971793W",
                        "/works/OL10432709W",
                        "/works/OL7729178W",
                        "/works/OL263458W",
                        "/works/OL151997W",
                        "/works/OL2790101W",
                        "/works/OL17094386W",
                        "/works/OL88713W",
                        "/works/OL189097W",
                        "/works/OL1858279W",
                        "/works/OL3399858W",
                        "/works/OL2569571W",
                        "/works/OL8713270W",
                        "/works/OL1430148W",
                        "/works/OL2854958W",
                        "/works/OL1794792W",
                        "/works/OL66562W",
                        "/works/OL8542762W",
                        "/works/OL67326W",
                        "/works/OL2005700W",
                        "/works/OL10395689W",
                        "/works/OL24161W",
                        "/works/OL1793589W",
                        "/works/OL4062432W",
                        "/works/OL8193418W",
                        "/works/OL98501W",
                        "/works/OL258850W",
                        "/works/OL4276206W",
                        "/works/OL362427W",
                        "/works/OL16899384W",
                        "/works/OL81588W",
                        "/works/OL7917989W",
                        "/works/OL3871015W",
                        "/works/OL16134139W",
                        "/works/OL5109271W",
                        "/works/OL258134W",
                        "/works/OL17603105W",
                        "/works/OL20604741W",
                        "/works/OL140125W",
                        "/works/OL20386119W",
                        "/works/OL1337528W",
                        "/works/OL5743157W",
                        "/works/OL1132128W",
                        "/works/OL5704208W",
                        "/works/OL15847281W",
                        "/works/OL1197859W",
                        "/works/OL3168678W",
                        "/works/OL1962457W",
                        "/works/OL1973472W",
                        "/works/OL15717002W",
                        "/works/OL6044682W",
                        "/works/OL167183W",
                        "/works/OL53908W",
                        "/works/OL1119456W",
                        "/works/OL98501W",
                        "/works/OL17602317W",
                        "/works/OL19926001W",
                        "/works/OL8961373W",
                        "/works/OL16151517W",
                        "/works/OL8599103W",
                        "/works/OL4623379W",
                        "/works/OL45793W",
                        "/works/OL245200W",
                        "/works/OL17044272W",
                        "/works/OL1854695W",
                        "/works/OL2196066W",
                        "/works/OL57025W",
                        "/works/OL6815134W",
                        "/works/OL488453W",
                        "/works/OL5850538W",
                    )
                )
            ),
        },
    }.get(month)
Beispiel #40
0
import web
from infogami.infobase.client import ClientException
from infogami.core import forms

from openlibrary.i18n import lgettext as _
from openlibrary.utils.form import Form, Textbox, Password, Hidden, Validator, RegexpValidator
from openlibrary import accounts


def find_account(username=None, lusername=None, email=None):
    return accounts.find(username=username, lusername=lusername, email=email)


Login = Form(
    Textbox("username", description=_("Username"), klass="required"),
    Password("password", description=_("Password"), klass="required"),
    Hidden("redirect"),
)
forms.login = Login

email_already_used = Validator(
    _("No user registered with this email address"), lambda email: find_account(email=email) is not None
)
email_not_already_used = Validator(_("Email already used"), lambda email: find_account(email=email) is None)
email_not_disposable = Validator(
    _("Disposable email not permitted"), lambda email: not email.lower().endswith("dispostable.com")
)
username_validator = Validator(
    _("Username already used"), lambda username: not find_account(lusername=username.lower())
)
Beispiel #41
0
        web.setcookie(config.login_cookie_name, web.ctx.conn.get_auth_token(), expires=expires)
        raise web.seeother(i.redirect)

    def POST_resend_verification_email(self, i):
        try:
            web.ctx.site.login(i.username, i.password)
        except ClientException, e:
            code = e.get_data().get("code")
            if code != "account_not_verified":
                return self.error("account_incorrect_password", i)

        account = web.ctx.site.find_account(username=i.username)
        send_verification_email(i.username, account.email)

        user = web.ctx.site.get('/people/' + i.username)
        title = _("Hi %(user)s", user=user.displayname or i.username)
        message = _("We've sent the verification email to %(email)s. You'll need to read that and click on the verification link to verify your email.", email=account.email)
        return render.message(title, message)

class account_verify(delegate.page):
    """Verify user account.
    """
    path = "/account/verify/([0-9a-f]*)"

    def GET(self, code):
        docs = web.ctx.site.store.values(type="account-link", name="code", value=code)
        if docs:
            doc = docs[0]

            web.ctx.site.activate_account(username=doc['username'])
            del web.ctx.site.store[doc['_key']]
Beispiel #42
0
def get_featured_subjects():
    # web.ctx must be initialized as it won't be available to the background thread.
    if 'env' not in web.ctx:
        delegate.fakeload()

    FEATURED_SUBJECTS = [
        {'key': '/subjects/art', 'presentable_name': _('Art')},
        {'key': '/subjects/science_fiction', 'presentable_name': _('Science Fiction')},
        {'key': '/subjects/fantasy', 'presentable_name': _('Fantasy')},
        {'key': '/subjects/biographies', 'presentable_name': _('Biographies')},
        {'key': '/subjects/recipes', 'presentable_name': _('Recipes')},
        {'key': '/subjects/romance', 'presentable_name': _('Romance')},
        {'key': '/subjects/textbooks', 'presentable_name': _('Textbooks')},
        {'key': '/subjects/children', 'presentable_name': _('Children')},
        {'key': '/subjects/history', 'presentable_name': _('History')},
        {'key': '/subjects/medicine', 'presentable_name': _('Medicine')},
        {'key': '/subjects/religion', 'presentable_name': _('Religion')},
        {
            'key': '/subjects/mystery_and_detective_stories',
            'presentable_name': _('Mystery and Detective Stories'),
        },
        {'key': '/subjects/plays', 'presentable_name': _('Plays')},
        {'key': '/subjects/music', 'presentable_name': _('Music')},
        {'key': '/subjects/science', 'presentable_name': _('Science')},
    ]
    return [
        {**subject, **(subjects.get_subject(subject['key'], limit=0) or {})}
        for subject in FEATURED_SUBJECTS
    ]
Beispiel #43
0
 def POST(self):
     user = accounts.get_current_user()
     user.save_preferences(web.input())
     add_flash_message('note', _("Notification preferences have been updated successfully."))
     web.seeother("/account")
Beispiel #44
0
from openlibrary.i18n import lgettext as _
from openlibrary.utils.form import Form, Textbox, Password, Hidden, Validator, RegexpValidator
from openlibrary import accounts
from openlibrary.accounts import InternetArchiveAccount
from . import spamcheck

def find_account(username=None, lusername=None, email=None):
    return accounts.find(username=username, lusername=lusername, email=email)

def find_ia_account(email=None):
    ia_account = InternetArchiveAccount.get(email=email)
    return ia_account

Login = Form(
    Textbox('username', description=_('Username'), klass='required'),
    Password('password', description=_('Password'), klass='required'),
    Hidden('redirect')
)
forms.login = Login

email_already_used = Validator(_("No user registered with this email address"), lambda email: find_account(email=email) is not None)
email_not_already_used = Validator(_("Email already registered"), lambda email: not find_ia_account(email=email))
email_not_disposable = Validator(_("Disposable email not permitted"), lambda email: not email.lower().endswith('dispostable.com'))
email_domain_not_blocked = Validator(_("Your email provider is not recognized."), lambda email: not spamcheck.is_spam_email(email))
username_validator = Validator(_("Username already used"), lambda username: not find_account(lusername=username.lower()))

vlogin = RegexpValidator(r"^[A-Za-z0-9-_]{3,20}$", _('Must be between 3 and 20 letters and numbers'))
vpass = RegexpValidator(r".{3,20}", _('Must be between 3 and 20 characters'))
vemail = RegexpValidator(r".*@.*", _("Must be a valid email address"))
Beispiel #45
0
import web
from infogami.infobase.client import ClientException
from infogami.core import forms

from openlibrary.i18n import lgettext as _
from openlibrary.utils.form import Form, Textbox, Password, Hidden, Validator, RegexpValidator


def find_account(username=None, lusername=None, email=None):
    import account
    return account.Account.find(username=username,
                                lusername=lusername,
                                email=email)


Login = Form(Textbox('username', description=_('Username'), klass='required'),
             Password('password', description=_('Password'), klass='required'),
             Hidden('redirect'))
forms.login = Login

email_already_used = Validator(
    _("No user registered with this email address"),
    lambda email: find_account(email=email) is not None)
email_not_already_used = Validator(
    _("Email already used"), lambda email: find_account(email=email) is None)
email_not_disposable = Validator(
    _("Disposable email not permitted"),
    lambda email: not email.lower().endswith('dispostable.com'))
username_validator = Validator(
    _("Username already used"),
    lambda username: not find_account(lusername=username.lower()))
Beispiel #46
0
        try:
            web.ctx.site.check_reset_code(i.username, i.code)
        except ClientException, e:
            title = _("Password reset failed.")
            message = web.safestr(e)
            return render.message(title, message)
        
        f = forms.ResetPassword()
        
        if not f.validates(i):
            return render['account/password/reset'](f)
            
        try:
            reset_password(i.username, i.code, i.password)
            web.ctx.site.login(i.username, i.password, False)
            add_flash_message('info', _("Your password has been updated successfully."))
            raise web.seeother('/')
        except Exception, e:
            add_flash_message('error', "Failed to reset password.<br/><br/> Reason: "  + str(e))
            return self.GET()


class account_notifications(delegate.page):
    path = "/account/notifications"
    
    @require_login
    def GET(self):
        prefs = web.ctx.site.get(context.user.key + "/preferences")
        d = (prefs and prefs.get('notifications')) or {}
        email = context.user.email
        return render['account/notifications'](d, email)
Beispiel #47
0
from openlibrary import accounts
from openlibrary.accounts import InternetArchiveAccount
from . import spamcheck


def find_account(username=None, lusername=None, email=None):
    return accounts.find(username=username, lusername=lusername, email=email)


def find_ia_account(email=None):
    ia_account = InternetArchiveAccount.get(email=email)
    return ia_account


Login = Form(
    Textbox('username', description=_('Username'), klass='required'),
    Password('password', description=_('Password'), klass='required'),
    Hidden('redirect'),
)
forms.login = Login

email_already_used = Validator(
    _("No user registered with this email address"),
    lambda email: find_account(email=email) is not None,
)
email_not_already_used = Validator(
    _("Email already registered"),
    lambda email: not find_ia_account(email=email))
email_not_disposable = Validator(
    _("Disposable email not permitted"),
    lambda email: not email.lower().endswith('dispostable.com'),
Beispiel #48
0
import web
from infogami.infobase.client import ClientException
from infogami.core import forms

from openlibrary.i18n import lgettext as _
from openlibrary.utils.form import Form, Textbox, Password, Hidden, Validator, RegexpValidator

Login = Form(
    Textbox('username', description=_('Username'), klass='required'),
    Password('password', description=_('Password'), klass='required'),
    Hidden('redirect')
)
forms.login = Login

email_already_used = Validator(_("No user registered with this email address"), lambda email: web.ctx.site.find_user_by_email(email) is not None)
email_not_already_used = Validator(_("Email already used"), lambda email: web.ctx.site.find_user_by_email(email) is None)
email_not_disposable = Validator(_("Disposable email not permitted"), lambda email: not email.lower().endswith('dispostable.com'))
username_validator = Validator(_("Username already used"), lambda username: not web.ctx.site._request("/has_user", data={"username": username}))

vlogin = RegexpValidator(r"^[A-Za-z0-9-_]{3,20}$", _('Must be between 3 and 20 letters and numbers')) 
vpass = RegexpValidator(r".{3,20}", _('Must be between 3 and 20 characters'))
vemail = RegexpValidator(r".*@.*", _("Must be a valid email address"))

Register = Form(
    Textbox("displayname", description=_("Your Full Name")),
    Textbox('email', description=_('Your Email Address'), klass='required', validators=[vemail, email_not_already_used, email_not_disposable]),
    Textbox('username', description=_('Choose a Username'), klass='required', help=_("Only letters and numbers, please, and at least 3 characters."), 
        validators=[vlogin, username_validator]),
    Password('password', description=_('Choose a Password'), klass='required', validators=[vpass])
)
Beispiel #49
0
class account_login(delegate.page):
    """Account login.

    Login can fail because of the following reasons:

    * account_not_found: Error message is displayed.
    * account_bad_password: Error message is displayed with a link to reset password.
    * account_not_verified: Error page is dispalyed with button to "resend verification email".
    """
    path = "/account/login"

    def GET(self):
        referer = web.ctx.env.get('HTTP_REFERER', '/')
        i = web.input(redirect=referer)
        f = forms.Login()
        f['redirect'].value = i.redirect
        return render.login(f)

    def POST(self):
        i = web.input(remember=False, redirect='/', action="login")

        if i.action == "resend_verification_email":
            return self.POST_resend_verification_email(i)
        else:
            return self.POST_login(i)

    def error(self, name, i):
        f = forms.Login()
        f.fill(i)
        f.note = utils.get_error(name)
        return render.login(f)

    def POST_login(self, i):
        # make sure the username is valid
        if not forms.vlogin.valid(i.username):
            return self.error("account_user_notfound", i)

        # Try to find account with exact username, failing which try for case variations.
        account = accounts.find(username=i.username) or accounts.find(
            lusername=i.username)

        if not account:
            return self.error("account_user_notfound", i)

        if i.redirect == "/account/login" or i.redirect == "":
            i.redirect = "/"

        status = account.login(i.password)
        if status == 'ok':
            expires = (i.remember and 3600 * 24 * 7) or ""
            web.setcookie(config.login_cookie_name,
                          web.ctx.conn.get_auth_token(),
                          expires=expires)
            raise web.seeother(i.redirect)
        elif status == "account_not_verified":
            return render_template("account/not_verified",
                                   username=account.username,
                                   password=i.password,
                                   email=account.email)
        elif status == "account_not_found":
            return self.error("account_user_notfound", i)
        elif status == "account_blocked":
            return self.error("account_blocked", i)
        else:
            return self.error("account_incorrect_password", i)

    def POST_resend_verification_email(self, i):
        try:
            accounts.login(i.username, i.password)
        except ClientException, e:
            code = e.get_data().get("code")
            if code != "account_not_verified":
                return self.error("account_incorrect_password", i)

        account = accounts.find(username=i.username)
        account.send_verification_email()

        title = _("Hi %(user)s", user=account.displayname)
        message = _(
            "We've sent the verification email to %(email)s. You'll need to read that and click on the verification link to verify your email.",
            email=account.email)
        return render.message(title, message)
Beispiel #50
0
                      web.ctx.conn.get_auth_token(),
                      expires=expires)
        raise web.seeother(i.redirect)

    def POST_resend_verification_email(self, i):
        try:
            web.ctx.site.login(i.username, i.password)
        except ClientException, e:
            code = e.get_data().get("code")
            if code != "account_not_verified":
                return self.error("account_incorrect_password", i)

        account = Account.find(username=i.username)
        send_verification_email(i.username, account.email)

        title = _("Hi %(user)s", user=account.displayname)
        message = _(
            "We've sent the verification email to %(email)s. You'll need to read that and click on the verification link to verify your email.",
            email=account.email)
        return render.message(title, message)


class account_verify(delegate.page):
    """Verify user account.
    """
    path = "/account/verify/([0-9a-f]*)"

    def GET(self, code):
        docs = web.ctx.site.store.values(type="account-link",
                                         name="code",
                                         value=code)
Beispiel #51
0
 def bad_link(self):
     title = _("Email address couldn't be verified.")
     message = _(
         "Your email address couldn't be verified. The verification link seems invalid."
     )
     return render.message(title, message)
Beispiel #52
0
class account_login(delegate.page):
    """Account login.

    Login can fail because of the following reasons:

    * account_not_found: Error message is displayed.
    * account_bad_password: Error message is displayed with a link to reset password.
    * account_not_verified: Error page is dispalyed with button to "resend verification email".
    """
    path = "/account/login"

    def GET(self):
        referer = web.ctx.env.get('HTTP_REFERER', '/')
        i = web.input(redirect=referer)
        f = forms.Login()
        f['redirect'].value = i.redirect
        return render.login(f)

    def POST(self):
        i = web.input(email='',
                      connect=None,
                      remember=False,
                      redirect='/',
                      action="login")

        if i.action == "resend_verification_email":
            return self.POST_resend_verification_email(i)
        else:
            return self.POST_login(i)

    def error(self, name, i):
        f = forms.Login()
        f.fill(i)
        f.note = utils.get_error(name)
        return render.login(f)

    def error_check(self, audit, i):
        if 'error' in audit:
            error = audit['error']
            if error == "account_not_verified":
                return render_template("account/not_verified",
                                       username=account.username,
                                       password=i.password,
                                       email=account.email)
            elif error == "account_not_found":
                return self.error("account_user_notfound", i)
            elif error == "account_blocked":
                return self.error("account_blocked", i)
            else:
                return self.error(audit['error'], i)
        if not audit['link']:
            # This needs to be overriden w/ `test`
            return self.error("accounts_not_connected", i)
        return None

    def POST_login(self, i):
        i = web.input(username="", password="", remember=False, redirect='')

        audit = audit_accounts(i.username, i.password)
        errors = self.error_check(audit, i)
        if errors:
            return errors

        blacklist = [
            "/account/login", "/account/password", "/account/email",
            "/account/create"
        ]
        if i.redirect == "" or any([path in i.redirect for path in blacklist]):
            i.redirect = "/"
        expires = (i.remember and 3600 * 24 * 7) or ""

        web.setcookie(config.login_cookie_name,
                      web.ctx.conn.get_auth_token(),
                      expires=expires)
        raise web.seeother(i.redirect)

    def POST_resend_verification_email(self, i):
        try:
            accounts.login(i.username, i.password)
        except ClientException, e:
            code = e.get_data().get("code")
            if code != "account_not_verified":
                return self.error("account_incorrect_password", i)

        account = accounts.find(username=i.username)
        account.send_verification_email()

        title = _("Hi %(user)s", user=account.displayname)
        message = _(
            "We've sent the verification email to %(email)s. You'll need to read that and click on the verification link to verify your email.",
            email=account.email)
        return render.message(title, message)
Beispiel #53
0
 def bad_link(self):
     title = _("Email address couldn't be verified.")
     message = _("Your email address couldn't be verified. The verification link seems invalid.")
     return render.message(title, message)
Beispiel #54
0
import web
from infogami.infobase.client import ClientException
from infogami.core import forms

from openlibrary.i18n import lgettext as _
from openlibrary.utils.form import Form, Textbox, Password, Hidden, Validator, RegexpValidator
from openlibrary import accounts

def find_account(username=None, lusername=None, email=None):
    return accounts.find(username=username, lusername=lusername, email=email)

Login = Form(
    Textbox('username', description=_('Username'), klass='required'),
    Password('password', description=_('Password'), klass='required'),
    Hidden('redirect')
)
forms.login = Login

email_already_used = Validator(_("No user registered with this email address"), lambda email: find_account(email=email) is not None)
email_not_already_used = Validator(_("Email already used"), lambda email: find_account(email=email) is None)
email_not_disposable = Validator(_("Disposable email not permitted"), lambda email: not email.lower().endswith('dispostable.com'))
username_validator = Validator(_("Username already used"), lambda username: not find_account(lusername=username.lower()))

vlogin = RegexpValidator(r"^[A-Za-z0-9-_]{3,20}$", _('Must be between 3 and 20 letters and numbers')) 
vpass = RegexpValidator(r".{3,20}", _('Must be between 3 and 20 characters'))
vemail = RegexpValidator(r".*@.*", _("Must be a valid email address"))

class EqualToValidator(Validator):
    def __init__(self, fieldname, message):
        Validator.__init__(self, message, None)
        self.fieldname = fieldname
Beispiel #55
0
import web
from infogami.infobase.client import ClientException
from infogami.core import forms

from openlibrary.i18n import lgettext as _
from openlibrary.utils.form import Form, Textbox, Password, Hidden, Validator, RegexpValidator

Login = Form(
    Textbox('username', description=_('Username'), klass='required'),
    Password('password', description=_('Password'), klass='required'),
    Hidden('redirect')
)
forms.login = Login

email_already_used = Validator(_("No user registered with this email address"), lambda email: web.ctx.site.find_user_by_email(email) is not None)
email_not_already_used = Validator(_("Email already used"), lambda email: web.ctx.site.find_user_by_email(email) is None)
username_validator = Validator(_("Username already used"), lambda username: web.ctx.site.get('/user/' + username) is None)

vlogin = RegexpValidator(r"^[A-Za-z0-9-_]{3,20}$", _('Must be between 3 and 20 letters and numbers')) 
vpass = RegexpValidator(r".{3,20}", _('Must be between 3 and 20 characters'))
vemail = RegexpValidator(r".*@.*", _("Must be a valid email address"))

Register = Form(
    Textbox('email', description=_('Your Email Address'), klass='required', validators=[vemail, email_not_already_used]),
    Textbox('username', description=_('Choose a Username'), klass='required', help=_("Only letters and numbers, please, and at least 3 characters."), 
        validators=[vlogin, username_validator]),
    Password('password', description=_('Choose a Password'), klass='required', validators=[vpass])
)

forms.register = Register