Пример #1
0
def send_suggestion_approved_email(journal_name, email):
    url_root = request.url_root
    if url_root.endswith("/"):
        url_root = url_root[:-1]

    to = [email]
    fro = app.config.get('SYSTEM_EMAIL_FROM', '*****@*****.**')
    subject = app.config.get("SERVICE_NAME","") + " - journal accepted"

    try:
        if app.config.get("ENABLE_PUBLISHER_EMAIL", False):
            app_email.send_mail(to=to,
                                fro=fro,
                                subject=subject,
                                template_name="email/suggestion_accepted.txt",
                                journal_name=journal_name.encode('utf-8', 'replace'),
                                url_root=url_root
            )
            flash('Sent email to ' + email + ' to tell them about their journal getting accepted into DOAJ.', 'success')
        else:
            flash('Did not send email to ' + email + ' to tell them about their journal getting accepted into DOAJ, as publisher emails are disabled.', 'error')
    except Exception as e:
        magic = str(uuid.uuid1())
        util.flash_with_url('Hm, sending the journal acceptance information email didn\'t work. Please quote this magic number when reporting the issue: ' + magic + ' . Thank you!', 'error')
        app.logger.error(magic + "\n" + repr(e))
        raise e
Пример #2
0
def forgot():
    if request.method == "POST":
        # get hold of the user account
        un = request.form.get("un", "")
        account = models.Account.pull(un)
        if account is None:
            account = models.Account.pull_by_email(un)
        if account is None:
            util.flash_with_url("Hm, sorry, your account username / email address is not recognised.", "error")
            return render_template("account/forgot.html")

        if not account.data.get("email"):
            util.flash_with_url("Hm, sorry, your account does not have an associated email address.", "error")
            return render_template("account/forgot.html")

        # if we get to here, we have a user account to reset
        reset_token = uuid.uuid4().hex
        account.set_reset_token(reset_token, app.config.get("PASSWORD_RESET_TIMEOUT", 86400))
        account.save()

        sep = "/"
        if request.url_root.endswith("/"):
            sep = ""
        reset_url = request.url_root + sep + "account/reset/" + reset_token

        to = [account.data["email"], app.config["ADMIN_EMAIL"]]
        fro = app.config["ADMIN_EMAIL"]
        subject = app.config.get("SERVICE_NAME", "") + " - password reset"
        text = "A password reset request for account '" + account.id + "' has been received and processed.\n\n"
        text += "Please visit " + reset_url + " and enter your new password.\n\n"
        text += (
            "If you are the user '"
            + account.id
            + "' and you requested this change, please visit that link now and set the password to something of your preference.\n\n"
        )
        text += (
            "If you are the user '"
            + account.id
            + "' and you did not request this change, you can ignore this email.\n\n"
        )
        text += "Regards, The OpenDOAR Team"
        try:
            util.send_mail(to=to, fro=fro, subject=subject, text=text)
            flash("Instructions to reset your password have been sent to you. Please check your emails.")
            if app.config.get("DEBUG", False):
                flash("Debug mode - url for reset is " + reset_url)
        except Exception as e:
            flash("Hm, sorry - sending the password reset email didn't work.", "error")
            if app.config.get("DEBUG", False):
                flash("Debug mode - url for reset is" + reset_url)
            # app.logger.error(magic + "\n" + repr(e))

    return render_template("account/forgot.html")
