Beispiel #1
0
    def send_mail(self, username, profile):
        site = find_site(self.context)
        title = get_setting(self.context, 'title')
        subject = 'Thank you for joining %s' % title
        body_template = get_renderer(
            'templates/email_accept_site_invitation.pt').implementation()

        system_email_domain = get_setting(self.context, 'system_email_domain')
        from_name = '%s invitation' % title
        from_email = 'invitation@%s' % system_email_domain
        mailer = getUtility(IMailDelivery)
        msg = MIMEMultipart('alternative')
        msg['From'] = '%s <%s>' % (from_name, from_email)
        msg['To'] = profile.email
        msg['Subject'] = subject
        bodyhtml = body_template(
            username=username,
            site_href=resource_url(site, self.request),
            system_name=title
            )
        bodyplain = html2text.html2text(bodyhtml)
        htmlpart = MIMEText(bodyhtml.encode('UTF-8'), 'html', 'UTF-8')
        plainpart = MIMEText(bodyplain.encode('UTF-8'), 'plain', 'UTF-8')
        msg.attach(plainpart)
        msg.attach(htmlpart)
        mailer.send([profile.email], msg)
Beispiel #2
0
def error_monitor_status_view(context, request):
    """
    Simple text only view that shows only error state, for use with external
    monitoring.
    """
    error_monitor_dir = get_setting(context, 'error_monitor_dir')
    subsystems = get_setting(context, 'error_monitor_subsystems')
    subsystems = subsystems + ['postoffice quarantine']

    req_subsystems = request.params.getall('subsystem')
    if req_subsystems:
        subsystems = filter(lambda x: x in subsystems, req_subsystems)

    buf = StringIO()
    for subsystem in subsystems:
        # Special case postoffice quarantine
        if subsystem == 'postoffice quarantine':
            use_postoffice = not not get_setting(
                context, 'postoffice.zodb_uri', False)
            if  use_postoffice:
                queue, closer = _get_postoffice_queue(request.context)
                if queue.count_quarantined_messages() == 0:
                    print >>buf, 'postoffice quarantine: OK'
                else:
                    print >>buf, 'postoffice quarantine: ERROR'

        # Normal case
        elif _get_error_monitor_state(error_monitor_dir, subsystem):
            print >>buf, '%s: ERROR' % subsystem
        else:
            print >>buf, '%s: OK' % subsystem

    return Response(buf.getvalue(), content_type='text/plain')
def admin_menu(context, request):
    admin_settings = {}
    site = find_site(context)
    settings = request.registry.settings
    syslog_view = get_setting(context, 'syslog_view', None)
    admin_settings['syslog_view_enabled'] = syslog_view != None
    admin_settings['has_logs'] = not not get_setting(context, 'logs_view', None)
    admin_settings['redislog'] = asbool(settings.get('redislog', 'False'))
    admin_settings['can_administer'] = has_permission('administer', site, request)
    admin_settings['can_email'] = has_permission('email', site, request)
    statistics_folder = get_setting(context, 'statistics_folder', None)
    if statistics_folder is not None and os.path.exists(statistics_folder):
        csv_files = [fn for fn in os.listdir(statistics_folder)
                    if fn.endswith('.csv')]
        admin_settings['statistics_view_enabled'] = not not csv_files
    else:
        admin_settings['statistics_view_enabled'] = False
    admin_settings['quarantine_url'] = ('%s/po_quarantine.html' %
                            request.application_url)
    site = find_site(context)
    if 'offices' in site:
        admin_settings['offices_url'] = resource_url(site['offices'], request)
    else:
        admin_settings['offices_url'] = None
    admin_settings['has_mailin'] = (
        get_setting(context, 'zodbconn.uri.postoffice') and
        get_setting(context, 'postoffice.queue'))
    return admin_settings
Beispiel #4
0
    def send_digests(self, context):
        mailer = getUtility(IMailDelivery)

        system_name = get_setting(context, "system_name", "KARL")
        system_email_domain = get_setting(context, "system_email_domain")
        sent_from = "%s@%s" % (system_name, system_email_domain)
        from_addr = "%s <%s>" % (system_name, sent_from)
        subject = "[%s] Your alerts digest" % system_name

        template = get_template("email_digest.pt")
        for profile in find_profiles(context).values():
            if not profile._pending_alerts:
                continue

            # Perform each in its own transaction, so a problem with one
            # user's email doesn't block all others
            transaction.manager.begin()
            try:
                attachments = []
                for alert in profile._pending_alerts:
                    attachments += alert['attachments']

                msg = MIMEMultipart() if attachments else Message()
                msg["From"] = from_addr
                msg["To"] = "%s <%s>" % (profile.title, profile.email)
                msg["Subject"] = subject

                body_text = template(
                    system_name=system_name,
                    alerts=profile._pending_alerts,
                )

                if isinstance(body_text, unicode):
                    body_text = body_text.encode("UTF-8")

                if attachments:
                    body = MIMEText(body_text, 'html', 'utf-8')
                    msg.attach(body)
                else:
                    msg.set_payload(body_text, "UTF-8")
                    msg.set_type("text/html")

                for attachment in attachments:
                    msg.attach(attachment)

                mailer.send(sent_from, [profile.email,], msg)
                del profile._pending_alerts[:]
                transaction.manager.commit()

            except Exception, e:
                # Log error and continue
                log.error("Error sending digest to %s <%s>" %
                          (profile.title, profile.email))

                b = StringIO()
                traceback.print_exc(file=b)
                log.error(b.getvalue())
                b.close()

                transaction.manager.abort()
Beispiel #5
0
def _get_postoffice_queue(context):
    zodb_uri = get_setting(context, 'zodbconn.uri.postoffice')
    queue_name = get_setting(context, 'postoffice.queue')
    if zodb_uri and queue_name:
        db = context._p_jar.db().databases['postoffice']
        return open_queue(db, queue_name)
    return None, None
Beispiel #6
0
    def __init__(self, context, request, page_title=None):
        super(AdminTemplateAPI, self).__init__(context, request, page_title)
        settings = request.registry.settings
        syslog_view = get_setting(context, 'syslog_view', None)
        self.syslog_view_enabled = syslog_view != None
        self.has_logs = not not get_setting(context, 'logs_view', None)
        self.redislog = asbool(settings.get('redislog', 'False'))
        statistics_folder = get_setting(context, 'statistics_folder', None)
        if statistics_folder is not None and os.path.exists(statistics_folder):
            csv_files = [fn for fn in os.listdir(statistics_folder)
                         if fn.endswith('.csv')]
            self.statistics_view_enabled = not not csv_files
        else:
            self.statistics_view_enabled = False

        self.quarantine_url = ('%s/po_quarantine.html' %
                               request.application_url)

        site = find_site(context)
        if 'offices' in site:
            self.offices_url = resource_url(site['offices'], request)
        else:
            self.offices_url = None

        self.has_mailin = (
            get_setting(context, 'zodbconn.uri.postoffice') and
            get_setting(context, 'postoffice.queue'))
