def references(self): """Reference export for single record in datatables format. :returns: list List of lists where every item represents a datatables row. A row consists of [reference, num_citations] """ from invenio_search.api import Query out = [] references = self.record.get('references') if references: refs_to_get_from_es = [ ref['recid'] for ref in references if ref.get('recid') ] es_query = ' or '.join( ['control_number:' + str(recid) for recid in refs_to_get_from_es] ) es_query = Query(es_query).search() es_query.body.update({ 'size': 9999 }) refs_from_es = { record['control_number']: record for record in es_query.records() } for reference in references: row = [] if 'recid' in reference: recid = reference['recid'] ref_record = refs_from_es.get(str(recid)) if ref_record: row.append(render_template_to_string( "references.html", record=ref_record, reference=reference )) row.append(ref_record.get('citation_count', '')) out.append(row) continue row.append(render_template_to_string( "references.html", reference=reference)) row.append('') out.append(row) return out
def format_records(records, of='hb', ln=None, **ctx): """Return records using Jinja template.""" from flask import request from invenio_base.i18n import wash_language from .registry import export_formats of = of.lower() jrec = request.values.get('jrec', ctx.get('jrec', 1), type=int) rg = request.values.get('rg', ctx.get('rg', 10), type=int) ln = ln or wash_language(request.values.get('ln', cfg['CFG_SITE_LANG'])) ot = (request.values.get('ot', ctx.get('ot')) or '').split(',') if jrec > records: jrec = rg * (records // rg) + 1 context = dict( of=of, jrec=jrec, rg=rg, ln=ln, ot=ot, facets={}, time=time, records=records, export_formats=export_formats, format_record=format_record, **TEMPLATE_CONTEXT_FUNCTIONS_CACHE.template_context_functions ) context.update(ctx) return render_template_to_string( ['format/records/%s.tpl' % of, 'format/records/%s.tpl' % of[0], 'format/records/%s.tpl' % get_output_format_content_type(of). replace('/', '_')], **context)
def citations(self): """Citation export for single record in datatables format. :returns: list List of lists where every item represents a datatables row. A row consists of [reference, num_citations] """ from invenio_search.api import Query out = [] row = [] recid = self.record['control_number'] es_query = Query('refersto:' + str(recid)).search() es_query.body.update({ 'sort': [{'citation_count': {'order': 'desc'}}], 'size': 9999 }) citations = es_query.records() for citation in citations: row.append(render_template_to_string("citations.html", record=citation)) row.append(citation.get('citation_count', '')) out.append(row) row = [] return out
def format_record(record, of, ln=None, verbose=0, search_pattern=None, xml_record=None, user_info=None, **kwargs): """Format a record in given output format. Return a formatted version of the record in the specified language, search pattern, and with the specified output format. The function will define which format template must be applied. The record to be formatted can be specified with its ID (with 'recID' parameter) or given as XML representation (with 'xml_record' parameter). If 'xml_record' is specified 'recID' is ignored (but should still be given for reference. A dummy recid 0 or -1 could be used). """ ln = ln or cfg['CFG_SITE_LANG'] template = decide_format_template(record, of) out = render_template_to_string( ['format/record/{0}'.format(template), template], recid=record['recid'], record=record, format_record=format_record, **(kwargs or {})) return out
def test_email_text_template(self): """ Test email text template engine. """ from invenio_ext.template import render_template_to_string contexts = { 'ctx1': {'content': 'Content 1'}, 'ctx2': {'content': 'Content 2', 'header': 'Header 2'}, 'ctx3': {'content': 'Content 3', 'footer': 'Footer 3'}, 'ctx4': {'content': 'Content 4', 'header': 'Header 4', 'footer': 'Footer 4'} } msg_content = """Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: %s From: [email protected] To: [email protected]""" for name, ctx in iteritems(contexts): msg = render_template_to_string('mail_text.tpl', **ctx) send_email('*****@*****.**', ['*****@*****.**'], subject=name, **ctx) email = sys.stdout.getvalue() self.assertIn(msg_content % name, email) self.assertIn(msg, email) self.flush_mailbox()
def test_simple_email_header(self): """ Test simple email header. """ from invenio_base.globals import cfg from invenio_ext.template import render_template_to_string msg_content = """Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: Subject From: [email protected] To: %s""" % (cfg['CFG_SITE_ADMIN_EMAIL'], ) msg = render_template_to_string('mail_text.tpl', content='Content') self.flush_mailbox() send_email('*****@*****.**', ['*****@*****.**'], subject='Subject', content='Content') email = self.stream.getvalue() self.assertIn(msg_content, email) self.assertIn(self.ADMIN_MESSAGE, email) self.assertNotIn('Bcc:', email) self.assertIn(msg, email) self.flush_mailbox() send_email('*****@*****.**', '*****@*****.**', subject='Subject', content='Content') email = self.stream.getvalue() self.assertIn(msg_content, email) self.assertIn(self.ADMIN_MESSAGE, email) self.assertNotIn('Bcc:', email) self.assertIn(msg, email) self.flush_mailbox()
def test_email_html_template(self): """ Test email html template engine. """ from invenio_ext.template import render_template_to_string contexts = { 'ctx1': {'html_content': '<b>Content 1</b>'}, 'ctx2': {'html_content': '<b>Content 2</b>', 'html_header': '<h1>Header 2</h1>'}, 'ctx3': {'html_content': '<b>Content 3</b>', 'html_footer': '<i>Footer 3</i>'}, 'ctx4': {'html_content': '<b>Content 4</b>', 'html_header': '<h1>Header 4</h1>', 'html_footer': '<i>Footer 4</i>'} } def strip_html_key(ctx): return dict(map(lambda (k, v): (k[5:], v), iteritems(ctx))) for name, ctx in iteritems(contexts): msg = render_template_to_string('mail_html.tpl', **strip_html_key(ctx)) send_email('*****@*****.**', ['*****@*****.**'], subject=name, content='Content Text', **ctx) email = sys.stdout.getvalue() self.assertIn('Content-Type: multipart/alternative;', email) self.assertIn('Content Text', email) self.assertIn(msg, email) self.flush_mailbox()
def template_context_function(recID): """ Displays next-hit/previous-hit/back-to-search links on the detailed record pages in order to be able to quickly flip between detailed record pages :param recID: detailed record ID :type recID: string :return: html output """ if recID is None: return "" # this variable is set to zero so nothing is displayed if not cfg['CFG_WEBSEARCH_PREV_NEXT_HIT_LIMIT']: return "" # search for a specific record having not done # any search before try: last_query = session['websearch-last-query'] recids = session["websearch-last-query-hits"] except: return "" if recids: return render_template_to_string( 'records/back_to_search_links.html', recID=int(recID), last_query=cfg['CFG_SITE_URL'] + last_query, recids=recids) else: # did not rich the limit CFG_WEBSEARCH_PREV_NEXT_HIT_LIMIT, # so nothing is displayed return ""
def template_context_function(recID): """ Displays next-hit/previous-hit/back-to-search links on the detailed record pages in order to be able to quickly flip between detailed record pages :param recID: detailed record ID :type recID: string :return: html output """ if recID is None: return "" # this variable is set to zero so nothing is displayed if not cfg['CFG_WEBSEARCH_PREV_NEXT_HIT_LIMIT']: return "" # search for a specific record having not done # any search before try: last_query = session['websearch-last-query'] recids = session["websearch-last-query-hits"] except: return "" if recids: return render_template_to_string('records/back_to_search_links.html', recID=int(recID), last_query=cfg['CFG_SITE_URL'] + last_query, recids=recids) else: # did not rich the limit CFG_WEBSEARCH_PREV_NEXT_HIT_LIMIT, # so nothing is displayed return ""
def email_alert(mapper, connection, target): """ Sends email alerts to message recipients. """ from invenio_ext.template import render_template_to_string from invenio_ext.email import send_email, scheduled_send_email m = target is_reminder = m.received_date is not None \ and m.received_date > datetime.now() alert = send_email if is_reminder: alert = lambda *args, **kwargs: scheduled_send_email(*args, other_bibtasklet_arguments=[ m.received_date.strftime(datetext_format)], **kwargs) for u in m.recipients: if isinstance(u.settings, dict) and \ u.settings.get('webmessage_email_alert', True): try: alert( cfg['CFG_WEBCOMMENT_ALERT_ENGINE_EMAIL'], u.email, subject=m.subject, content=render_template_to_string( 'messages/email_alert.html', message=m, user=u)) except: # FIXME tests are not in request context pass
def format_record(record, of, ln=None, verbose=0, search_pattern=None, xml_record=None, user_info=None, **kwargs): """Format a record in given output format. Return a formatted version of the record in the specified language, search pattern, and with the specified output format. The function will define which format template must be applied. The record to be formatted can be specified with its ID (with 'recID' parameter) or given as XML representation (with 'xml_record' parameter). If 'xml_record' is specified 'recID' is ignored (but should still be given for reference. A dummy recid 0 or -1 could be used). """ ln = ln or cfg['CFG_SITE_LANG'] template = decide_format_template(record, of) out = render_template_to_string( ['format/record/{0}'.format(template), template], recid=record['recid'], record=record, format_record=format_record, **(kwargs or {}) ) return out
def format_records(records, of='hb', ln=None, **ctx): """Return records using Jinja template.""" from flask import request from invenio_base.i18n import wash_language from .registry import export_formats of = of.lower() jrec = request.values.get('jrec', ctx.get('jrec', 1), type=int) rg = request.values.get('rg', ctx.get('rg', 10), type=int) ln = ln or wash_language(request.values.get('ln', cfg['CFG_SITE_LANG'])) ot = (request.values.get('ot', ctx.get('ot')) or '').split(',') if jrec > records: jrec = rg * (records // rg) + 1 context = dict( of=of, jrec=jrec, rg=rg, ln=ln, ot=ot, facets={}, time=time, records=records, export_formats=export_formats, format_record=format_record, **TEMPLATE_CONTEXT_FUNCTIONS_CACHE.template_context_functions) context.update(ctx) return render_template_to_string([ 'format/records/%s.tpl' % of, 'format/records/%s.tpl' % of[0], 'format/records/%s.tpl' % get_output_format_content_type(of).replace('/', '_') ], **context)
def __call__(self, field, **kwargs): template = 'deposit/jsonwidget.html' field_id = kwargs.pop('id', field.id) return HTMLString( render_template_to_string(template, field=field, field_id=field_id, **kwargs))
def __call__(self, field, **kwargs): """Render PLUpload widget.""" field_id = kwargs.pop('id', field.id) kwargs['class'] = u'plupload' return HTMLString( render_template_to_string(self.template, field=field, field_id=field_id, **kwargs))
def render_portalbox_bodies(self, templates): """Get a list of rendered portal boxes for this user collection.""" ctx = { 'community': self, } return map( lambda t: render_template_to_string(t, **ctx), templates )
def __str__(self): uid = current_user.get_id() dbquery.update_user_inbox_for_reminders(uid) unread = db.session.query(db.func.count(UserMsgMESSAGE.id_msgMESSAGE)).\ filter(db.and_( UserMsgMESSAGE.id_user_to == uid, UserMsgMESSAGE.status == cfg[ 'CFG_WEBMESSAGE_STATUS_CODE']['NEW'] )).scalar() return render_template_to_string( "messages/menu_item.html", unread=unread)
def widget(self): user = User.query.get(current_user.get_id()) tag_count = user.tags_query.count() record_count = Record.query.join(WtgTAGRecord)\ .join(WtgTAG)\ .filter(WtgTAG.user == user).count() return render_template_to_string('tags/user_settings.html', tag_count=tag_count, record_count=record_count)
def widget(self): user = User.query.get(current_user.get_id()) tag_count = user.tags_query.count() record_count = Record.query.join(WtgTAGRecord)\ .join(WtgTAG)\ .filter(WtgTAG.user == user).count() return render_template_to_string( 'tags/user_settings.html', tag_count=tag_count, record_count=record_count)
def __call__(self, field, **kwargs): template = 'deposit/jsonwidget.html' field_id = kwargs.pop('id', field.id) return HTMLString( render_template_to_string( template, field=field, field_id=field_id, **kwargs ) )
def __call__(self, field, **kwargs): """Render given field using a tempalte. :param field: field that should be rendered. :param template: path to Jinja template. :type template: str """ template = kwargs.pop('template', field.template) field_id = kwargs.pop('id', field.id) return HTMLString( render_template_to_string(template, field=field, field_id=field_id, **kwargs))
def widget(self): uid = current_user.get_id() unread = db.session.query(db.func.count(UserMsgMESSAGE.id_msgMESSAGE)).\ filter(db.and_( UserMsgMESSAGE.id_user_to == uid, UserMsgMESSAGE.status == current_app.config[ 'CFG_WEBMESSAGE_STATUS_CODE']['NEW'] )).scalar() total = db.session.query(db.func.count(UserMsgMESSAGE.id_msgMESSAGE)).\ filter( UserMsgMESSAGE.id_user_to == uid ).scalar() template = """ {{ _("You have %(x_num_new)d new messages out of %(x_num_total)d messages.", x_num_new=unread, x_num_total=total) }} """ return render_template_to_string(template, _from_string=True, unread=unread, total=total)
def test_email_text_template(self): """ Test email text template engine. """ from invenio_ext.template import render_template_to_string contexts = { 'ctx1': { 'content': 'Content 1' }, 'ctx2': { 'content': 'Content 2', 'header': 'Header 2' }, 'ctx3': { 'content': 'Content 3', 'footer': 'Footer 3' }, 'ctx4': { 'content': 'Content 4', 'header': 'Header 4', 'footer': 'Footer 4' } } msg_content = """Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: %s From: [email protected] To: [email protected]""" for name, ctx in iteritems(contexts): msg = render_template_to_string('mail_text.tpl', **ctx) send_email('*****@*****.**', ['*****@*****.**'], subject=name, **ctx) email = sys.stdout.getvalue() self.assertIn(msg_content % name, email) self.assertIn(msg, email) self.flush_mailbox()
def test_email_html_template(self): """ Test email html template engine. """ from invenio_ext.template import render_template_to_string contexts = { 'ctx1': { 'html_content': '<b>Content 1</b>' }, 'ctx2': { 'html_content': '<b>Content 2</b>', 'html_header': '<h1>Header 2</h1>' }, 'ctx3': { 'html_content': '<b>Content 3</b>', 'html_footer': '<i>Footer 3</i>' }, 'ctx4': { 'html_content': '<b>Content 4</b>', 'html_header': '<h1>Header 4</h1>', 'html_footer': '<i>Footer 4</i>' } } def strip_html_key(ctx): return dict(map(lambda (k, v): (k[5:], v), iteritems(ctx))) for name, ctx in iteritems(contexts): msg = render_template_to_string('mail_html.tpl', **strip_html_key(ctx)) send_email('*****@*****.**', ['*****@*****.**'], subject=name, content='Content Text', **ctx) email = sys.stdout.getvalue() self.assertIn('Content-Type: multipart/alternative;', email) self.assertIn('Content Text', email) self.assertIn(msg, email) self.flush_mailbox()
def open_tag(self, subfield, **kwargs): """Render open tag.""" if self.html_tag: if subfield.name.endswith('__input__'): return '<%s>' % self.html_tag else: ctx = {} if (isinstance(subfield.data, six.string_types)): ctx['value'] = subfield.data elif subfield.data: ctx.update(subfield.data) return ( '<%s %s><button type="button" class="close remove-element"' ' data-dismiss="alert">×</button>' '<span class="tag-title">%s</span>' % (self.html_tag, html_params(class_=self.class_ + ' ' + kwargs.get('class_', '')), render_template_to_string( self.template, _from_string=True, **ctx))) return ''
def render_citations(recid): """Citation export for single record in datatables format. :returns: list List of lists where every item represents a datatables row. A row consists of [reference, num_citations] """ out = [] row = [] es_query = Query('refersto:' + str(recid)).search() es_query.body.update({ 'sort': [{'citation_count': {'order': 'desc'}}] }) citations = es_query.records() for citation in citations: row.append(render_template_to_string("citations.html", record=citation, reference=None)) row.append(citation.get('citation_count', '')) out.append(row) row = [] return out
def tplEqualToString(self, tpl, text, **ctx): self.assertEqual( render_template_to_string(tpl, _from_string=True, **ctx), text)
def tplEqualToString(self, tpl, text, **ctx): self.assertEqual(render_template_to_string(tpl, _from_string=True, **ctx), text)
def forge_email(fromaddr, toaddr, subject, content, html_content='', html_images=None, usebcc=False, header=None, footer=None, html_header=None, html_footer=None, ln=None, charset=None, replytoaddr="", attachments=None, bccaddr=""): """Prepare email. Add header and footer if needed. @param fromaddr: [string] sender @param toaddr: [string or list-of-strings] list of receivers (if string, then receivers are separated by ',') @param usebcc: [bool] True for using Bcc in place of To @param subject: [string] subject of the email @param content: [string] content of the email @param html_content: [string] html version of the email @param html_images: [dict] dictionary of image id, image path @param header: [string] None for the default header @param footer: [string] None for the default footer @param ln: language @charset: [string] the content charset. By default is None which means to try to encode the email as ascii, then latin1 then utf-8. @param replytoaddr: [string or list-of-strings] to be used for the reply-to header of the email (if string, then receivers are separated by ',') @param attachments: list of paths of files to be attached. Alternatively, every element of the list could be a tuple: (filename, mimetype) @param bccaddr: [string or list-of-strings] to be used for BCC header of the email (if string, then receivers are separated by ',') @return: forged email as an EmailMessage object""" from invenio_ext.template import render_template_to_string ln = default_ln(ln) if html_images is None: html_images = {} content = render_template_to_string('mail_text.tpl', content=unicodifier(content), header=unicodifier(header), footer=unicodifier(footer) ).encode('utf8') if isinstance(toaddr, list): toaddr = ','.join(toaddr) if isinstance(bccaddr, list): bccaddr = ','.join(bccaddr) if isinstance(replytoaddr, list): replytoaddr = ','.join(replytoaddr) toaddr = remove_temporary_emails(toaddr) headers = {} kwargs = {'to': [], 'cc': [], 'bcc': []} if replytoaddr: headers['Reply-To'] = replytoaddr if usebcc: headers['Bcc'] = bccaddr kwargs['bcc'] = toaddr.split(',') + bccaddr.split(',') kwargs['to'] = ['Undisclosed.Recipients:'] else: kwargs['to'] = toaddr.split(',') headers['From'] = fromaddr headers['Date'] = formatdate(localtime=True) headers['User-Agent'] = 'Invenio %s at %s' % (cfg['CFG_VERSION'], cfg['CFG_SITE_URL']) if html_content: html_content = render_template_to_string( 'mail_html.tpl', content=unicodifier(html_content), header=unicodifier(html_header), footer=unicodifier(html_footer) ).encode('utf8') msg_root = EmailMultiAlternatives(subject=subject, body=content, from_email=fromaddr, headers=headers, **kwargs) msg_root.attach_alternative(html_content, "text/html") # if not html_images: # # No image? Attach the HTML to the root # msg_root.attach(msg_text) # else: if html_images: # Image(s)? Attach the HTML and image(s) as children of a # "related" block msg_related = MIMEMultipart('related') # msg_related.attach(msg_text) for image_id, image_path in iteritems(html_images): attach_embed_image(msg_related, image_id, image_path) msg_root.attach(msg_related) else: msg_root = EmailMessage(subject=subject, body=content, from_email=fromaddr, headers=headers, **kwargs) if attachments: _mimes = MimeTypes(strict=False) for attachment in attachments: try: mime = None if type(attachment) in (list, tuple): attachment, mime = attachment if mime is None: # Automatic guessing of mimetype mime = _mimes.guess_type(attachment)[0] if mime is None: ext = _mimes.guess_extension(getContentType(attachment)) mime = _mimes.guess_type("foo" + ext)[0] if not mime: mime = 'application/octet-stream' part = MIMEBase(*mime.split('/', 1)) part.set_payload(open(attachment, 'rb').read()) Encoders.encode_base64(part) part.add_header( 'Content-Disposition', 'attachment; filename="%s"' % os.path.basename(attachment)) msg_root.attach(part) except: from invenio_ext.logging import register_exception register_exception( alert_admin=True, prefix="Can't attach %s" % attachment) return msg_root
def cache_record_oneline_views(self): from invenio_ext.template import render_template_to_string for record in self.records: render_template_to_string("citations.html", record=record, reference=None)
def create_config(force=False, no_ssl=False): """ Create Apache configuration files for this site, keeping previous files in a backup copy. """ import os import pwd import pkg_resources import sys import shutil from flask import current_app from jinja2 import TemplateNotFound from invenio_ext.template import render_template_to_string from invenio_utils.text import wrap_text_in_a_box CFG_ETCDIR = current_app.config.get('CFG_ETCDIR', '') def get_context(): conf = current_app.config # Apache vhost conf file is distro specific, so analyze needs: # Gentoo (and generic defaults): listen_directive_needed = True ssl_pem_directive_needed = False ssl_pem_path = CFG_ETCDIR + '/apache/ssl/apache.pem' ssl_crt_path = CFG_ETCDIR + '/apache/ssl/server.crt' ssl_key_path = CFG_ETCDIR + '/apache/ssl/server.key' vhost_ip_address_needed = False wsgi_socket_directive_needed = False # Debian: if os.path.exists(os.path.sep + 'etc' + os.path.sep + 'debian_version'): listen_directive_needed = False ssl_pem_directive_needed = True ssl_pem_path = '/etc/apache2/ssl/apache.pem' ssl_crt_path = '/etc/apache2/ssl/server.crt' ssl_key_path = '/etc/apache2/ssl/server.key' # RHEL/SLC: if os.path.exists(os.path.sep + 'etc' + os.path.sep + 'redhat-release'): listen_directive_needed = False ssl_crt_path = '/etc/pki/tls/certs/localhost.crt' ssl_key_path = '/etc/pki/tls/private/localhost.key' vhost_ip_address_needed = True wsgi_socket_directive_needed = True # maybe we are using non-standard ports? vhost_site_url = conf.get('CFG_SITE_URL').replace("http://", "") if vhost_site_url.startswith("https://"): # The installation is configured to require HTTPS for any # connection vhost_site_url = vhost_site_url.replace("https://", "") vhost_site_url_port = '80' vhost_site_secure_url = conf.get('CFG_SITE_SECURE_URL').replace( "https://", "").replace("http://", "") vhost_site_secure_url_port = '443' if ':' in vhost_site_url: vhost_site_url, vhost_site_url_port = vhost_site_url.split(':', 1) if ':' in vhost_site_secure_url: vhost_site_secure_url, vhost_site_secure_url_port = \ vhost_site_secure_url.split(':', 1) if vhost_site_url_port != '80' or vhost_site_secure_url_port != '443': listen_directive_needed = True static_root = current_app.config['COLLECT_STATIC_ROOT'] if not os.path.exists(static_root): os.mkdir(static_root) def prepare_alias(filename): if os.path.isdir(os.path.join(static_root, filename)): return '/%s/' % (filename, ) return '/%s' % (filename, ) aliases = map(prepare_alias, os.listdir(static_root)) apc1 = {'vhost_site_url_port': vhost_site_url_port, 'servername': vhost_site_url, 'serveralias': vhost_site_url.split('.')[0], 'vhost_ip_address': vhost_ip_address_needed and _detect_ip_address() or '*', 'wsgi_socket_directive_needed': wsgi_socket_directive_needed, 'listen_directive_needed': listen_directive_needed, 'aliases': aliases, } apc2 = {'vhost_site_url_port': vhost_site_secure_url_port, 'servername': vhost_site_secure_url, 'serveralias': vhost_site_secure_url.split('.')[0], 'vhost_ip_address': vhost_ip_address_needed and _detect_ip_address() or '*', 'wsgi_socket_directive_needed': wsgi_socket_directive_needed, 'ssl_pem_directive': ssl_pem_directive_needed and 'SSLCertificateFile %s' % ssl_pem_path or '#SSLCertificateFile %s' % ssl_pem_path, 'ssl_crt_directive': ssl_pem_directive_needed and '#SSLCertificateFile %s' % ssl_crt_path or 'SSLCertificateFile %s' % ssl_crt_path, 'ssl_key_directive': ssl_pem_directive_needed and '#SSLCertificateKeyFile %s' % ssl_key_path or 'SSLCertificateKeyFile %s' % ssl_key_path, 'listen_directive_needed': listen_directive_needed, 'aliases': aliases, } return [apc1, apc2] current_app.config.update( SYS_PREFIX=sys.prefix, CFG_RUNNING_AS_USER=pwd.getpwuid(os.getuid())[0], CFG_WSGIDIR=os.path.abspath( pkg_resources.resource_filename('invenio', ''))) apache_conf_dir = current_app.instance_path + os.sep + 'apache' print(">>> Going to create Apache conf files...") conf_files = ['invenio-apache-vhost.conf', 'invenio-apache-vhost-ssl.conf'] conf_files = conf_files[:1 if no_ssl else 2] if not os.path.exists(apache_conf_dir): os.mkdir(apache_conf_dir) for local_file, context in zip(conf_files, get_context()[:1 if no_ssl else 2]): print(">>> Writing %s ..." % local_file) try: apache_vhost_file = apache_conf_dir + os.sep + local_file if os.path.exists(apache_vhost_file): shutil.copy(apache_vhost_file, apache_vhost_file + '.OLD') with open(apache_vhost_file, 'w') as f: out = render_template_to_string(local_file + '.tpl', os=os, **context) print(out, file=f) except TemplateNotFound: print("Could not find template %s".format(local_file), file=sys.stderr) print(wrap_text_in_a_box("""\ Apache virtual host configuration file(s) for your Invenio site was(were) created. Please check created file(s) and activate virtual host(s). For example, you can put the following include statements in your httpd.conf:\n %s Please see the INSTALL file for more details. """ % '\n\n'.join(tuple(map( lambda x: "Include " + apache_conf_dir.encode('utf-8') + os.sep + x, list(conf_files[:1 if no_ssl else 2])))))) print(">>> Apache conf files created.")
def template_context_function(id_bibrec, id_user): """Add tag editor. :param id_bibrec: ID of record :param id_user: user viewing the record (and owning the displayed tags) :return: HTML containing tag list """ if id_user and id_bibrec: # Get user settings: user = User.query.get(id_user) user_settings = user.settings.get( 'webtag', cfg['CFG_WEBTAG_DEFAULT_USER_SETTINGS']) if not user_settings['display_tags']: # Do not display if user turned off tags in settings return '' # Private query_results = db.session.query(WtgTAG, WtgTAGRecord.annotation)\ .filter(WtgTAG.id == WtgTAGRecord.id_tag)\ .filter(WtgTAGRecord.id_bibrec == id_bibrec)\ .filter(WtgTAG.id_user == id_user)\ .all() # Group tags if user_settings.get('display_tags_group', True): group_results = db.session.query( WtgTAG, WtgTAGRecord.annotation, Group.name ).join(Membership, Membership.id_user == id_user)\ .filter(WtgTAG.id == WtgTAGRecord.id_tag)\ .filter(WtgTAGRecord.id_bibrec == id_bibrec)\ .filter(WtgTAG.group_access_rights >= WtgTAG.ACCESS_LEVELS['View'])\ .filter(WtgTAG.id_usergroup == Group.id)\ .filter(WtgTAG.id_user != id_user)\ .filter(Group.id == Membership.id_usergroup)\ .all() for (tag, annotation, group_name) in group_results: tag.group_name = group_name query_results.append((tag, annotation)) # Public tags # if user_settings.get('display_tags_public', True): tag_infos = [] for (tag, annotation_text) in query_results: tag_info = dict( id=tag.id, name=tag.name, record_count=tag.record_count, annotation=annotation_text, label_classes='') tag_info['owned'] = (tag.id_user == id_user) tag_info['is_group'] = (tag.id_usergroup != 0) tag_info['is_private'] = not tag_info['is_group'] if tag_info['is_private']: tag_info['label_classes'] += ' label-info' if tag_info['is_group']: tag_info['group_name'] = getattr(tag, 'group_name', '') tag_info['label_classes'] += ' label-success' if tag_info['owned']: tag_info['label_classes'] += ' label-tag-owned' tag_info['popover_title'] = render_template_to_string( 'tags/tag_popover_title.html', tag=tag_info, id_bibrec=id_bibrec) tag_info['popover_content'] = render_template_to_string( 'tags/tag_popover_content.html', tag=tag_info, id_bibrec=id_bibrec) tag_infos.append(tag_info) return render_template_to_string( 'tags/record_tags.html', tag_infos=tag_infos, id_bibrec=id_bibrec) else: return ''
def template_context_function(id_bibrec, id_user): """Add tag editor. :param id_bibrec: ID of record :param id_user: user viewing the record (and owning the displayed tags) :return: HTML containing tag list """ if id_user and id_bibrec: # Get user settings: user = User.query.get(id_user) user_settings = user.settings.get( 'webtag', cfg['CFG_WEBTAG_DEFAULT_USER_SETTINGS']) if not user_settings['display_tags']: # Do not display if user turned off tags in settings return '' # Private query_results = db.session.query(WtgTAG, WtgTAGRecord.annotation)\ .filter(WtgTAG.id == WtgTAGRecord.id_tag)\ .filter(WtgTAGRecord.id_bibrec == id_bibrec)\ .filter(WtgTAG.id_user == id_user)\ .all() # Group tags if user_settings.get('display_tags_group', True): group_results = db.session.query( WtgTAG, WtgTAGRecord.annotation, Group.name ).join(Membership, Membership.id_user == id_user)\ .filter(WtgTAG.id == WtgTAGRecord.id_tag)\ .filter(WtgTAGRecord.id_bibrec == id_bibrec)\ .filter(WtgTAG.group_access_rights >= WtgTAG.ACCESS_LEVELS['View'])\ .filter(WtgTAG.id_usergroup == Group.id)\ .filter(WtgTAG.id_user != id_user)\ .filter(Group.id == Membership.id_usergroup)\ .all() for (tag, annotation, group_name) in group_results: tag.group_name = group_name query_results.append((tag, annotation)) # Public tags # if user_settings.get('display_tags_public', True): tag_infos = [] for (tag, annotation_text) in query_results: tag_info = dict(id=tag.id, name=tag.name, record_count=tag.record_count, annotation=annotation_text, label_classes='') tag_info['owned'] = (tag.id_user == id_user) tag_info['is_group'] = (tag.id_usergroup != 0) tag_info['is_private'] = not tag_info['is_group'] if tag_info['is_private']: tag_info['label_classes'] += ' label-info' if tag_info['is_group']: tag_info['group_name'] = getattr(tag, 'group_name', '') tag_info['label_classes'] += ' label-success' if tag_info['owned']: tag_info['label_classes'] += ' label-tag-owned' tag_info['popover_title'] = render_template_to_string( 'tags/tag_popover_title.html', tag=tag_info, id_bibrec=id_bibrec) tag_info['popover_content'] = render_template_to_string( 'tags/tag_popover_content.html', tag=tag_info, id_bibrec=id_bibrec) tag_infos.append(tag_info) return render_template_to_string('tags/record_tags.html', tag_infos=tag_infos, id_bibrec=id_bibrec) else: return ''
def forge_email(fromaddr, toaddr, subject, content, html_content='', html_images=None, usebcc=False, header=None, footer=None, html_header=None, html_footer=None, ln=None, charset=None, replytoaddr="", attachments=None, bccaddr=""): """Prepare email. Add header and footer if needed. @param fromaddr: [string] sender @param toaddr: [string or list-of-strings] list of receivers (if string, then receivers are separated by ',') @param usebcc: [bool] True for using Bcc in place of To @param subject: [string] subject of the email @param content: [string] content of the email @param html_content: [string] html version of the email @param html_images: [dict] dictionary of image id, image path @param header: [string] None for the default header @param footer: [string] None for the default footer @param ln: language @charset: [string] the content charset. By default is None which means to try to encode the email as ascii, then latin1 then utf-8. @param replytoaddr: [string or list-of-strings] to be used for the reply-to header of the email (if string, then receivers are separated by ',') @param attachments: list of paths of files to be attached. Alternatively, every element of the list could be a tuple: (filename, mimetype) @param bccaddr: [string or list-of-strings] to be used for BCC header of the email (if string, then receivers are separated by ',') @return: forged email as an EmailMessage object""" from invenio_ext.template import render_template_to_string ln = default_ln(ln) if html_images is None: html_images = {} content = render_template_to_string( 'mail_text.tpl', content=unicodifier(content), header=unicodifier(header), footer=unicodifier(footer)).encode('utf8') if isinstance(toaddr, list): toaddr = ','.join(toaddr) if isinstance(bccaddr, list): bccaddr = ','.join(bccaddr) if isinstance(replytoaddr, list): replytoaddr = ','.join(replytoaddr) toaddr = remove_temporary_emails(toaddr) headers = {} kwargs = {'to': [], 'cc': [], 'bcc': []} if replytoaddr: headers['Reply-To'] = replytoaddr if usebcc: headers['Bcc'] = bccaddr kwargs['bcc'] = toaddr.split(',') + bccaddr.split(',') kwargs['to'] = ['Undisclosed.Recipients:'] else: kwargs['to'] = toaddr.split(',') headers['From'] = fromaddr headers['Date'] = formatdate(localtime=True) headers['User-Agent'] = 'Invenio %s at %s' % (cfg['CFG_VERSION'], cfg['CFG_SITE_URL']) if html_content: html_content = render_template_to_string( 'mail_html.tpl', content=unicodifier(html_content), header=unicodifier(html_header), footer=unicodifier(html_footer)).encode('utf8') msg_root = EmailMultiAlternatives(subject=subject, body=content, from_email=fromaddr, headers=headers, **kwargs) msg_root.attach_alternative(html_content, "text/html") # if not html_images: # # No image? Attach the HTML to the root # msg_root.attach(msg_text) # else: if html_images: # Image(s)? Attach the HTML and image(s) as children of a # "related" block msg_related = MIMEMultipart('related') # msg_related.attach(msg_text) for image_id, image_path in iteritems(html_images): attach_embed_image(msg_related, image_id, image_path) msg_root.attach(msg_related) else: msg_root = EmailMessage(subject=subject, body=content, from_email=fromaddr, headers=headers, **kwargs) if attachments: _mimes = MimeTypes(strict=False) for attachment in attachments: try: mime = None if type(attachment) in (list, tuple): attachment, mime = attachment if mime is None: # Automatic guessing of mimetype mime = _mimes.guess_type(attachment)[0] if mime is None: ext = _mimes.guess_extension(getContentType(attachment)) mime = _mimes.guess_type("foo" + ext)[0] if not mime: mime = 'application/octet-stream' part = MIMEBase(*mime.split('/', 1)) part.set_payload(open(attachment, 'rb').read()) Encoders.encode_base64(part) part.add_header( 'Content-Disposition', 'attachment; filename="%s"' % os.path.basename(attachment)) msg_root.attach(part) except: from invenio_ext.logging import register_exception register_exception(alert_admin=True, prefix="Can't attach %s" % attachment) return msg_root
def create_config(force=False, no_ssl=False): """ Create Apache configuration files for this site, keeping previous files in a backup copy. """ import os import pwd import pkg_resources import sys import shutil from flask import current_app from jinja2 import TemplateNotFound from invenio_ext.template import render_template_to_string from invenio_utils.text import wrap_text_in_a_box CFG_ETCDIR = current_app.config.get("CFG_ETCDIR", "") def get_context(): conf = current_app.config # Apache vhost conf file is distro specific, so analyze needs: # Gentoo (and generic defaults): listen_directive_needed = True ssl_pem_directive_needed = False ssl_pem_path = CFG_ETCDIR + "/apache/ssl/apache.pem" ssl_crt_path = CFG_ETCDIR + "/apache/ssl/server.crt" ssl_key_path = CFG_ETCDIR + "/apache/ssl/server.key" vhost_ip_address_needed = False wsgi_socket_directive_needed = False # Debian: if os.path.exists(os.path.sep + "etc" + os.path.sep + "debian_version"): listen_directive_needed = False ssl_pem_directive_needed = True ssl_pem_path = "/etc/apache2/ssl/apache.pem" ssl_crt_path = "/etc/apache2/ssl/server.crt" ssl_key_path = "/etc/apache2/ssl/server.key" # RHEL/SLC: if os.path.exists(os.path.sep + "etc" + os.path.sep + "redhat-release"): listen_directive_needed = False ssl_crt_path = "/etc/pki/tls/certs/localhost.crt" ssl_key_path = "/etc/pki/tls/private/localhost.key" vhost_ip_address_needed = True wsgi_socket_directive_needed = True # maybe we are using non-standard ports? vhost_site_url = conf.get("CFG_SITE_URL").replace("http://", "") if vhost_site_url.startswith("https://"): # The installation is configured to require HTTPS for any # connection vhost_site_url = vhost_site_url.replace("https://", "") vhost_site_url_port = "80" vhost_site_secure_url = conf.get("CFG_SITE_SECURE_URL").replace("https://", "").replace("http://", "") vhost_site_secure_url_port = "443" if ":" in vhost_site_url: vhost_site_url, vhost_site_url_port = vhost_site_url.split(":", 1) if ":" in vhost_site_secure_url: vhost_site_secure_url, vhost_site_secure_url_port = vhost_site_secure_url.split(":", 1) if vhost_site_url_port != "80" or vhost_site_secure_url_port != "443": listen_directive_needed = True static_root = current_app.config["COLLECT_STATIC_ROOT"] if not os.path.exists(static_root): os.mkdir(static_root) def prepare_alias(filename): if os.path.isdir(os.path.join(static_root, filename)): return "/%s/" % (filename,) return "/%s" % (filename,) aliases = map(prepare_alias, os.listdir(static_root)) apc1 = { "vhost_site_url_port": vhost_site_url_port, "servername": vhost_site_url, "serveralias": vhost_site_url.split(".")[0], "vhost_ip_address": vhost_ip_address_needed and _detect_ip_address() or "*", "wsgi_socket_directive_needed": wsgi_socket_directive_needed, "listen_directive_needed": listen_directive_needed, "aliases": aliases, } apc2 = { "vhost_site_url_port": vhost_site_secure_url_port, "servername": vhost_site_secure_url, "serveralias": vhost_site_secure_url.split(".")[0], "vhost_ip_address": vhost_ip_address_needed and _detect_ip_address() or "*", "wsgi_socket_directive_needed": wsgi_socket_directive_needed, "ssl_pem_directive": ssl_pem_directive_needed and "SSLCertificateFile %s" % ssl_pem_path or "#SSLCertificateFile %s" % ssl_pem_path, "ssl_crt_directive": ssl_pem_directive_needed and "#SSLCertificateFile %s" % ssl_crt_path or "SSLCertificateFile %s" % ssl_crt_path, "ssl_key_directive": ssl_pem_directive_needed and "#SSLCertificateKeyFile %s" % ssl_key_path or "SSLCertificateKeyFile %s" % ssl_key_path, "listen_directive_needed": listen_directive_needed, "aliases": aliases, } return [apc1, apc2] current_app.config.update( SYS_PREFIX=sys.prefix, CFG_RUNNING_AS_USER=pwd.getpwuid(os.getuid())[0], CFG_WSGIDIR=os.path.abspath(pkg_resources.resource_filename("invenio", "")), ) apache_conf_dir = current_app.instance_path + os.sep + "apache" print(">>> Going to create Apache conf files...") conf_files = ["invenio-apache-vhost.conf", "invenio-apache-vhost-ssl.conf"] conf_files = conf_files[: 1 if no_ssl else 2] if not os.path.exists(apache_conf_dir): os.mkdir(apache_conf_dir) for local_file, context in zip(conf_files, get_context()[: 1 if no_ssl else 2]): print(">>> Writing %s ..." % local_file) try: apache_vhost_file = apache_conf_dir + os.sep + local_file if os.path.exists(apache_vhost_file): shutil.copy(apache_vhost_file, apache_vhost_file + ".OLD") with open(apache_vhost_file, "w") as f: out = render_template_to_string(local_file + ".tpl", os=os, **context) print(out, file=f) except TemplateNotFound: print("Could not find template %s".format(local_file), file=sys.stderr) print( wrap_text_in_a_box( """\ Apache virtual host configuration file(s) for your Invenio site was(were) created. Please check created file(s) and activate virtual host(s). For example, you can put the following include statements in your httpd.conf:\n %s Please see the INSTALL file for more details. """ % "\n\n".join( tuple( map( lambda x: "Include " + apache_conf_dir.encode("utf-8") + os.sep + x, list(conf_files[: 1 if no_ssl else 2]), ) ) ) ) ) print(">>> Apache conf files created.")