Пример #3
0
def journal_page(journal_id):
    # user must have the role "edit_journal"
    if not current_user.has_role("edit_journal"):
        abort(401)

    # get the journal, so we can check our permissions against it
    j = models.Journal.pull(journal_id)
    if j is None:
        abort(404)

    # user must be either the "admin.editor" of the journal, or the editor of the "admin.editor_group"

    # is the user the currently assigned editor of the journal?
    passed = False
    if j.editor == current_user.id:
        passed = True

    # now check whether the user is the editor of the editor group
    role = "associate_editor"
    eg = models.EditorGroup.pull_by_key("name", j.editor_group)
    if eg is not None and eg.editor == current_user.id:
        passed = True
        role = "editor"

    # if the user wasn't the editor or the owner of the editor group, unauthorised
    if not passed:
        abort(401)

    # attempt to get a lock on the object
    try:
        lockinfo = lock.lock("journal", journal_id, current_user.id)
    except lock.Locked as l:
        return render_template("editor/journal_locked.html", journal=j, lock=l.lock, edit_journal_page=True)

    if request.method == "GET":
        fc = formcontext.JournalFormFactory.get_form_context(role=role, source=j)
        return fc.render_template(edit_journal_page=True, lock=lockinfo)
    elif request.method == "POST":
        fc = formcontext.JournalFormFactory.get_form_context(role=role, form_data=request.form, source=j)
        if fc.validate():
            try:
                fc.finalise()
                flash('Journal updated.', 'success')
                for a in fc.alert:
                    flash_with_url(a, "success")
                return redirect(url_for("editor.journal_page", journal_id=j.id, _anchor='done'))
            except formcontext.FormContextException as e:
                flash(e.message)
                return redirect(url_for("editor.journal_page", journal_id=j.id, _anchor='cannot_edit'))
        else:
            return fc.render_template(edit_journal_page=True, lock=lockinfo)
Пример #4
0
def journal_page(journal_id):
    # user must have the role "edit_journal"
    if not current_user.has_role("edit_journal"):
        abort(401)

    # get the journal, so we can check our permissions against it
    j = models.Journal.pull(journal_id)
    if j is None:
        abort(404)

    # user must be either the "admin.editor" of the journal, or the editor of the "admin.editor_group"

    # is the user the currently assigned editor of the journal?
    passed = False
    if j.editor == current_user.id:
        passed = True

    # now check whether the user is the editor of the editor group
    role = "associate_editor"
    eg = models.EditorGroup.pull_by_key("name", j.editor_group)
    if eg is not None and eg.editor == current_user.id:
        passed = True
        role = "editor"

    # if the user wasn't the editor or the owner of the editor group, unauthorised
    if not passed:
        abort(401)

    # attempt to get a lock on the object
    try:
        lockinfo = lock.lock("journal", journal_id, current_user.id)
    except lock.Locked as l:
        return render_template("editor/journal_locked.html", journal=j, lock=l.lock, edit_journal_page=True)

    if request.method == "GET":
        fc = formcontext.JournalFormFactory.get_form_context(role=role, source=j)
        return fc.render_template(edit_journal_page=True, lock=lockinfo)
    elif request.method == "POST":
        fc = formcontext.JournalFormFactory.get_form_context(role=role, form_data=request.form, source=j)
        if fc.validate():
            try:
                fc.finalise()
                flash('Journal updated.', 'success')
                for a in fc.alert:
                    flash_with_url(a, "success")
                return redirect(url_for("editor.journal_page", journal_id=j.id, _anchor='done'))
            except formcontext.FormContextException as e:
                flash(str(e))
                return redirect(url_for("editor.journal_page", journal_id=j.id, _anchor='cannot_edit'))
        else:
            return fc.render_template(edit_journal_page=True, lock=lockinfo)
Пример #5
0
def journal_page(journal_id):
    if not current_user.has_role("edit_journal"):
        abort(401)
    ap = models.Journal.pull(journal_id)
    if ap is None:
        abort(404)

    # attempt to get a lock on the object
    try:
        lockinfo = lock.lock("journal", journal_id, current_user.id)
    except lock.Locked as l:
        return render_template("admin/journal_locked.html",
                               journal=ap,
                               lock=l.lock,
                               edit_journal_page=True)

    if request.method == "GET":
        job = None
        job_id = request.values.get("job")
        if job_id is not None and job_id != "":
            job = models.BackgroundJob.pull(job_id)
        fc = formcontext.JournalFormFactory.get_form_context(role="admin",
                                                             source=ap)
        return fc.render_template(edit_journal_page=True,
                                  lock=lockinfo,
                                  job=job)
    elif request.method == "POST":
        fc = formcontext.JournalFormFactory.get_form_context(
            role="admin", form_data=request.form, source=ap)
        if fc.validate():
            try:
                fc.finalise()
                flash('Journal updated.', 'success')
                for a in fc.alert:
                    flash_with_url(a, "success")
                return redirect(
                    url_for("admin.journal_page",
                            journal_id=ap.id,
                            _anchor='done'))
            except formcontext.FormContextException as e:
                flash(str(e))
                return redirect(
                    url_for("admin.journal_page",
                            journal_id=ap.id,
                            _anchor='cannot_edit'))
        else:
            return fc.render_template(edit_journal_page=True, lock=lockinfo)