Beispiel #7
0
    def run():
        root, closer = get_root(app)
        set_subsystem('mailin')

        zodb_uri = get_setting(root, 'postoffice.zodb_uri')
        zodb_path = get_setting(root, 'postoffice.zodb_path', '/postoffice')
        queue = get_setting(root, 'postoffice.queue')

        if zodb_uri is None:
            parser.error("postoffice.zodb_uri must be set in config file")

        if queue is None:
            parser.error("postoffice.queue must be set in config file")

        runner = MailinRunner2(root, zodb_uri, zodb_path, queue)
        try:
            runner()

            if options.dry_run:
                transaction.abort()
            else:
                transaction.commit()

            p_jar = getattr(root, '_p_jar', None)
            if p_jar is not None:
                # Attempt to fix memory leak
                p_jar.db().cacheMinimize()

        except:
            transaction.abort()
            raise

        finally:
            closer()
            runner.close()
Beispiel #8
0
    def __init__(self, context, request, page_title=None):
        super(AdminTemplateAPI, self).__init__(context, request, page_title)
        syslog_view = get_setting(context, 'syslog_view', None)
        self.syslog_view_enabled = syslog_view != None
        self.has_logs = not not get_setting(context, 'logs_view', None)
        self.error_monitoring = not not get_setting(
            context, 'error_monitor_subsystems', None
        )
        statistics_folder = get_setting(context, 'statistics_folder', None)
        if statistics_folder is not None and os.path.exists(statistics_folder):
            csv_files = [fn for fn in os.listdir(statistics_folder)
                         if fn.endswith('.csv')]
            self.statistics_view_enabled = not not csv_files
        else:
            self.statistics_view_enabled = False

        use_postoffice = not not get_setting(
            context, 'postoffice.zodb_uri', False)
        if use_postoffice:
            self.quarantine_url = ('%s/po_quarantine.html' %
                                   request.application_url)
        else:
            self.quarantine_url = ('%s/mailin/quarantine' %
                                   request.application_url)

        site = find_site(context)
        if 'offices' in site:
            self.offices_url = resource_url(site['offices'], request)
        else:
            self.offices_url = None
Beispiel #9
0
def syslog_view(context, request):
    syslog_path = get_setting(context, "syslog_view")
    instances = get_setting(context, "syslog_view_instances", ["karl"])
    filter_instance = request.params.get("instance", "_any")
    if filter_instance == "_any":
        filter_instances = instances
    else:
        filter_instances = [filter_instance]

    def line_filter(line):
        try:
            month, day, time, host, instance, message = line.split(None, 5)
        except ValueError:
            # Ignore lines that don't fit the format
            return None

        if instance not in filter_instances:
            return None

        return line

    if syslog_path:
        syslog = codecs.open(syslog_path, encoding="utf-8", errors="replace")
    else:
        syslog = StringIO()

    batch_info = get_fileline_batch(syslog, context, request, line_filter=line_filter, backwards=True)

    return dict(
        api=AdminTemplateAPI(context, request),
        menu=_menu_macro(),
        instances=instances,
        instance=filter_instance,
        batch_info=batch_info,
    )
Beispiel #10
0
def error_monitor_view(context, request):
    error_monitor_dir = get_setting(context, "error_monitor_dir", "")
    subsystems = get_setting(context, "error_monitor_subsystems")
    states = {}
    urls = {}
    for subsystem in subsystems:
        urls[subsystem] = model_url(context, request, "error_monitor_subsystem.html", query={"subsystem": subsystem})
        states[subsystem] = _get_error_monitor_state(error_monitor_dir, subsystem)

    # Tack on mailin quarantine status while we're at it
    use_postoffice = not not get_setting(context, "postoffice.zodb_uri", False)
    if use_postoffice:
        name = "postoffice quarantine"
        urls[name] = "%s/po_quarantine.html" % request.application_url
        queue, closer = _get_postoffice_queue(request.context)
        if queue.count_quarantined_messages() > 0:
            states[name] = ["Messages in quarantine."]
        else:
            states[name] = []
        subsystems = list(subsystems)
        subsystems.append(name)

    return dict(
        api=AdminTemplateAPI(context, request), menu=_menu_macro(), subsystems=subsystems, urls=urls, states=states
    )
Beispiel #11
0
def request_password_reset(user, profile, request):
    profile.password_reset_key = sha1(
        str(random.random())).hexdigest()
    profile.password_reset_time = datetime.datetime.now()
    context = find_site(profile)
    reset_url = resource_url(
        context, request, "reset_confirm.html",
        query=dict(key=profile.password_reset_key))

    # send email
    mail = MIMEMultipart('alternative')
    system_name = get_setting(context, 'title', 'KARL')
    admin_email = get_setting(context, 'admin_email')
    mail["From"] = "%s Administrator <%s>" % (system_name, admin_email)
    mail["To"] = "%s <%s>" % (profile.title, profile.email)
    mail["Subject"] = "%s Password Reset Request" % system_name
    bodyhtml = render(
        "templates/email_reset_password.pt",
        dict(login=user['login'],
             reset_url=reset_url,
             system_name=system_name),
        request=request,
    )
    bodyplain = html2text.html2text(bodyhtml)
    htmlpart = MIMEText(bodyhtml.encode('UTF-8'), 'html', 'UTF-8')
    plainpart = MIMEText(bodyplain.encode('UTF-8'), 'plain', 'UTF-8')
    mail.attach(plainpart)
    mail.attach(htmlpart)
    recipients = [profile.email]
    mailer = getUtility(IMailDelivery)
    mailer.send(recipients, mail)
Beispiel #12
0
def _get_aspell_settings(context):
    D = {}
    D['executable'] = get_setting(context, 'aspell_executable', 'aspell')
    D['max_words'] = int(get_setting(context, 'aspell_max_words', 5000))
    langs_csv = get_setting(context, 'aspell_languages', 'en')  
    D['languages'] = [x.strip() for x in langs_csv.split(',')]
    return D
def request_password_reset(user, profile, request):
    profile.password_reset_key = sha1(
        str(random.random())).hexdigest()
    profile.password_reset_time = datetime.datetime.now()
    context = find_site(profile)
    reset_url = resource_url(
        context, request, "reset_confirm.html",
        query=dict(key=profile.password_reset_key))

    # send email
    mail = Message()
    system_name = get_setting(context, 'system_name', 'KARL')
    admin_email = get_setting(context, 'admin_email')
    mail["From"] = "%s Administrator <%s>" % (system_name, admin_email)
    mail["To"] = "%s <%s>" % (profile.title, profile.email)
    mail["Subject"] = "%s Password Reset Request" % system_name
    body = render(
        "templates/email_reset_password.pt",
        dict(login=user['login'],
             reset_url=reset_url,
             system_name=system_name),
        request=request,
    )

    if isinstance(body, unicode):
        body = body.encode("UTF-8")

    mail.set_payload(body, "UTF-8")
    mail.set_type("text/html")

    recipients = [profile.email]
    mailer = getUtility(IMailDelivery)
    mailer.send(recipients, mail)
Beispiel #14
0
def error_monitor_subsystem_view(context, request):
    error_monitor_dir = get_setting(context, 'error_monitor_dir', '')
    subsystems = get_setting(context, 'error_monitor_subsystems')
    subsystem = request.params.get('subsystem', None)
    if subsystem is None or subsystem not in subsystems:
        raise NotFound()

    back_url = resource_url(context, request, 'error_monitor.html')
    if 'clear' in request.params:
        path = os.path.join(error_monitor_dir, subsystem)
        os.remove(path)
        return HTTPFound(location=back_url)


    clear_url = resource_url(context, request, request.view_name,
                          query={'clear': '1', 'subsystem': subsystem})
    entries = _get_error_monitor_state(error_monitor_dir, subsystem)

    return dict(
        api=AdminTemplateAPI(context, request),
        menu=_menu_macro(),
        subsystem=subsystem,
        entries=entries,
        back_url=back_url,
        clear_url=clear_url,
    )