Пример #6
0
def suggestion_page(suggestion_id):
    if not current_user.has_role("edit_suggestion"):
        abort(401)
    ap = models.Suggestion.pull(suggestion_id)
    if ap is None:
        abort(404)

    # attempt to get a lock on the object
    try:
        lockinfo = lock.lock("suggestion", suggestion_id, current_user.id)
    except lock.Locked as l:
        return render_template("admin/suggestion_locked.html",
                               suggestion=ap,
                               lock=l.lock,
                               edit_suggestion_page=True)

    if request.method == "GET":
        fc = formcontext.ApplicationFormFactory.get_form_context(role="admin",
                                                                 source=ap)
        return fc.render_template(edit_suggestion_page=True, lock=lockinfo)
    elif request.method == "POST":
        fc = formcontext.ApplicationFormFactory.get_form_context(
            role="admin", form_data=request.form, source=ap)
        if fc.validate():
            try:
                fc.finalise()
                flash('Application updated.', 'success')
                for a in fc.alert:
                    flash_with_url(a, "success")
                return redirect(
                    url_for("admin.suggestion_page",
                            suggestion_id=ap.id,
                            _anchor='done'))
            except formcontext.FormContextException as e:
                flash(str(e))
                return redirect(
                    url_for("admin.suggestion_page",
                            suggestion_id=ap.id,
                            _anchor='cannot_edit'))
        else:
            return fc.render_template(edit_suggestion_page=True, lock=lockinfo)
Пример #7
0
def forgot():
    if request.method == 'POST':
        # get hold of the user account
        un = request.form.get('un', "")
        account = models.Account.pull(un)
        if account is None:
            account = models.Account.pull_by_email(un)
        if account is None:
            util.flash_with_url('Your account email address is not recognised.', 'error')
            return render_template('account/forgot.html')

        if account.is_deleted():
            util.flash_with_url('Your account email address is not recognised.', 'error')
            return render_template('account/forgot.html')

        if account.is_banned():
            flash('This account is banned from the service', 'error')
            return render_template('account/forgot.html')

        if not account.data.get('email'):
            util.flash_with_url('Your account does not have an associated email address.', 'error')
            return render_template('account/forgot.html')

        # if we get to here, we have a user account to reset
        reset_token = uuid.uuid4().hex
        account.set_reset_token(reset_token, app.config.get("PASSWORD_RESET_TIMEOUT", 86400))
        account.save()

        sep = "/"
        if request.url_root.endswith("/"):
            sep = ""
        reset_url = request.url_root + sep + "account/reset/" + reset_token

        to = [account.data['email'], app.config['FEEDBACK_EMAIL']]
        fro = app.config['FEEDBACK_EMAIL']
        subject = app.config.get("SERVICE_NAME", "") + " - password reset"
        text = "A password reset request for account '" + account.id + "' has been received and processed.\n\n"
        text += "Please visit " + reset_url + " and enter your new password.\n\n"
        text += "If you are the user " + account.id + " and you requested this change, please visit that link now and set the password to something of your preference.\n\n"
        text += "If you are the user " + account.id + " and you did not request this change, you can ignore this email.\n\n"
        text += "Regards, The UniBoard Team"
        try:
            util.send_mail(to=to, fro=fro, subject=subject, text=text)
            flash('Instructions to reset your password have been sent to you. Please check your emails.', "success")
            if app.config.get('DEBUG', False):
                flash('Debug mode - url for reset is ' + reset_url, "error")
        except Exception as e:
            flash('Hm, sorry - sending the password reset email didn\'t work.', 'error')
            if app.config.get('DEBUG', False):
                flash('Debug mode - url for reset is' + reset_url, "error")
                # app.logger.error(magic + "\n" + repr(e))

    return render_template('account/forgot.html')
Пример #8
0
def forgot():
    CONTACT_INSTR = ' Please <a href="{url}">contact us.</a>'.format(url=url_for('doaj.contact'))
    if request.method == 'POST':
        # get hold of the user account
        un = request.form.get('un',"")
        account = models.Account.pull(un)
        if account is None: 
            account = models.Account.pull_by_email(un)
        if account is None:
            util.flash_with_url('Hm, sorry, your account username / email address is not recognised.' + CONTACT_INSTR, 'error')
            return render_template('account/forgot.html')
        
        if not account.data.get('email'):
            util.flash_with_url('Hm, sorry, your account does not have an associated email address.' + CONTACT_INSTR, 'error')
            return render_template('account/forgot.html')

        # if we get to here, we have a user account to reset
        #newpass = util.generate_password()
        #account.set_password(newpass)
        reset_token = uuid.uuid4().hex
        account.set_reset_token(reset_token, app.config.get("PASSWORD_RESET_TIMEOUT", 86400))
        account.save()
        
        sep = "/"
        if request.url_root.endswith("/"):
            sep = ""
        reset_url = request.url_root + sep + "account/reset/" + reset_token

        to = [account.data['email']]
        fro = app.config.get('SYSTEM_EMAIL_FROM', app.config['ADMIN_EMAIL'])
        subject = app.config.get("SERVICE_NAME","") + " - password reset"
        try:
            app_email.send_mail(to=to,
                                fro=fro,
                                subject=subject,
                                template_name="email/password_reset.txt",
                                account_id=account.id,
                                reset_url=reset_url,
                                )
            flash('Instructions to reset your password have been sent to you. Please check your emails.')
            if app.config.get('DEBUG',False):
                flash('Debug mode - url for reset is ' + reset_url)
        except Exception as e:
            magic = str(uuid.uuid1())
            util.flash_with_url('Hm, sorry - sending the password reset email didn\'t work.' + CONTACT_INSTR + ' It would help us if you also quote this magic number: ' + magic + ' . Thank you!', 'error')
            if app.config.get('DEBUG',False):
                flash('Debug mode - url for reset is ' + reset_url)
            app.logger.error(magic + "\n" + repr(e))

    return render_template('account/forgot.html')
Пример #9
0
def forgot():
    CONTACT_INSTR = ' Please <a href="{url}">contact us.</a>'.format(url=url_for('doaj.contact'))
    if request.method == 'POST':
        # get hold of the user account
        un = request.form.get('un', "")
        account = models.Account.pull(un)
        if account is None:
            account = models.Account.pull_by_email(un)
        if account is None:
            util.flash_with_url('Hm, sorry, your account username / email address is not recognised.' + CONTACT_INSTR, 'error')
            return render_template('account/forgot.html')

        if not account.data.get('email'):
            util.flash_with_url('Hm, sorry, your account does not have an associated email address.' + CONTACT_INSTR, 'error')
            return render_template('account/forgot.html')

        # if we get to here, we have a user account to reset
        #newpass = util.generate_password()
        #account.set_password(newpass)
        reset_token = uuid.uuid4().hex
        account.set_reset_token(reset_token, app.config.get("PASSWORD_RESET_TIMEOUT", 86400))
        account.save()

        sep = "/"
        if request.url_root.endswith("/"):
            sep = ""
        reset_url = request.url_root + sep + "account/reset/" + reset_token

        to = [account.data['email']]
        fro = app.config.get('SYSTEM_EMAIL_FROM', app.config['ADMIN_EMAIL'])
        subject = app.config.get("SERVICE_NAME", "") + " - password reset"
        try:
            app_email.send_mail(to=to,
                                fro=fro,
                                subject=subject,
                                template_name="email/password_reset.txt",
                                account_id=account.id,
                                reset_url=reset_url,
                                )
            flash('Instructions to reset your password have been sent to you. Please check your emails.')
            if app.config.get('DEBUG', False):
                flash('Debug mode - url for reset is ' + reset_url)
        except Exception as e:
            magic = str(uuid.uuid1())
            util.flash_with_url('Hm, sorry - sending the password reset email didn\'t work.' + CONTACT_INSTR + ' It would help us if you also quote this magic number: ' + magic + ' . Thank you!', 'error')
            if app.config.get('DEBUG', False):
                flash('Debug mode - url for reset is ' + reset_url)
            app.logger.error(magic + "\n" + repr(e))

    return render_template('account/forgot.html')