Beispiel #15
0
def syslog_view(context, request):
    syslog_path = get_setting(context, 'syslog_view')
    instances = get_setting(context, 'syslog_view_instances', ['karl'])
    filter_instance = request.params.get('instance', '_any')
    if filter_instance == '_any':
        filter_instances = instances
    else:
        filter_instances = [filter_instance]

    entries = []
    with codecs.open(syslog_path, encoding='utf-8',
                     errors='replace') as syslog:
        for line in syslog:
            line = _decode(line)
            try:
                month, day, time, host, instance, message = line.split(None, 5)
            except ValueError:
                # Ignore lines that don't fit the format
                continue

            if instance not in filter_instances:
                continue
            entries.append(line)
    entries.reverse() # Show more recent entries first

    return render_template_to_response(
        'templates/admin/syslog.pt',
        api=AdminTemplateAPI(context, request),
        menu=_menu_macro(),
        instances=instances,
        instance=filter_instance,
        entries=entries,
    )
Beispiel #16
0
def error_monitor_view(context, request):
    error_monitor_dir = get_setting(context, 'error_monitor_dir', '')
    subsystems = get_setting(context, 'error_monitor_subsystems')
    states = {}
    urls = {}
    for subsystem in subsystems:
        urls[subsystem] = resource_url(context, request,
                                    'error_monitor_subsystem.html',
                                    query={'subsystem': subsystem})
        states[subsystem] = _get_error_monitor_state(
            error_monitor_dir, subsystem
        )

    # Tack on mailin quarantine status while we're at it
    use_postoffice = not not get_setting(
        context, 'postoffice.zodb_uri', False)
    if  use_postoffice:
        name = 'postoffice quarantine'
        urls[name] = '%s/po_quarantine.html' % request.application_url
        queue, closer = _get_postoffice_queue(request.context)
        if queue.count_quarantined_messages() > 0:
            states[name] = ['Messages in quarantine.']
        else:
            states[name] = []
        subsystems = list(subsystems)
        subsystems.append(name)

    return dict(
        api=AdminTemplateAPI(context, request),
        menu=_menu_macro(),
        subsystems=subsystems,
        urls=urls,
        states=states,
    )
Beispiel #17
0
def mailin(args, instance):
    log.info("Processing mailin for %s" % instance)
    root, closer = args.get_root(instance)
    set_current_instance(instance)
    set_subsystem('mailin')

    zodb_uri = get_setting(root, 'postoffice.zodb_uri')
    zodb_path = get_setting(root, 'postoffice.zodb_path', '/postoffice')
    queue = get_setting(root, 'postoffice.queue')

    if zodb_uri is None:
        args.parser.error("postoffice.zodb_uri must be set in config file")

    if queue is None:
        args.parser.error("postoffice.queue must be set in config file")

    runner = None
    try:
        runner = MailinRunner2(root, zodb_uri, zodb_path, queue)
        runner()
        transaction.commit()

        p_jar = getattr(root, '_p_jar', None)
        if p_jar is not None:
            # Attempt to fix memory leak
            p_jar.db().cacheMinimize()

    except:
        transaction.abort()
        raise

    finally:
        closer()
        if runner is not None:
            runner.close()
Beispiel #18
0
def _get_mailto(context, peopledir):
    mailinglist = context.get('mailinglist')
    if mailinglist is not None:
        system_email_domain = get_setting(context, "system_email_domain")
        system_list_subdomain = get_setting(context, "system_list_subdomain",
                                            system_email_domain)
        return 'mailto:%s@%s' % (mailinglist.short_address,
                                 system_list_subdomain)
Beispiel #19
0
 def __init__(self, context, request, page_title=None):
     super(AdminTemplateAPI, self).__init__(context, request, page_title)
     syslog_view = get_setting(context, 'syslog_view', None)
     self.syslog_view_enabled = syslog_view != None
     self.has_logs = not not get_setting(context, 'logs_view', None)
     self.error_monitoring = not not get_setting(
         context, 'error_monitor_subsystems', None
     )
Beispiel #20
0
def _get_mailto(context, peopledir):
    mailinglist = context.get("mailinglist")
    if mailinglist is not None:
        pd_path = resource_path_tuple(peopledir)
        report_path = resource_path_tuple(context)
        mail_name = "+".join(report_path[len(pd_path) :])
        system_email_domain = get_setting(context, "system_email_domain")
        system_list_subdomain = get_setting(context, "system_list_subdomain", system_email_domain)
        return "mailto:%s@%s" % (mailinglist.short_address, system_list_subdomain)
Beispiel #21
0
 def quarantine_message(self, message):
     mailer = getUtility(IMailDelivery)
     from_email = get_setting(self.root, 'postoffice.bounce_from_email')
     if from_email is None:
         from_email = get_setting(self.root, 'admin_email')
     error = traceback.format_exc()
     self.queue.quarantine(message, error, wrap_send(mailer.send),
                           from_email)
     return error
Beispiel #22
0
    def __call__(self):
        context, request = self.context, self.request
        api = AdminTemplateAPI(context, request, "Admin UI: Send Email")
        admin_email = get_setting(context, "admin_email")
        system_name = get_setting(context, "system_name")
        profiles = find_profiles(context)
        admin = profiles[authenticated_userid(request)]
        from_emails = [
            ("self", "%s <%s>" % (admin.title, admin.email)),
            ("admin", "%s Administrator <%s>" % (system_name, admin_email)),
        ]

        if "send_email" in request.params:
            mailer = getUtility(IMailDelivery)
            group = request.params["to_group"]
            users = find_users(context)
            search = ICatalogSearch(context)
            count, docids, resolver = search(interfaces=[IProfile])
            n = 0
            for docid in docids:
                profile = resolver(docid)
                if getattr(profile, "security_state", None) == "inactive":
                    continue
                userid = profile.__name__
                if group and not users.member_of_group(userid, group):
                    continue

                message = Message()
                if request.params["from_email"] == "self":
                    message["From"] = from_emails[0][1]
                    message_from = admin.email
                else:
                    message["From"] = from_emails[1][1]
                    message_from = admin_email
                message["To"] = "%s <%s>" % (profile.title, profile.email)
                message["Subject"] = request.params["subject"]
                body = u"<html><body>%s</body></html>" % (request.params["text"])
                message.set_payload(body.encode("UTF-8"), "UTF-8")
                message.set_type("text/html")

                mailer.send([profile.email], message)
                n += 1

            status_message = "Sent message to %d users." % n
            if has_permission(ADMINISTER, context, request):
                redirect_to = model_url(context, request, "admin.html", query=dict(status_message=status_message))
            else:
                redirect_to = model_url(
                    find_communities(context),
                    request,
                    "all_communities.html",
                    query=dict(status_message=status_message),
                )

            return HTTPFound(location=redirect_to)

        return dict(api=api, menu=_menu_macro(), to_groups=self.to_groups, from_emails=from_emails)
Beispiel #23
0
def change_password_view(context, request):
    min_pw_length = get_setting(context, 'min_pw_length')
    form = ChangePasswordForm(min_pw_length=min_pw_length)
    if 'form.cancel' in request.POST:
        return HTTPFound(location=model_url(context, request))

    if 'form.submitted' in request.POST:
        try:
            converted = form.validate(request.POST)
            users = find_users(context)
            userid = context.__name__
            user = users.get_by_id(userid)

            # check the old password
            # XXX: repoze.who.plugins.zodb.interfaces.IUsers
            # really should have a check_password(id, password)
            # method.  We shouldn't have to use get_sha_password
            # directly.
            enc = get_sha_password(converted['old_password'])
            if enc != user['password']:
                raise CustomInvalid({'old_password': '******'})

            users.change_password(userid, converted['password'])

            # send email
            system_name = get_setting(context, 'system_name', 'KARL')
            mail = karl.mail.Message()
            admin_email = get_setting(context, 'admin_email')
            mail["From"] = "%s Administrator <%s>" % (system_name, admin_email)
            mail["To"] = "%s <%s>" % (context.title, context.email)
            mail["Subject"] = "%s Password Change Notification" % system_name
            system_name = get_setting(context, 'system_name', 'KARL')
            body = render_template(
                "templates/email_change_password.pt",
                login=user['login'],
                password=converted['password'],
                system_name=system_name,
            )

            if isinstance(body, unicode):
                body = body.encode("UTF-8")

            mail.set_payload(body, "UTF-8")
            mail.set_type("text/html")

            recipients = [context.email]
            mailer = getUtility(IMailDelivery)
            mailer.send(admin_email, recipients, mail)

            path = model_url(context, request)
            msg = '?status_message=Password%20changed'
            return HTTPFound(location=path+msg)

        except Invalid, e:
            fielderrors = e.error_dict
            fill_values = form.convert(request.POST)
Beispiel #24
0
    def __call__(self):
        context, request = self.context, self.request
        api = AdminTemplateAPI(context, request, 'Admin UI: Send Email')
        admin_email = get_setting(context, 'admin_email')
        system_name = get_setting(context, 'system_name')
        profiles = find_profiles(context)
        admin = profiles[authenticated_userid(request)]
        from_emails = [
            ('self', '%s <%s>' % (admin.title, admin.email)),
            ('admin', '%s Administrator <%s>' % (system_name, admin_email)),
        ]

        if 'send_email' in request.params:
            mailer = getUtility(IMailDelivery)
            group = request.params['to_group']
            users = find_users(context)
            search = ICatalogSearch(context)
            count, docids, resolver = search(interfaces=[IProfile])
            n = 0
            for docid in docids:
                profile = resolver(docid)
                userid = profile.__name__
                if group and not users.member_of_group(userid, group):
                    continue

                message = Message()
                if request.params['from_email'] == 'self':
                    message['From'] = from_emails[0][1]
                    message_from = admin.email
                else:
                    message['From'] = from_emails[1][1]
                    message_from = admin_email
                message['To'] = '%s <%s>' % (profile.title, profile.email)
                message['Subject'] = request.params['subject']
                body = u'<html><body>%s</body></html>' % (
                    request.params['text']
                )
                message.set_payload(body.encode('UTF-8'), 'UTF-8')
                message.set_type('text/html')

                mailer.send(message_from, [profile.email], message)
                n += 1

            status_message = "Sent message to %d users." % n
            redirect_to = model_url(context, request, 'admin.html',
                                    query=dict(status_message=status_message))
            return HTTPFound(location=redirect_to)

        return render_template_to_response(
            'templates/admin/email_users.pt',
            api=api,
            menu=_menu_macro(),
            to_groups = self.to_groups,
            from_emails=from_emails,
        )
Beispiel #25
0
def _get_mailto(context, peopledir):
    mailinglist = context.get('mailinglist')
    if mailinglist is not None:
        pd_path = model_path_tuple(peopledir)
        report_path = model_path_tuple(context)
        mail_name = '+'.join(report_path[len(pd_path):])
        system_email_domain = get_setting(context, "system_email_domain")
        system_list_subdomain = get_setting(context, "system_list_subdomain",
                                            system_email_domain)
        return 'mailto:%s@%s' % (mailinglist.short_address,
                                 system_list_subdomain)
Beispiel #26
0
def show_mailin_trace_blog(context, request):
    path = get_setting(context, 'mailin_trace_file')
    formatted_timestamp = None
    if os.path.exists(path):
        timestamp = os.path.getmtime(path)
        timestamp = datetime.datetime.fromtimestamp(timestamp)
        formatted_timestamp = timestamp.ctime()
    return dict(
        api=TemplateAPI(context, request),
        system_email_domain=get_setting(context, 'system_email_domain'),
        timestamp=formatted_timestamp,
    )
Beispiel #27
0
def _get_common_email_info(community, community_href):
    info = {}
    info['system_name'] = get_setting(community, 'system_name', 'KARL')
    info['system_email_domain'] = get_setting(community,
                                              'system_email_domain')
    info['from_name'] = '%s invitation' % info['system_name']
    info['from_email'] = 'invitation@%s' % info['system_email_domain']
    info['c_title'] = community.title
    info['c_description'] = community.description
    info['c_href'] = community_href
    info['mfrom'] = '%s <%s>' % (info['from_name'], info['from_email'])

    return info
Beispiel #28
0
    def message(self):
        if self._message is not None:
            return self._message

        community = self._community
        request = self.request
        profile = self.profile
        model = self._model

        community_href = model_url(community, request)
        model_href = model_url(model, request)
        manage_preferences_href = model_url(profile, request)
        system_name = get_setting(self.context, "system_name", "KARL")
        system_email_domain = get_setting(self.context, "system_email_domain")

        body_template = get_template(self._template)
        from_name = "%s | %s" % (self.creator.title, system_name)
        msg = Message()
        msg["From"] = "%s <%s>" % (from_name, self.mfrom)
        msg["To"] = "%s <%s>" % (community.title, profile.email)
        msg["Subject"] = self._subject
        body = body_template(
            context=self.context,
            community=community,
            community_href=community_href,
            model=model,
            model_href=model_href,
            manage_preferences_href=manage_preferences_href,
            profile=profile,
            creator=self.creator,
            content_type=self._content_type_name,
            digest=self.digest,
            alert=self,
        )

        if self.digest:
            # Only interested in body for digest
            html = document_fromstring(body)
            body_element = html.cssselect('body')[0]
            span = etree.Element("span", nsmap=body_element.nsmap)
            span[:] = body_element[:] # Copy all body elements to an empty span
            body = etree.tostring(span, pretty_print=True)

        if isinstance(body, unicode):
            body = body.encode('utf-8')

        msg.set_payload(body, 'utf-8')
        msg.set_type("text/html")
        self._message = msg
        return msg