Пример #10
0
def suggestion_form(form, request, template_name, existing_suggestion=None, success_url=None,
                    process_the_form=True, group_editable=False, editorial_available=False, redirect_route=None, lock=None, **kwargs):

    first_field_with_error = ''

    #import json
    #print json.dumps(request.form, indent=3)

    #import json
    #print json.dumps(form.data, indent=3)

    # the code below will output only submitted values which were truthy
    # useful for debugging the form itself without getting lost in the
    # 57-field object that gets created
    #print
    #print
    #for field in form:
    #    #if field.data and field.data != 'None':
    #    if field.short_name == 'subject':
    #        print field.short_name, '::', field.data, ',', type(field.data)
    #print

    if request.method == 'POST':
        if not process_the_form:
            if existing_suggestion:
                # this is not a success, so we do not consider the success_url
                return redirect(url_for(redirect_route, suggestion_id=existing_suggestion.id, _anchor='cannot_edit'))
        else:
            #if form.make_all_fields_optional.data:
            #    valid = True
            #else:
            #    valid = form.validate()
            valid = form.validate()
            if valid:
                email_editor = False
                if group_editable:
                    email_editor = SuggestionFormXWalk.is_new_editor_group(form, existing_suggestion)

                email_associate = False
                if editorial_available:
                    email_associate = SuggestionFormXWalk.is_new_editor(form, existing_suggestion)

                # do the core crosswalk
                suggestion = SuggestionFormXWalk.form2obj(form, existing_suggestion)

                now = datetime.now().strftime("%Y-%m-%dT%H:%M:%SZ")
                if not existing_suggestion:
                    suggestion.suggested_on = now
                    suggestion.set_application_status('pending')
                else:
                    # copy over any important fields from the previous version of the object
                    created_date = existing_suggestion.created_date if existing_suggestion.created_date else now
                    suggestion.set_created(created_date)
                    suggestion.suggested_on = existing_suggestion.suggested_on
                    suggestion.data['id'] = existing_suggestion.data['id']
                    if ((suggestion.owner is None or suggestion.owner == "") and (existing_suggestion.owner is not None)) or not current_user.has_role("admin"):
                        suggestion.set_owner(existing_suggestion.owner)

                    if not group_editable or not editorial_available:
                        suggestion.set_editor_group(existing_suggestion.editor_group)

                    if not editorial_available:
                        suggestion.set_editor(existing_suggestion.editor)

                    # FIXME: probably should check that the editor is in the editor_group and remove if not

                # the code below can be used to quickly debug objects which
                # fail to serialise as JSON - there should be none of those
                # in the suggestion!
                '''
                import json
                for thing in suggestion.data:
                    try:
                        if thing == 'bibjson':
                            bibjson = suggestion.bibjson().bibjson
                            for thing2 in bibjson:
                                try:
                                    print json.dumps(bibjson[thing2])
                                except TypeError as e:
                                    print 'This is it:',thing2
                                    print e
                                    print
                                    print json.dumps(bibjson[thing2])
                    except TypeError as e:
                        print 'This is it:',thing
                        print e
                        print
                '''

                # the code below produces a dump of the object returned by
                # the crosswalk
                '''
                import json
                print
                print
                print 'Now all the data!'

                print json.dumps(suggestion.data, indent=3)
                '''

                suggestion.save()
                if existing_suggestion:
                    flash('Application updated.', 'success')
                    if suggestion.application_status == 'accepted':
                        # this suggestion is just getting accepted
                        j = journal.suggestion2journal(suggestion)
                        j.set_in_doaj(True)
                        j.save()
                        qobj = j.make_query(q=j.id)
                        jurl = url_for('admin.admin_site_search') + '?source=' + json.dumps(qobj).replace('"', '&quot;')
                        flash_with_url('<a href="{url}" target="_blank">New journal created</a>.'.format(url=jurl), 'success')
                        owner = create_account_on_suggestion_approval(suggestion, j)
                        send_suggestion_approved_email(j.bibjson().title, owner.email)

                # only actually send the email when we've successfully processed the form
                if email_editor:
                    send_editor_group_email(suggestion)

                if email_associate:
                    send_editor_email(suggestion)

                if success_url:
                    return redirect(success_url)
                else:
                    return redirect(url_for(redirect_route, suggestion_id=suggestion.id, _anchor='done'))
            else:
                for field in form:  # in order of definition of fields, so the order of rendering should be (manually) kept the same as the order of definition for this to work
                    if field.errors:
                        first_field_with_error = field.short_name
                        print "field with error", first_field_with_error
                        break
    return render_template(
            template_name,
            form=form,
            first_field_with_error=first_field_with_error,
            q_numbers=xrange(1, 10000).__iter__(),  # a generator for the purpose of displaying numbered questions
            other_val=other_val,
            digital_archiving_policy_specific_library_value=digital_archiving_policy_specific_library_value,
            edit_suggestion_page=True,
            group_editable=group_editable,
            editorial_available=editorial_available,
            lock=lock,
            **kwargs
    )