Beispiel #29
0
    def handle_submit(self, converted):
        context = self.context
        request = self.request
        system_name = get_setting(context, 'system_name', 'KARL')
        address = converted['email']
        if address:
            address = address.lower()

        search = getAdapter(context, ICatalogSearch)
        count, docids, resolver = search(
            interfaces=[IProfile], email=[address])

        users = find_users(context)
        for docid in docids:
            profile = resolver(docid)
            if profile is None:
                continue
            userid = profile.__name__
            user = users.get_by_id(userid)
            if user is None:
                continue
            # found the profile and user
            break
        else:
            raise ValidationError(**{"email":
                "%s has no account with the email address: %s" %
                (system_name, address)})

        request_password_reset(user, profile, request)

        url = resource_url(context, request, 'reset_sent.html') + (
            '?email=%s' % urllib.quote_plus(address))
        return HTTPFound(location=url)
Beispiel #30
0
def show_profiles_view(context, request):
    system_name = get_setting(context, 'system_name', 'KARL')
    page_title = '%s Profiles' % system_name
    api = TemplateAPI(context, request, page_title)

    # Grab the data for the two listings, main communities and portlet
    search = ICatalogSearch(context)

    query = dict(sort_index='title', interfaces=[IProfile], limit=5)

    titlestartswith = request.params.get('titlestartswith')
    if titlestartswith:
        query['titlestartswith'] = (titlestartswith, titlestartswith)

    num, docids, resolver = search(**query)

    profiles = []
    for docid in docids:
        model = resolver(docid)
        if model is None:
            continue
        profiles.append(model)

    mgr = ILetterManager(context)
    letter_info = mgr.get_info(request)

    return render_to_response(
        'templates/profiles.pt',
        dict(api=api,
             profiles=profiles,
             letters=letter_info),
        request=request,
        )
Beispiel #31
0
def showtag_view(context, request, community=None, user=None, crumb_title=None):
    """Show a page for a particular tag, optionally refined by context."""

    page_title = 'Show Tag'
    api = TemplateAPI(context, request, page_title)

    # The tag screens (cloud, listing, and this view) each have a
    # "jump box" that allows you to quickly jump to another tag.  All
    # three will point here at /showtag?tag=tag1.  We detect this mode
    # and do a redirect.
    jump_tag = request.params.get('jumptag', False)
    if jump_tag:
        location = resource_url(context, request, request.view_name, jump_tag)
        return HTTPFound(location=location)

    # Our strategy is to support tag URLs that are like this:
    #     /showtag/tag1
    # ...instead of:
    #     /tagpage.html?tag=tag1
    # However, our tag data isn't traversable (it is site.tags and not
    # site['tags'].  So we have a view at /showtag that picks apart
    # the next hop in the URL.
    tag = request.subpath
    if not tag:
        # The user didn't provide anything beyond /showtag in the URL
        tag = None
        entries = related = []
    else:
        # Ahh, the good part.  Let's find some tag results and unpack
        # data into what the ZPT needs.
        tag = tag[0]

        catalog = find_catalog(context)
        dm = catalog.document_map
        tags = find_tags(context)

        if community is None and user is None:
            # Only show related tags portlet in global view
            related = tags.getRelatedTags(tag, user=user, community=community)
        else:
            related = []

        entries = []
        if user:
            users = (user,)
        else:
            users = None
        for docid in tags.getItems(tags=(tag,), users=users,
                                   community=community,
                                   ):
            # XXX Need to wire in batching
            address = dm.address_for_docid(int(docid))
            if address is None:
                raise KeyError(docid)
            resource = find_resource(context, address)

            # Skip documents which aren't viewable by authenticated user
            if not has_permission('view', resource, request):
                continue

            # Do a secondary query for each result to find the
            # per-user info
            users = tags.getUsers(tags=(tag,), items=(docid,),
                                  community=community)
            if len(users) == 1:
                tuh = '1 person'
            else:
                tuh = '%s people' % len(users)

            tuhref = resource_url(context, request, 'tagusers.html',
                                  query={'tag': tag, 'docid': docid})
            entry = {
                'title': resource.title,
                'description': getattr(resource, 'description', ''),
                'href': resource_url(resource, request),
                'type': get_content_type_name(resource),
                'tagusers_href': tuhref,
                'tagusers_count': tuh,
                }
            entries.append(entry)

    args = dict(
        api=api,
        tag=tag,
        entries=entries,
        related=related,
    )

    if crumb_title:
        # XXX Would context.title be a bit nicer for displaying to user?
        system_name = get_setting(context, 'title', 'KARL')
        args['crumbs'] = '%s / %s / %s' % (
            system_name, crumb_title, context.__name__)

    return dict(**args)
Beispiel #32
0
 def ts_config(self):
     ts_config = self._v_ts_config
     if ts_config is None:
         ts_config = get_setting(self, 'pgtextindex.ts_config', 'english')
         self._v_ts_config = ts_config
     return ts_config
Beispiel #33
0
 def enabled(self):
     return get_setting(self.context, 'two_factor_enabled', False)
Beispiel #34
0
    def send_digests(self, context, period='daily'):
        PERIODS = {
            'daily': [IProfile.ALERT_DAILY_DIGEST],
            'weekly':
            [IProfile.ALERT_DAILY_DIGEST, IProfile.ALERT_WEEKLY_DIGEST],
            'biweekly': [
                IProfile.ALERT_DAILY_DIGEST, IProfile.ALERT_WEEKLY_DIGEST,
                IProfile.ALERT_BIWEEKLY_DIGEST
            ],
        }
        periods = PERIODS[period]
        mailer = getUtility(IMailDelivery)

        system_name = get_setting(context, "title", "KARL")
        sent_from = get_setting(context, "admin_email")
        from_addr = "%s <%s>" % (system_name, sent_from)
        subject = "[%s] Your alerts digest" % system_name

        template = get_renderer("email_digest.pt").implementation()
        for profile in find_profiles(context).values():
            if not list(profile._pending_alerts):
                continue

            # Perform each in its own transaction, so a problem with one
            # user's email doesn't block all others
            transaction.manager.begin()
            alerts = profile._pending_alerts.consume()
            try:
                pending = []
                skipped = []
                for alert in alerts:
                    community = alert.get('community')
                    if community is not None:
                        pref = profile.get_alerts_preference(community)
                        if pref in periods:
                            pending.append(alert)
                        else:
                            skipped.append(alert)
                    else:  # XXX belt-and-suspenders:  send it now
                        pending.append(alert)

                if len(pending) > 0:

                    attachments = []
                    for alert in pending:
                        attachments += alert['attachments']

                    msg = MIMEMultipart() if attachments else Message()
                    msg["From"] = from_addr
                    msg["To"] = "%s <%s>" % (profile.title, profile.email)
                    msg["Subject"] = subject

                    body_text = template.render(
                        system_name=system_name,
                        alerts=pending,
                    )

                    if isinstance(body_text, unicode):
                        body_text = body_text.encode("UTF-8")

                    if attachments:
                        body = MIMEText(body_text, 'html', 'utf-8')
                        msg.attach(body)
                    else:
                        msg.set_payload(body_text, "UTF-8")
                        msg.set_type("text/html")

                    for attachment in attachments:
                        msg.attach(attachment)

                    mailer.send([profile.email], msg)

                for alert in skipped:
                    profile._pending_alerts.append(alert)

                transaction.manager.commit()

            except Exception:
                # Log error and continue
                log.error("Error sending digest to %s <%s>" %
                          (profile.title, profile.email))

                b = StringIO()
                traceback.print_exc(file=b)
                log.error(b.getvalue())
                b.close()

                transaction.manager.abort()
Beispiel #35
0
def min_pw_length():
    global _MIN_PW_LENGTH
    if _MIN_PW_LENGTH is None:
        _MIN_PW_LENGTH = get_setting(None, 'min_pw_length', 8)
    return _MIN_PW_LENGTH
Beispiel #36
0
from karl.views import peopledirectory
from karl.views.api import TemplateAPI
from karl.views.forms import validators as karlvalidators
from karl.views.forms import widgets as karlwidgets
from karl.views.forms.widgets import VerticalRadioChoice
from karl.views.people import AdminEditProfileFormController as AdminFCBase
from karl.views.people import EditProfileFormController
from karl.views.people import groups_field
from karl.views.people import login_field
from karl.views.people import show_profile_view
from karl.views.peopledirectory import get_actions
from karl.views.peopledirectory import get_admin_actions

from osi.utilities.former_staff import make_non_staff

min_pw_length = get_setting(None, 'min_pw_length', 8)


class AdminEditProfileFormController(AdminFCBase):
    def __init__(self, context, request):
        super(AdminEditProfileFormController, self).__init__(context, request)
        users = self.users
        self.is_staff = users.member_of_group(self.userid, 'group.KarlStaff')
        self.is_own_profile = context.__name__ == authenticated_userid(request)

    def __call__(self):
        kw = super(AdminEditProfileFormController, self).__call__()
        kw['is_own_profile'] = self.is_own_profile
        kw['is_staff'] = self.is_staff
        return kw
Beispiel #37
0
    def __call__(self):
        context, request = self.context, self.request
        api = AdminTemplateAPI(context, request, 'Admin UI: Send Email')
        admin_email = get_setting(context, 'admin_email')
        system_name = get_setting(context, 'system_name')
        profiles = find_profiles(context)
        admin = profiles[authenticated_userid(request)]
        from_emails = [
            ('self', '%s <%s>' % (admin.title, admin.email)),
            ('admin', '%s Administrator <%s>' % (system_name, admin_email)),
        ]

        if 'send_email' in request.params:
            mailer = getUtility(IMailDelivery)
            group = request.params['to_group']
            users = find_users(context)
            search = ICatalogSearch(context)
            count, docids, resolver = search(interfaces=[IProfile])
            n = 0
            for docid in docids:
                profile = resolver(docid)
                if getattr(profile, 'security_state', None) == 'inactive':
                    continue
                userid = profile.__name__
                if group and not users.member_of_group(userid, group):
                    continue

                message = Message()
                if request.params['from_email'] == 'self':
                    message['From'] = from_emails[0][1]
                    message_from = admin.email
                else:
                    message['From'] = from_emails[1][1]
                    message_from = admin_email
                message['To'] = '%s <%s>' % (profile.title, profile.email)
                message['Subject'] = request.params['subject']
                body = u'<html><body>%s</body></html>' % (
                    request.params['text'])
                message.set_payload(body.encode('UTF-8'), 'UTF-8')
                message.set_type('text/html')

                mailer.send([profile.email], message)
                n += 1

            status_message = "Sent message to %d users." % n
            if has_permission(ADMINISTER, context, request):
                redirect_to = resource_url(
                    context,
                    request,
                    'admin.html',
                    query=dict(status_message=status_message))
            else:
                redirect_to = resource_url(
                    find_communities(context),
                    request,
                    'all_communities.html',
                    query=dict(status_message=status_message))

            return HTTPFound(location=redirect_to)

        return dict(
            api=api,
            menu=_menu_macro(),
            to_groups=self.to_groups,
            from_emails=from_emails,
        )