Пример #11
0
def create_account_on_suggestion_approval(suggestion, journal):
    o = Account.pull(suggestion.owner)
    if o:
        flash('Account {username} already exists, so simply associating the new journal with it.'.format(username=o.id), 'success')
        o.add_journal(journal.id)
        if not o.has_role('publisher'):
            o.add_role('publisher')
        o.save()
        return o

    suggestion_contact = util.listpop(suggestion.contacts())
    if not suggestion_contact.get('email'):
        msg = ERROR_MSG_TEMPLATE.format(username=o.id, missing_thing='journal contact email in the application')
        app.logger.error(msg)
        flash(msg)
        return o

    send_info_to = suggestion_contact.get('email')
    o = Account.make_account(
        suggestion.owner,
        name=suggestion_contact.get('name'),
        email=send_info_to,
        roles=['publisher'],
        associated_journal_ids=[journal.id]
    )

    o.save()

    url_root = request.url_root
    if url_root.endswith("/"):
        url_root = url_root[:-1]

    if not o.reset_token:
        msg = ERROR_MSG_TEMPLATE.format(username=o.id, missing_thing='reset token')
        app.logger.error(msg)
        flash(msg)
        return o

    reset_url = url_root + url_for('account.reset', reset_token=o.reset_token)
    forgot_pw_url = url_root + url_for('account.forgot')


    password_create_timeout_seconds = int(app.config.get("PASSWORD_CREATE_TIMEOUT", app.config.get('PASSWORD_RESET_TIMEOUT', 86400) * 14))
    password_create_timeout_days = password_create_timeout_seconds / (60*60*24)

    to = [send_info_to]
    fro = app.config.get('SYSTEM_EMAIL_FROM', '*****@*****.**')
    subject = app.config.get("SERVICE_NAME","") + " - account created"


    try:
        if app.config.get("ENABLE_PUBLISHER_EMAIL", False):
            app_email.send_mail(to=to,
                                fro=fro,
                                subject=subject,
                                template_name="email/account_created.txt",
                                reset_url=reset_url,
                                username=o.id,
                                timeout_days=password_create_timeout_days,
                                forgot_pw_url=forgot_pw_url
            )
            flash('Sent email to ' + send_info_to + ' to tell them about the new account.', 'success')
        else:
            flash('Did not email to ' + send_info_to + ' to tell them about the new account, as publisher emailing is disabled.', 'error')
        if app.config.get('DEBUG',False):
            util.flash_with_url('Debug mode - url for create is <a href="{url}">{url}</a>'.format(url=reset_url))
    except Exception as e:
        magic = str(uuid.uuid1())
        util.flash_with_url('Hm, sending the account creation email didn\'t work. Please quote this magic number when reporting the issue: ' + magic + ' . Thank you!', 'error')
        if app.config.get('DEBUG',False):
            util.flash_with_url('Debug mode - url for create is <a href="{url}">{url}</a>'.format(url=reset_url))
        app.logger.error(magic + "\n" + repr(e))
        raise e

    flash('Account {username} created'.format(username=o.id), 'success')
    return o