Beispiel #38
0
    classes = []
    for name, title, description, urlname in _VIEWS:
        classes.append({
            'name': name,
            'title': title,
            'description': description,
            'href': urlname,
            'url': request.resource_url(context, urlname),
            'selected': name == view_cookie,
        })

    actions = []
    if has_permission('create', context, request):
        actions.append(('Add Community', 'add_community.html'))

    system_name = get_setting(context, 'title', 'KARL')
    page_title = '%s%s Communities' % (prefix, system_name)

    my_communities = get_my_communities(context, request)
    preferred_communities = get_preferred_communities(context, request)

    return {
        'communities': communities,
        'batch_info': batch_info,
        'letters': letter_info,
        'community_tabs': classes,
        'actions': actions,
        'my_communities': my_communities,
        'preferred_communities': preferred_communities,
        'api': TemplateAPI(context, request, page_title),
        'profile': None,
Beispiel #39
0
 def send_text_code(self, profile):
     msg = "%s authorization code: %s" % (get_setting(
         self.context, 'title'), profile.current_auth_code)
     self.send_text_to_number(profile.two_factor_phone, msg)
Beispiel #40
0
    def message(self):
        if self._message is not None:
            return self._message

        community = self._community
        request = self.request
        profile = self.profile
        model = self._model

        community_href = resource_url(community, request)
        model_href = resource_url(model, request)
        manage_preferences_href = resource_url(
            profile, request) + '/manage_communities.html'  # noqa
        system_name = get_setting(self.context, "title", "KARL")

        attachments, attachment_links, attachment_hrefs = self.attachments

        from_name = "%s | %s" % (self.creator.title, system_name)
        msg = MIMEMultipart() if attachments else Message()
        msg["From"] = '"%s" <%s>' % (from_name, self.mfrom)
        msg["To"] = '"%s" <%s>' % (community.title, profile.email)
        msg["Subject"] = self._subject
        msg["Precedence"] = 'bulk'
        body_text = self.template(
            context=self.context,
            community=community,
            community_href=community_href,
            model=model,
            model_href=model_href,
            manage_preferences_href=manage_preferences_href,
            attachments=attachment_links,
            attachment_hrefs=attachment_hrefs,
            profile=profile,
            profiles=self.profiles,
            creator=self.creator,
            content_type=self._content_type_name,
            digest=self.digest,
            alert=self,
            resource_url=resource_url,
            request=request,
            reply_enabled=self.reply_enabled)

        if self.digest:
            # Only interested in body for digest
            html = document_fromstring(body_text)
            body_element = html.cssselect('body')[0]
            span = etree.Element("span", nsmap=body_element.nsmap)
            span[:] = body_element[:]  # Copy all body elements to an empty span
            body_text = etree.tostring(span, pretty_print=True)

        if isinstance(body_text, unicode):
            body_text = body_text.encode('utf-8')

        if attachments:
            body = MIMEText(body_text, 'html', 'utf-8')
            msg.attach(body)
            for attachment in attachments:
                msg.attach(attachment)
        else:
            msg.set_payload(body_text, 'utf-8')
            msg.set_type("text/html")

        self._message = msg
        return msg
Beispiel #41
0
def show_blog_view(context, request):
    if 'year' in request.GET and 'month' in request.GET:
        year = int(request.GET['year'])
        month = int(request.GET['month'])
        dt = datetime.date(year, month, 1).strftime('%B %Y')
        page_title = 'Blog: %s' % dt
        where_month = ("and state->>'created' like '%.4d-%.2d%%%%'" %
                       (year, month))
    else:
        page_title = 'Blog'
        where_month = ''

    from newt.db import search
    community = find_community(context)
    community_cond = qbe.sql(context._p_jar, dict(community=community))
    results = search.search(
        context._p_jar,
        """
        select * from newt natural join karlex where
        class_name = 'karl.content.models.blog.BlogEntry'
        and """ + community_cond + """
        and newt_can_view(state, %s)
        """ + where_month + """
        order by state->>'created' desc
        """,
        effective_principals(request),
    )

    api = TemplateAPI(context, request, page_title)

    actions = []
    if has_permission('create', context, request):
        actions.append(('Add Blog Entry',
                        request.resource_url(context, 'add_blogentry.html')), )

    batch = get_simple_batch(results, context, request)

    # Unpack into data for the template
    entries = []
    profiles = find_profiles(context)
    karldates = getUtility(IKarlDates)
    fmt0 = '<a href="%s#addcomment">Add a Comment</a>'
    fmt1 = '<a href="%s#comments">1 Comment</a>'
    fmt2 = '<a href="%s#comments">%i Comments</a>'

    for entry in batch['entries']:
        profile = profiles[entry.creator]
        byline_info = getMultiAdapter((entry, request), IBylineInfo)
        entry_url = resource_url(entry, request)

        # Get information about comments on this entry to display in
        # the last line of the entry
        comment_count = len(entry['comments'])
        if comment_count == 0:
            comments_blurb = fmt0 % entry_url
        elif comment_count == 1:
            comments_blurb = fmt1 % entry_url
        else:
            comments_blurb = fmt2 % (entry_url, comment_count)
        info = {
            'title': entry.title,
            'href': resource_url(entry, request),
            'description': entry.description,
            'creator_title': profile.title,
            'creator_href': entry_url,
            'long_date': karldates(entry.created, 'longform'),
            'byline_info': byline_info,
            'comments_blurb': comments_blurb,
        }
        entries.append(info)

    feed_url = "%satom.xml" % resource_url(context, request)
    workflow = get_workflow(IBlogEntry, 'security', context)
    if workflow is None:
        security_states = []
    else:
        security_states = get_security_states(workflow, None, request)

    system_email_domain = get_setting(context, "system_email_domain")
    return dict(
        api=api,
        actions=actions,
        entries=entries,
        system_email_domain=system_email_domain,
        feed_url=feed_url,
        batch_info=batch,
        security_states=security_states,
    )
Beispiel #42
0
 def table(self):
     table = self._v_table
     if table is None:
         table = get_setting(self, 'pgtextindex.table', 'pgtextindex')
         self._v_table = table
     return table
Beispiel #43
0
def check_upload_size(context, obj, field_name):
    max_size = int(get_setting(context, 'upload_limit', 0))
    if max_size and obj.size > max_size:
        msg = 'File size exceeds upload limit of %d.' % max_size
        transaction.get().doom()
        raise Invalid({field_name: msg})
Beispiel #44
0
def make_non_staff(profile, inform_moderators=True):
    """
    When a user is removed from the KarlStaff role, their community
    memberships are removed. Moderators of their communities are optionally
    informed via email.
    """
    id = profile.__name__
    moderators = {}
    users = find_users(profile)
    profile.categories = {}
    for group in list(users.get_by_id(id)['groups']):
        if group.startswith('group.community'):
            # Remove user from group
            users.remove_user_from_group(id, group)
            if not inform_moderators:
                continue

            # Keep track of moderators we need to email making sure
            # each moderator is emailed only once and each community is
            # only mentioned once in any given email.
            community_name = group.split(':')[1]
            moderators_group = ('group.community:%s:moderators' %
                                community_name)
            for moderator in users.users_in_group(moderators_group):
                if moderator == id:
                    continue  # Really should only come up in unittests
                if moderator not in moderators:
                    moderators[moderator] = set()
                moderators[moderator].add(community_name)

    if not inform_moderators:
        return

    communities = find_communities(profile)
    profiles = profile.__parent__
    mailer = getUtility(IMailDelivery)
    for moderator_id in moderators:
        moderator = profiles[moderator_id]
        msg = Message()
        msg['From'] = get_setting(profile, 'admin_email')
        msg['To'] = '%s <%s>' % (moderator.title, moderator.email)
        msg['Subject'] = 'Notice that %s is now former staff' % profile.title
        former_communities = sorted(
            [communities[c] for c in moderators[moderator_id]],
            key=lambda x: x.title)
        app_url = get_setting(profile, 'offline_app_url')
        communities_info = [
            dict(title=c.title,
                 unremove_url='%s%s?user_id=%s' %
                 (app_url, model_path(c, 'members', 'add_existing.html'), id))
            for c in former_communities
        ]
        body = render(
            'templates/email_notify_former_staff.pt',
            dict(name=profile.title, communities=communities_info),
        )
        if isinstance(body, unicode):
            body = body.encode('UTF-8')
        msg.set_payload(body, 'UTF-8')
        msg.set_type('text/html')

        mailer.send([msg['To']], msg)
Beispiel #45
0
 def phone_factor_enabled(self):
     return bool(
         get_setting(self.context, 'two_factor_plivo_auth_id', False)
         and get_setting(self.context, 'two_factor_plivo_auth_token', False)
         and get_setting(self.context, 'two_factor_src_phone_number',
                         False))
Beispiel #46
0
 def max_ranked(self):
     max_ranked = self._v_max_ranked
     if max_ranked is None:
         max_ranked = int(get_setting(self, 'pgtextindex.max_ranked', 6000))
         self._v_max_ranked = max_ranked
     return max_ranked
Beispiel #47
0
Datei: blog.py Projekt: zagy/karl
def show_blog_view(context, request):
    # add portlets to template
    layout = request.layout_manager.layout
    layout.add_portlet('blog_archive')

    if 'year' in request.GET and 'month' in request.GET:
        year = int(request.GET['year'])
        month = int(request.GET['month'])

        def filter_func(name, item):
            created = item.created
            return created.year == year and created.month == month

        dt = datetime.date(year, month, 1).strftime('%B %Y')
        page_title = 'Blog: %s' % dt
    else:
        filter_func = None
        page_title = 'Blog'

    api = TemplateAPI(context, request, page_title)

    actions = []
    if has_permission('create', context, request):
        actions.append(('Add Blog Entry',
                        request.resource_url(context, 'add_blogentry.html')), )

    batch = get_container_batch(context,
                                request,
                                filter_func=filter_func,
                                interfaces=[IBlogEntry],
                                sort_index='creation_date',
                                reverse=True)

    # Unpack into data for the template
    entries = []
    profiles = find_profiles(context)
    karldates = getUtility(IKarlDates)
    fmt0 = '<a href="%s#addcomment">Add a Comment</a>'
    fmt1 = '<a href="%s#comments">1 Comment</a>'
    fmt2 = '<a href="%s#comments">%i Comments</a>'

    for entry in batch['entries']:
        profile = profiles[entry.creator]
        byline_info = getMultiAdapter((entry, request), IBylineInfo)
        entry_url = resource_url(entry, request)

        # Get information about comments on this entry to display in
        # the last line of the entry
        comment_count = len(entry['comments'])
        if comment_count == 0:
            comments_blurb = fmt0 % entry_url
        elif comment_count == 1:
            comments_blurb = fmt1 % entry_url
        else:
            comments_blurb = fmt2 % (entry_url, comment_count)
        info = {
            'title': entry.title,
            'href': resource_url(entry, request),
            'description': entry.description,
            'creator_title': profile.title,
            'creator_href': entry_url,
            'long_date': karldates(entry.created, 'longform'),
            'byline_info': byline_info,
            'comments_blurb': comments_blurb,
        }
        entries.append(info)

    feed_url = "%satom.xml" % resource_url(context, request)
    workflow = get_workflow(IBlogEntry, 'security', context)
    if workflow is None:
        security_states = []
    else:
        security_states = get_security_states(workflow, None, request)

    system_email_domain = get_setting(context, "system_email_domain")
    community = find_community(context)
    mailin_addr = '%s@%s' % (community.__name__, system_email_domain)
    return dict(
        api=api,
        actions=actions,
        entries=entries,
        system_email_domain=system_email_domain,  # Deprecated UX1
        feed_url=feed_url,
        batch_info=batch,
        security_states=security_states,
        mailin_addr=mailin_addr,  # UX2
    )
Beispiel #48
0
import logging

import user_agents

from pyramid.security import authenticated_userid
from pyramid.security import forget

from karl.utils import find_profiles
from karl.utils import get_setting

logger = logging.getLogger('request_logger')
var = get_setting(None, 'var')
if var is not None:
    filehandler = logging.FileHandler('%s/log/tracker.log' % var)
    filehandler.setLevel(logging.INFO)
    formatter = logging.Formatter('%(asctime)s - %(message)s')
    filehandler.setFormatter(formatter)
    logger.addHandler(filehandler)


def request_logger(event):
    request = event.request
    if not (request.path.startswith('/static')
            or request.path.startswith('/newest_feed_items.json')):
        userid = authenticated_userid(request),
        if userid is not None:
            userid = userid[0]
        email = ''
        profile = None
        try:
            profiles = find_profiles(request.context)
Beispiel #49
0
def login_view(context, request):
    settings = request.registry.settings
    request.layout_manager.use_layout('anonymous')
    came_from = _fixup_came_from(request, request.POST.get('came_from'))

    if request.params.get('form.submitted', None) is not None:

        challenge_qs = {'came_from': came_from}
        # identify
        login = request.POST.get('login')
        password = request.POST.get('password')
        if login is None or password is None:
            return HTTPFound(location='%s/login.html' %
                             request.application_url)
        max_age = request.POST.get('max_age')
        if max_age is not None:
            max_age = int(max_age)

        # authenticate
        userid = None
        reason = 'Bad username or password'
        users = find_users(context)
        for authenticate in (password_authenticator,
                             impersonate_authenticator):
            userid = authenticate(users, login, password)
            if userid:
                break

        # if not successful, try again
        if not userid:
            challenge_qs['reason'] = reason
            return HTTPFound(
                location='%s/login.html?%s' %
                (request.application_url, urlencode(challenge_qs, doseq=True)))

        # else, remember
        return remember_login(context, request, userid, max_age, came_from)

    # Log in user seamlessly with kerberos if enabled
    try_kerberos = request.GET.get('try_kerberos', None)
    if try_kerberos:
        try_kerberos = asbool(try_kerberos)
    else:
        try_kerberos = asbool(get_setting(context, 'kerberos', 'False'))
    if try_kerberos:
        from karl.security.kerberos_auth import get_kerberos_userid
        userid = get_kerberos_userid(request)
        if userid:
            return remember_login(context, request, userid, None, came_from)

        # Break infinite loop if kerberos authorization fails
        if request.authorization and request.authorization[0] == 'Negotiate':
            try_kerberos = False

    page_title = 'Login to %s' % settings.get(
        'system_name', 'KARL')  # Per #366377, don't say what screen
    layout = request.layout_manager.layout
    layout.page_title = page_title
    api = TemplateAPI(context, request, page_title)

    came_from = _fixup_came_from(request,
                                 request.params.get('came_from', request.url))
    request.session['came_from'] = came_from

    sso_providers = []
    sso = settings.get('sso')
    if sso:
        # importing here rather than in global scope allows to only require
        # velruse be installed for systems using it.
        from velruse import login_url
        for name in sso.split():
            provider = settings.get('sso.%s.provider' % name)
            title = settings.get('sso.%s.title' % name)
            sso_providers.append({
                'title': title,
                'name': name,
                'url': login_url(request, provider)
            })

    api.status_message = request.params.get('reason', None)
    response = render_to_response('templates/login.pt',
                                  dict(api=api,
                                       came_from=came_from,
                                       nothing='',
                                       try_kerberos=try_kerberos,
                                       sso_providers=sso_providers,
                                       app_url=request.application_url),
                                  request=request)
    forget_headers = forget(request)
    response.headers.extend(forget_headers)
    return response
Beispiel #50
0
    def message(self):
        if self._message is not None:
            return self._message

        community = self._community
        request = self.request
        profile = self.profile
        blogentry = self._blogentry

        community_href = resource_url(community, request)
        blogentry_href = resource_url(blogentry, request)
        manage_preferences_href = resource_url(profile, request)
        system_name = get_setting(self.context, "system_name", "KARL")
        system_email_domain = get_setting(self.context, "system_email_domain")

        reply_to = '"%s" <%s+blog-%s@%s>' % (
            community.title, community.__name__, docid_to_hex(
                blogentry.docid), system_email_domain)

        attachments, attachment_links, attachment_hrefs = self.attachments

        body_template = get_renderer(self._template).implementation()
        from_name = "%s | %s" % (self.creator.title, system_name)
        msg = MIMEMultipart() if attachments else Message()
        msg["From"] = '"%s" <%s>' % (from_name, self.mfrom)
        msg["To"] = '"%s" <%s>' % (profile.title, profile.email)
        msg["Reply-to"] = reply_to
        msg["Subject"] = self._subject
        msg["Precedence"] = 'bulk'
        body_text = body_template(
            context=self.context,
            community=community,
            community_href=community_href,
            blogentry=blogentry,
            blogentry_href=blogentry_href,
            attachments=attachment_links,
            attachment_hrefs=attachment_hrefs,
            manage_preferences_href=manage_preferences_href,
            profile=profile,
            profiles=self.profiles,
            creator=self.creator,
            digest=self.digest,
            alert=self,
            history=self._history,
        )

        if self.digest:
            # Only interested in body for digest
            html = document_fromstring(body_text)
            body_element = html.cssselect('body')[0]
            span = etree.Element("span", nsmap=body_element.nsmap)
            span[:] = body_element[:]  # Copy all body elements to an empty span
            body_text = etree.tostring(span, pretty_print=True)

        if isinstance(body_text, unicode):
            body_text = body_text.encode('utf-8')

        if attachments:
            body = MIMEText(body_text, 'html', 'utf-8')
            msg.attach(body)
            for attachment in attachments:
                msg.attach(attachment)
        else:
            msg.set_payload(body_text, 'utf-8')
            msg.set_type("text/html")

        self._message = msg

        return self._message
Beispiel #51
0
 def src_number(self):
     src_number = get_setting(self.context, 'two_factor_src_phone_number')
     return ''.join(n for n in src_number if n in string.digits)
Beispiel #52
0
 def bounce_message(self, message, error):
     mailer = getUtility(IMailDelivery)
     from_email = get_config_setting('postoffice.bounce_from_email')
     if from_email is None:
         from_email = get_setting(self.root, 'admin_email')
     self.queue.bounce(message, wrap_send(mailer.bounce), from_email, error)