Пример #1
0
    def _on_setup_widgets(self):
        e_type = self.attr('e_type')
        eids = self.attr('eids', [])
        ol = htmler.Ol()
        for eid in eids:
            if e_type == 'role':
                ol.append_child(htmler.Li(auth.get_role(uid=eid).name))
            elif e_type == 'user':
                ol.append_child(htmler.Li(auth.get_user(uid=eid).login))

        self.add_widget(
            widget.static.Text(
                uid='confirmation_text',
                text=lang.t('auth_admin@delete_{}_confirmation'.format(
                    self.attr('e_type'))),
            ))

        self.add_widget(widget.static.HTML(
            uid='uids_text',
            em=ol,
        ))

        self.add_widget(
            widget.button.Link(uid='action_cancel',
                               weight=100,
                               form_area='footer',
                               href=self.referer or self.redirect
                               or router.base_url(),
                               value=lang.t('auth_admin@cancel'),
                               icon='fa fas fa-ban'))

        self.submit_button.color = 'btn btn-danger'
        self.submit_button.icon = 'fa fas fa-trash'
        self.submit_button.value = lang.t('auth_admin@delete')
Пример #2
0
    def _on_setup_widgets(self):
        """Hook.
        """
        from ._api import dispense_entity

        # List of items to process
        ol = htmler.Ol()
        for eid in self.attr('eids', self.attr('ids', [])):
            entity = dispense_entity(self.attr('model'), eid)
            self.add_widget(
                widget.input.Hidden(uid='eids-' + eid, name='eids', value=eid))
            ol.append_child(
                htmler.Li(entity.odm_ui_mass_action_entity_description()))
        self.add_widget(widget.static.HTML(uid='eids-text', em=ol))

        # Submit button
        submit_button = self.get_widget(
            'action_submit')  # type: widget.button.Submit
        submit_button.value = lang.t('odm_ui@continue')
        submit_button.icon = 'angle-double-right'

        # Cancel button
        self.add_widget(
            widget.button.Link(uid='action_cancel',
                               weight=100,
                               value=lang.t('odm_ui@cancel'),
                               href=self.referer or self.redirect
                               or router.base_url(),
                               icon='fa fas fa-ban',
                               form_area='footer'))
Пример #3
0
    def _on_setup_widgets(self):
        self.add_widget(
            widget.input.Password(
                uid='password',
                weight=10,
                placeholder=lang.t('auth_ui_password@new_password'),
                prepend='<i class="fa fa-fw fa-lock"></i>',
                h_size='col col-sm-6'
                if _BS_VER == 4 else 'col-sm-6 col-sm-offset-3',
                h_size_row_css='justify-content-center'
                if _BS_VER == 4 else '',
                h_size_label=True,
                required=True,
            ))

        self.add_widget(
            widget.input.Password(
                uid='password_confirm',
                weight=20,
                placeholder=lang.t('auth_ui_password@password_confirm'),
                prepend='<i class="fa fa-fw fa-lock"></i>',
                h_size='col col-sm-6'
                if _BS_VER == 4 else 'col-sm-6 col-sm-offset-3',
                h_size_row_css='justify-content-center'
                if _BS_VER == 4 else '',
                h_size_label=True,
                required=True,
            ))

        submit_btn = self.get_widget('action_submit')
        submit_btn.value = lang.t('auth_ui_password@reset_password')
        submit_btn.icon = 'fa fa-key'
Пример #4
0
def on_auth_sign_up(user: auth.AbstractUser):
    # Set session notification
    router.session().add_success_message(
        lang.t('auth_ui@registration_form_success'))

    # Send a confirmation email to the user
    if auth.is_sign_up_confirmation_required():
        msg = tpl.render(
            'auth_ui@mail/{}/sign-up'.format(lang.get_current()), {
                'user':
                user,
                'confirm_url':
                router.rule_url('auth_ui@sign_up_confirm',
                                {'code': user.confirmation_hash})
                if not user.is_confirmed else None
            })
        mail.Message(user.login, lang.t('auth_ui@confirm_registration'),
                     msg).send()

    # Send a notification emails to admins
    if auth.is_sign_up_admins_notification_enabled():
        for admin in auth.get_admin_users():
            msg = tpl.render(
                'auth_ui@mail/{}/sign-up-admin-notify'.format(
                    lang.get_current()), {
                        'admin': admin,
                        'user': user,
                    })
            mail.Message(admin.login,
                         lang.t('auth_ui@registration_admin_notify'),
                         msg).send()
Пример #5
0
    def exec(self):
        reporter = auth.get_current_user()
        if reporter.is_anonymous:
            raise self.forbidden()

        model = self.arg('model')

        try:
            entity = _api.dispense(model, self.arg('uid'))
        except odm.error.EntityNotFound:
            raise self.not_found()

        tpl_name = 'content@mail/{}/abuse'.format(lang.get_current())
        subject = lang.t('content@mail_subject_abuse')
        for recipient in auth.find_users(
                query.Query(query.Eq('status', 'active'))):
            if not entity.odm_auth_check_entity_permissions(
                [PERM_MODIFY, PERM_DELETE], recipient):
                continue

            body = tpl.render(tpl_name, {
                'reporter': reporter,
                'recipient': recipient,
                'entity': entity
            })
            mail.Message(entity.author.login, subject, body).send()

        return {'message': lang.t('content@abuse_receipt_confirm')}
Пример #6
0
    def _on_submit(self):
        try:
            user = auth.get_user(self.val('login'))
            if user.status != auth.USER_STATUS_ACTIVE:
                return

            token = util.random_password(64, True)
            _RESET_TOKENS_POOL.put(token, user.login, _RESET_TOKEN_TTL)
            reset_url = router.rule_url('auth_ui_password@reset',
                                        {'token': token})
            msg_body = tpl.render(
                'auth_ui_password@mail/{}/reset-password'.format(
                    lang.get_current()), {
                        'user': user,
                        'reset_url': reset_url
                    })
            mail.Message(
                user.login,
                lang.t('auth_ui_password@reset_password_mail_subject'),
                msg_body).send()

            router.session().add_info_message(
                lang.t('auth_ui_password@check_email_for_instructions'))

        except auth.error.UserNotFound:
            pass
Пример #7
0
    def _on_setup_widgets(self):
        app_id = ''
        app_secret = ''
        try:
            app_id = _api.get_app_id()
            app_secret = _api.get_app_secret()
        except (_error.AppIdNotSet, _error.AppSecretNotSet):
            pass

        self.add_widget(
            _widget.input.Text(
                uid='setting_app_id',
                weight=10,
                label=_lang.t('facebook@app_id'),
                required=True,
                help=_lang.t('facebook@app_id_setup_help'),
                rules=_validation.rule.Integer(),
                default=app_id,
            ))

        self.add_widget(
            _widget.input.Text(
                uid='setting_app_secret',
                weight=20,
                label=_lang.t('facebook@app_secret'),
                required=True,
                help=_lang.t('facebook@app_secret_setup_help'),
                rules=_validation.rule.Regex(pattern='[0-9a-f]{32}'),
                default=app_secret,
            ))

        super()._on_setup_widgets()
Пример #8
0
    def exec(self) -> dict:
        # If the user is already authenticated
        if not auth.get_current_user().is_anonymous:
            raise self.forbidden(
                lang.t('auth_http_api@user_already_authenticated'))

        try:
            user = auth.sign_in(self.arg('driver'), self.args)

            r = {'status': True}
            if self.arg('access_token'):
                r['access_token'] = _get_access_token_info(
                    auth.generate_access_token(user))

            return r

        # User account is not active
        except (auth.error.UserNotActive, auth.error.UserNotConfirmed) as e:
            raise self.warning(e, 401)

        # Any other exception
        except Exception as e:
            # Don't expose reason of error to the outer world
            logger.error(e)
            raise self.unauthorized(
                lang.t('auth_http_api@authentication_error'))
Пример #9
0
def _update_themes():
    import subprocess
    import semaver
    from os import path
    from pytsite import console, lang, pip, plugman
    from plugins import assetman
    from . import _api

    for theme in _api.get_all().values():
        # Update theme from git repository
        if path.exists(path.join(theme.path, '.git')):
            console.print_info(
                lang.t('theming@updating_theme', {'name': theme.name}))
            subprocess.call(['git', '-C', theme.path, 'pull'])

        console.print_info(
            lang.t('theming@installing_theme_requirements',
                   {'name': theme.name}))

        # Install/upgrade required pip packagers
        for p_name, p_ver in theme.requires['packages'].items():
            pip.install(p_name, p_ver, True)

        # Install or update required plugins
        for p_name, p_ver in theme.requires['plugins'].items():
            plugman.install(p_name, semaver.VersionRange(p_ver))

        # Compile theme assets
        if assetman.is_package_registered(theme.package_name):
            assetman.build(theme.package_name)
Пример #10
0
    def _on_setup_widgets(self):
        # Label
        self.add_widget(
            widget.static.HTML(uid='upload_header',
                               weight=10,
                               em=htmler.H2(
                                   lang.t('theming@install_or_update_theme'))))

        # Upload theme input
        self.add_widget(
            widget.input.File(
                uid='file',
                weight=11,
                max_files=1,
                upload_endpoint=http_api.endpoint('theming@install'),
            ))

        # Themes browser
        self.add_widget(_ThemesBrowser(
            uid='themes',
            weight=20,
        ))

        # Label
        self.add_widget(
            widget.static.HTML(
                uid='theme_settings_header',
                weight=30,
                em=htmler.H2(lang.t('theming@theme_settings')),
            ))

        # Logo
        self.add_widget(
            file_ui.widget.ImagesUpload(
                uid='setting_logo',
                weight=40,
                label=lang.t('theming@logo'),
                skip_missing=True,
            ))

        # Footer logo
        self.add_widget(
            file_ui.widget.ImagesUpload(
                uid='setting_logo_footer',
                weight=50,
                label=lang.t('theming@logo_footer'),
                skip_missing=True,
            ))

        # Favicon
        self.add_widget(
            file_ui.widget.ImagesUpload(
                uid='setting_favicon',
                weight=60,
                label=lang.t('theming@favicon'),
                skip_missing=True,
            ))

        super()._on_setup_widgets()
Пример #11
0
def get_user_statuses() -> tuple:
    """Get valid user statuses
    """
    return (
        ('active', lang.t('auth@status_active')),
        ('waiting', lang.t('auth@status_waiting')),
        ('disabled', lang.t('auth@status_disabled')),
    )
Пример #12
0
    def setup_widgets(self):
        """Setup widgets
        """
        # 'Submit' button for the last step
        if self.steps == self._current_step and self._submit_button:
            self.add_widget(self._submit_button)

        # 'Next' button for all steps except the last one
        if self._current_step < self.steps:
            self.add_widget(
                _widget.button.Submit(weight=200,
                                      uid='action_forward_' +
                                      str(self._current_step + 1),
                                      value=_lang.t('form@forward'),
                                      form_area='footer',
                                      color='primary',
                                      css='form-action-forward',
                                      icon='fa fas fa-fw fa-forward',
                                      data={
                                          'to-step': self._current_step + 1,
                                      }))

        # 'Back' button for all steps except the first one
        if self._current_step > 1:
            self.add_widget(
                _widget.button.Button(weight=100,
                                      uid='action_backward_' +
                                      str(self._current_step - 1),
                                      value=_lang.t('form@backward'),
                                      form_area='footer',
                                      form_step=self._current_step,
                                      css='form-action-backward',
                                      icon='fa fas fa-fw fa-backward',
                                      data={
                                          'to-step': self._current_step - 1,
                                      }))

        # Ask form instance to setup widgets
        self._on_setup_widgets()

        # Ask others to setup form's widgets
        _events.fire('form@setup_widgets.' + self.name, frm=self)

        # Restore widgets' values
        if self._cache:
            try:
                for k, v in _cache.get_pool('form.form_values').get_hash(
                        self._uid).items():
                    try:
                        self.get_widget(k).set_val(v)
                    except _error.WidgetNotExistError:
                        pass
            except _cache.error.KeyNotExist:
                pass

        return self
Пример #13
0
    def __init__(self, uid: str, **kwargs):
        super().__init__(uid, **kwargs)

        self._max_slots = kwargs.get('max_slots', 100)
        self._modal_title = kwargs.get('modal_title',
                                       lang.t('auth_ui@select_user'))
        self._modal_ok_button_caption = kwargs.get('modal_ok_button_caption',
                                                   lang.t('auth_ui@add'))
        self._modal_cancel_button_caption = kwargs.get(
            'modal_cancel_button_caption')
Пример #14
0
    def _on_setup_widgets(self):
        self.add_widget(_widget.input.Number(
            uid='setting_counter_id',
            weight=10,
            label=_lang.t('yandex_metrika@counter_id'),
            required=True,
            help=_lang.t('yandex_metrika@counter_id_setup_help'),
            rules=_validation.rule.Integer()
        ))

        super()._on_setup_widgets()
Пример #15
0
    def _on_setup_widgets(self):
        self.add_widget(
            _widget.input.Text(
                uid='setting_tracking_id',
                weight=10,
                label=_lang.t('google_analytics@tracking_id'),
                required=True,
                help=_lang.t('google_analytics@tracking_id_setup_help'),
                rules=_validation.rule.Regex(pattern='UA-\d+-\d+')))

        super()._on_setup_widgets()
Пример #16
0
    def _on_setup_widgets(self):
        """Hook
        """
        if not _api.get_drivers():
            self.remove_widget('action_submit')
            self.add_widget(widget.static.Text(
                uid='error_message',
                text=lang.t('comments@no_comments_driver_installed'),
            ))
            return

        self.add_widget(widget.select.Select(
            uid='setting_driver',
            weight=10,
            label=lang.t('comments@driver'),
            h_size='col-xs-12 col-sm-6 col-md-4 col-lg-3',
            append_none_item=False,
            required=True,
            items=[(k, d.get_description()) for k, d in sorted(_api.get_drivers().items())],
            default=_api.get_driver().get_name(),
        ))

        self.add_widget(widget.select.Select(
            uid='setting_max_comment_depth',
            weight=20,
            label=lang.t('comments@max_comment_depth'),
            h_size='col-xs-12 col-sm-3 col-md-2 col-lg-1',
            append_none_item=False,
            required=True,
            items=[(str(x), str(x)) for x in range(0, 11)],
            default=4,
        ))

        self.add_widget(widget.input.Integer(
            uid='setting_min_comment_length',
            weight=30,
            label=lang.t('comments@min_comment_length'),
            h_size='col-xs-12 col-sm-3 col-md-2 col-lg-1',
            default=2,
            required=True,
        ))

        self.add_widget(widget.input.Integer(
            uid='setting_max_comment_length',
            weight=40,
            label=lang.t('comments@max_comment_length'),
            h_size='col-xs-12 col-sm-3 col-md-2 col-lg-1',
            default=2048,
            required=True,
        ))

        super()._on_setup_widgets()
Пример #17
0
    def _on_setup_widgets(self):
        self.add_widget(_widget.input.Email(
            uid='email',
            weight=10,
            label=_lang.t('content_digest@your_email'),
            label_hidden=True,
            placeholder=_lang.t('content_digest@your_email'),
            required=True,
        ))

        self.submit_button.form_area = 'body'
        self.submit_button.value = _lang.t('content_digest@ok')
        self.submit_button.icon = None
Пример #18
0
    def _on_setup_widgets(self):
        """Hook.
        """
        self.add_widget(
            widget.input.Text(
                uid='setting_pub_id',
                weight=10,
                label=lang.t('addthis@pub_id'),
                required=True,
                help=lang.t('addthis@pub_id_setup_help'),
                rules=validation.rule.Regex(pattern='ra-[0-9a-f]{16}')))

        super()._on_setup_widgets()
Пример #19
0
    def _on_setup_form(self):
        if self.attr('e_type') not in ('role', 'user'):
            raise ValueError('Auth entity type is not specified')

        if not self.attr('eids'):
            raise ValueError('Entity IDs is not specified')

        if self.attr('e_type') == 'role':
            self.title = lang.t('auth_admin@delete_roles')
        else:
            self.title = lang.t('auth_admin@delete_users')

        lang.t('auth_admin@delete_roles')
    def _on_setup_widgets(self):
        """Hook.
        """
        self.add_widget(
            widget.input.Text(
                uid='setting_api_key',
                weight=10,
                label=lang.t('google_maps_ui@api_key'),
                help=lang.t('google_maps_ui@api_key_setup_help'),
                default=reg.get('google_maps.api_key'),
            ))

        super()._on_setup_widgets()
Пример #21
0
    def insert_data_field(self,
                          name: str,
                          title: str = None,
                          sortable: bool = True,
                          pos: int = None):
        """Insert a data field
        """
        title = lang.t(title) if title else lang.t(name)

        if pos is None:
            pos = len(self._data_fields)

        self._data_fields.insert(pos, (name, title, sortable))
Пример #22
0
    def _render_sidebar(sidebar: admin.SideBar) -> htmler.Aside:
        """Render admin's sidebar
        """
        aside = htmler.Aside(css='main-sidebar')
        sidebar_section_em = htmler.Section(css='sidebar')
        aside.append_child(sidebar_section_em)

        root_menu_ul = htmler.Ul(css='sidebar-menu')
        sidebar_section_em.append_child(root_menu_ul)

        sections, menus = sidebar.items

        # Do actual rendering
        for section in sections:
            li = htmler.Li(lang.t(section['title']),
                           css='header',
                           data_section_weight=section['weight'])
            root_menu_ul.append_child(li)

            # Building top level menu item
            for menu in menus[section['sid']]:
                # Link
                a = htmler.A(
                    href=router.url(menu['path'], lang=lang.get_current()))

                # Icon
                if menu['icon']:
                    a.append_child(htmler.I(css=menu['icon']))

                # Title
                a.append_child(htmler.Span(lang.t(menu['title'])))

                # Label
                if menu['label']:
                    label_class = 'label pull-right label-' + menu[
                        'label_class']
                    a.append_child(
                        htmler.Span(lang.t(menu['label']), css=label_class))

                # List element
                li = htmler.Li(data_menu_weight=menu['weight'])

                # Active state
                if menu['active']:
                    li.set_attr('css', 'active')

                li.append_child(a)
                root_menu_ul.append_child(li)

        return aside
Пример #23
0
    def render(self) -> str:
        # 'Create' toolbar button
        if self._model_class.odm_ui_creation_allowed(
        ) and odm_auth.check_model_permissions(self._model, PERM_CREATE):
            create_form_url = router.rule_url(
                self._m_form_rule, {
                    'model': self._model,
                    'eid': 0,
                    '__redirect': router.current_url(),
                })
            title = lang.t('odm_ui@create')
            btn = htmler.A(href=create_form_url,
                           css='btn btn-default btn-light add-button',
                           title=title)
            btn.append_child(htmler.I(css='fa fas fa-fw fa-plus'))
            self._widget.toolbar.append_child(btn)
            self._widget.toolbar.append_child(htmler.Span('&nbsp;'))

        # 'Delete' toolbar button
        if self._model_class.odm_ui_deletion_allowed():
            delete_form_url = router.rule_url(self._d_form_rule,
                                              {'model': self._model})
            title = lang.t('odm_ui@delete_selected')
            btn = htmler.A(
                href=delete_form_url,
                css='hidden btn btn-danger mass-action-button sr-only',
                title=title)
            btn.append_child(htmler.I(css='fa fas fa-fw fa-remove fa-times'))
            self._widget.toolbar.append_child(btn)
            self._widget.toolbar.append_child(htmler.Span('&nbsp;'))

        # Additional toolbar buttons
        for btn_data in self._model_class.odm_ui_browser_mass_action_buttons():
            ep = btn_data.get('ep')
            url = router.rule_url(ep) if ep else '#'
            css = 'btn btn-{} mass-action-button'.format(
                btn_data.get('color', 'default btn-light'))
            icon = 'fa fas fa-fw fa-' + btn_data.get('icon', 'question')
            button = htmler.A(href=url, css=css, title=btn_data.get('title'))
            if icon:
                button.append_child(htmler.I(css=icon))
            self._widget.toolbar.append_child(button)
            self._widget.toolbar.append_child(htmler.Span('&nbsp;'))

        frm = htmler.Form(self._widget.render(),
                          action='#',
                          method='post',
                          css='table-responsive odm-ui-browser')

        return frm.render()
Пример #24
0
    def exec(self):
        if not auth.get_current_user().is_admin:
            raise self.forbidden()

        e_type = self.arg('e_type')
        if e_type == 'role':
            metatag.t_set('title', lang.t('auth_admin@roles'))
            form = _frm.BrowseRoles(self.request)
        elif e_type == 'user':
            metatag.t_set('title', lang.t('auth_admin@users'))
            form = _frm.BrowseUsers(self.request)
        else:
            raise self.server_error('Unknown auth entity type')

        return admin.render(tpl.render('auth_admin@form', {'form': form}))
Пример #25
0
    def odm_ui_browser_entity_actions(self, browser) -> List[Dict]:
        """Get actions buttons data for single data row.
        """
        r = []

        if self.odm_ui_modification_allowed(
        ) and self.odm_auth_check_entity_permissions(PERM_MODIFY):
            r.append({
                'url':
                router.rule_url(
                    browser.m_form_rule, {
                        'model':
                        self.model,
                        'eid':
                        str(self.id),
                        '__redirect':
                        router.rule_url(browser.browse_rule,
                                        {'model': self.model}),
                    }),
                'title':
                lang.t('odm_ui@modify'),
                'icon':
                'fa fas fa-fw fa-fw fa-edit',
            })

        if self.odm_ui_deletion_allowed(
        ) and self.odm_auth_check_entity_permissions(PERM_DELETE):
            r.append({
                'url':
                router.rule_url(
                    browser.d_form_rule, {
                        'model':
                        self.model,
                        'ids':
                        str(self.id),
                        '__redirect':
                        router.rule_url(browser.browse_rule,
                                        {'model': self.model}),
                    }),
                'title':
                lang.t('odm_ui@delete'),
                'icon':
                'fa fas fa-fw fa-fw fa-remove fa-times',
                'color':
                'danger',
            })

        return r
Пример #26
0
def router_dispatch():
    """'pytsite.router.dispatch' event handler.
    """
    if _auth.get_current_user().has_role('dev'):
        if not _reg.get('tumblr.app_key') or not _reg.get('tumblr.app_secret'):
            _router.session().add_warning_message(
                _lang.t('tumblr@plugin_setup_required_warning'))
Пример #27
0
def enable(silent: bool = False):
    """Enable maintenance mode.
    """
    if not is_enabled():
        _cache_pool.put('enabled', True)
        if not silent:
            _console.print_success(_lang.t('pytsite.maintenance@maintenance_mode_enabled'))
Пример #28
0
def disable(silent: bool = False):
    """Disable maintenance mode.
    """
    if is_enabled():
        _cache_pool.rm('enabled')
        if not silent:
            _console.print_success(_lang.t('pytsite.maintenance@maintenance_mode_disabled'))
Пример #29
0
def on_router_dispatch():
    try:
        api_key = google_maps.helpers.get_google_api_key()
        metatag.t_set('pytsite-google-maps-api-key', api_key)
    except google_maps.error.GoogleApiKeyNotDefined:
        if auth.get_current_user().has_role('dev'):
            router.session().add_warning_message(lang.t('google_maps_ui@plugin_setup_required_warning'))
Пример #30
0
    def __init__(self, uid: str = None, **kwargs):
        """Init.
        """
        kwargs.setdefault('title', lang.t('comments_odm@comments'))

        super().__init__(uid, **kwargs)

        self.css += ' pytsite-comments'

        thread_uid = kwargs.get('thread_uid')
        self._props.update({
            'authenticationURL': auth_ui.sign_in_url(),
            'isUserAuthenticated': not auth.get_current_user().is_anonymous,
            'settings': {
                'maxBodyLength': comments.get_comment_max_body_length(),
                'minBodyLength': comments.get_comment_min_body_length(),
                'maxDepth': comments.get_comment_max_depth(),
                'statuses': comments.get_comment_statuses(),
                'permissions': comments.get_permissions(driver_name='odm')
            },
            'urls': {
                'get':
                http_api.url('comments@get_comments',
                             {'thread_uid': thread_uid}),
                'post':
                http_api.url('comments@post_comment',
                             {'thread_uid': thread_uid}),
            },
            'threadUID': kwargs.get('thread_uid'),
            'title': kwargs.get('title'),
        })
Пример #31
0
def dump(tag: str) -> str:
    """Dump a tag
    """
    if not _tags:
        raise RuntimeError('reset() should be called before')

    tid = _threading.get_id()

    if tag not in _tags[tid]:
        return ''

    # Page charset
    if tag == 'charset':
        r = '<meta charset="{}">\n'.format(_tags[tid][tag])

    # Page title
    elif tag == 'title':
        r = '<title>{} | {}</title>\n'.format(_tags[tid][tag], _lang.t('app_name'))

    # OpenGraph tags
    elif tag.startswith('og:') or tag.startswith('author:') or tag.startswith('fb:'):
        r = '<meta property="{}" content="{}">'.format(tag, _tags[tid][tag])

    # Page links
    elif tag == 'link':
        r = ''
        for value in _tags[tid][tag]:
            args_str = ' '.join(['{}="{}"'.format(k, v) for k, v in value.items()])
            r += '<{} {}>\n'.format(tag, args_str)

    # Other
    else:
        r = '<meta name="{}" content="{}">'.format(tag, _tags[tid][tag])

    return r
Пример #32
0
    def _default_item_renderer(self, e: odm.Entity):
        caption = self._caption_field(e) if callable(
            self._caption_field) else e.f_get(self._caption_field)
        if self._translate_captions:
            caption = lang.t(caption)

        return super()._default_item_renderer((e.ref, caption))
Пример #33
0
    def _do_validate(self):
        """Do actual validation of the rule.
        """
        if self._value is None:
            return

        self._msg_args.update({
            'pattern': self._pattern,
            'value': self._value
        })

        if isinstance(self.value, (list, tuple)):
            self._msg_id += '_row'
            self.value = _util.cleanup_list(self.value)
            for k, v in enumerate(self.value):
                if not self._regex.match(v):
                    raise _error.RuleError(self._msg_id, dict(self._msg_args, row=k + 1))

        elif isinstance(self.value, dict):
            self._msg_id += '_row'
            self.value = _util.cleanup_dict(self.value)
            for k, v in self.value.items():
                if not self._regex.match(v):
                    raise _error.RuleError(self._msg_id, dict(self._msg_args, row=k + 1))

        elif isinstance(self.value, str):
            value = self.value.strip()
            if value and not self._regex.match(value):
                raise _error.RuleError(self._msg_id, self._msg_args)

        else:
            msg = _lang.t('pytsite.validation@list_dict_str_expected', {'got': self.value.__class__.__name__})
            raise TypeError(msg)
Пример #34
0
def get_comment_statuses() -> Mapping:
    """Get valid comment statuses.
    """
    return {
        s: lang.t('comments@status_{}'.format(s))
        for s in _COMMENT_STATUSES
    }
Пример #35
0
def update_stage_2():
    # Install/update pip packages
    _console.print_info(_lang.t('pytsite.pip@updating_packages'))
    for pkg_name, pkg_ver in _package_info.requires_packages('app').items():
        try:
            _api.install(pkg_name, pkg_ver, True, _reg.get('debug'))
        except _error.PackageInstallError as e:
            raise _console.error.CommandExecutionError(e)
Пример #36
0
def reset(title: str = None):
    """Reset tags
    """
    tid = _threading.get_id()
    _tags[tid] = {}

    t_set('charset', 'UTF-8')
    t_set('title', title or _lang.t('pytsite.metatag@untitled_document'))
    t_set('viewport', 'width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0')
    t_set('pytsite-version', str(_package_info.version('pytsite')))
Пример #37
0
    def exec(self):
        if self.args:
            packages = {}
            for pkg_spec in self.args:
                match = _PKG_SPEC_RE.findall(pkg_spec)
                if not match:
                    raise _console.error.CommandExecutionError('Invalid package identifier: {}'.format(pkg_spec))
                packages[match[0][0]] = match[0][1]
        else:
            packages = _package_info.requires_packages('app').items()

        for pkg_name, pkg_version in packages.items():
            pkg_spec = '{}{}'.format(pkg_name, pkg_version)
            try:
                _console.print_info(_lang.t('pytsite.pip@package_installing', {'package': pkg_spec}))
                _pip.install(pkg_name, pkg_version, self.opt('upgrade'), self.opt('debug'))
                _console.print_success(_lang.t('pytsite.pip@package_successfully_installed', {'package': pkg_spec}))
            except _pip.error.Error as e:
                raise _console.error.CommandExecutionError(e)
Пример #38
0
    def _do_validate(self):
        """Do actual validation of the rule.
        """
        if self._value is None:
            return

        if not isinstance(self.value, list):
            msg = _lang.t('pytsite.validation@list_expected', {'got': self.value.__class__.__name__})
            raise TypeError(msg)

        for row, sub_list in enumerate(self.value):
            if not isinstance(sub_list, list):
                msg = _lang.t('pytsite.validation@list_expected', {'got': self.value.__class__.__name__})
                raise TypeError(msg)

            if self._index + 1 > len(sub_list):
                raise _error.RuleError(self._msg_id, dict(self._msg_args, row=row + 1, col=self._index + 1))

            if not sub_list[self._index]:
                raise _error.RuleError(self._msg_id, dict(self._msg_args, row=row + 1, col=self._index + 1))
Пример #39
0
    def _do_validate(self):
        """Do actual validation of the rule.
        """
        if self._value is None or not self._keys:
            return

        if not isinstance(self._value, dict):
            raise TypeError(_lang.t('pytsite.validation@dict_expected', {'got': self.value.__class__.__name__}))

        for k in self._keys:
            if k not in self._value or not self._value[k]:
                raise _error.RuleError(self._msg_id, self._msg_args)
Пример #40
0
def _do_reload():
    """Modify 'touch.reload' file
    """
    touch_reload_path = _path.join(_reg.get('paths.storage'), 'touch.reload')

    _events.fire('pytsite.reload@before_reload')

    with open(touch_reload_path, 'wt') as f:
        f.write(_util.w3c_datetime_str())

    _events.fire('pytsite.reload@reload')

    _console.print_info(_lang.t('pytsite.reload@app_is_reloading'))
Пример #41
0
    def _do_validate(self):
        """Do actual validation of the rule.
        """
        if self._value is None:
            return

        if not isinstance(self.value, list):
            msg = _lang.t('pytsite.validation@list_expected', {'got': self.value.__class__.__name__})
            raise TypeError(msg)

        for row, sub_list in enumerate(self.value):
            if not isinstance(sub_list, list):
                msg = _lang.t('pytsite.validation@list_expected', {'got': self.value.__class__.__name__})
                raise TypeError(msg)

            if self._index + 1 > len(sub_list):
                raise _error.RuleError(self._msg_id, {'row': row + 1, 'col': self._index + 1})

            try:
                Url(sub_list[self._index], self._msg_id).validate()
            except _error.RuleError:
                raise _error.RuleError(self._msg_id, {'row': row + 1, 'col': self._index + 1})
Пример #42
0
    def _do_validate(self):
        """Do actual validation of the rule.
        """
        if self._value is None:
            return

        super()._do_validate()

        if isinstance(self._value, list):
            for k, v in enumerate(self._value):
                if not self._validate_str(v):
                    raise _error.RuleError(self._msg_id, dict(self._msg_args, row=k + 1))
        elif isinstance(self._value, dict):
            for k, v in self._value.items():
                if not self._validate_str(v):
                    raise _error.RuleError(self._msg_id, dict(self._msg_args, row=k + 1))
        elif isinstance(self._value, str):
            if not self._validate_str(self._value):
                raise _error.RuleError(self._msg_id, self._msg_args)
        else:
            raise TypeError(_lang.t('pytsite.validation@list_dict_str_expected', {'got': type(self._value)}))
Пример #43
0
    def _do_validate(self):
        if not self._value:
            return

        if isinstance(self._value, (list, tuple)):
            for k, v in enumerate(self._value):
                if not _util.is_url(v):
                    self._msg_args['row'] = k + 1
                    raise _error.RuleError(self._msg_id, self._msg_args)

        elif isinstance(self._value, dict):
            for k, v in enumerate(self._value.items()):
                if not _util.is_url(v):
                    self._msg_args['row'] = k + 1
                    raise _error.RuleError(self._msg_id, self._msg_args)

        elif isinstance(self._value, str):
            if not _util.is_url(self._value):
                raise _error.RuleError(self._msg_id, self._msg_args)

        else:
            raise TypeError(_lang.t('pytsite.validation@list_dict_str_expected', {'got': type(self._value)}))
Пример #44
0
 def __str__(self):
     return _lang.t('pytsite.console@invalid_argument', {'arg_index': self._arg_index, 'arg_value': self._arg_value})
Пример #45
0
permissions.define_permission('app.settings.manage', 'app@manage_app_settings', 'app')

# Settings
settings.define('app', settings_form.Form, __name__ + '@application', 'fa fa-cube', 'app.settings.manage')

# Index by section route
router.add_rule('/section/<string:term_alias>', 'index_by_section', 'pytsite.content@index', {
    'model': 'article',
    'term_field': 'section',
})

# Index by tag route
router.add_rule('/tag/<string:term_alias>', 'article_index_by_tag', 'pytsite.content@index', {
    'model': 'article',
    'term_field': 'tags',
})

# Prepare language related tpl globals
language_nav = {}
search_input = {}
for l in lang.langs():
    language_nav[l] = str(widget.select.LanguageNav('language-nav', dropdown=True, language=l))
    search_input[l] = str(content.widget.Search('search-article', model='article',
                                                title=lang.t('app@search', language=l), language=l))

# Tpl globals
tpl.register_global('language_nav', language_nav)
tpl.register_global('search_input', search_input)
tpl.register_global('get_content_sections', lambda: list(content.get_sections()))
tpl.register_global('get_content_pages', lambda: list(content.find('page').get()))
Пример #46
0
    def exec(self, args: tuple = (), **kwargs):
        """Execute the command.
        """
        app_path = _reg.get('paths.app')
        config_path = _reg.get('paths.config')
        stage = self.opt('stage')
        stop_after = self.opt('stop-after')

        _chdir(app_path)
        _maintenance.enable()

        d = self._get_update_data()
        if not d['update_in_progress']:
            d['pytsite_version_from'] = str(_package_info.version('pytsite'))
            d['app_version_from'] = str(_package_info.version('app'))
            d['update_in_progress'] = True
            self._set_update_data(d)

        # Stage 1: update pip and PytSite
        if stage == 1:
            _console.print_info(_lang.t('pytsite.update@updating_environment'))

            # Update pip
            _pip.install('pip', None, True, self.opt('debug'))

            # Update PytSite
            _pip.install('pytsite', _package_info.requires_pytsite('app'), True, self.opt('debug'))

            d['pytsite_version_to'] = str(_package_info.version('pytsite', False))
            self._set_update_data(d)

            # Notify listeners
            _events.fire('pytsite.update@stage_1')

            if stop_after != 1:
                _subprocess.call(['./console', 'update', '--stage=2'])
            else:
                _maintenance.disable()

        # Stage 2: update application and configuration
        elif stage == 2:
            # Notify listeners about PytSite update
            _events.fire('pytsite.update@pytsite', v_from=_semver.Version(d['pytsite_version_from']))

            # Update configuration
            if _path.exists(_path.join(config_path, '.git')):
                _console.print_info(_lang.t('pytsite.update@updating_configuration'))
                _subprocess_run(['git', '-C', config_path, 'pull'])

            # Update application
            if _path.exists(_path.join(app_path, '.git')):
                _console.print_info(_lang.t('pytsite.update@updating_application'))
                _subprocess_run(['git', '-C', app_path, 'pull'])
            d['app_version_to'] = str(_package_info.version('app', False))
            self._set_update_data(d)

            # Notify listeners
            _events.fire('pytsite.update@stage_2')

            if stop_after != 2:
                _subprocess.call(['./console', 'update', '--stage=3'])
            else:
                _maintenance.disable()

        # Stage 3: finish update process
        elif stage == 3:
            _console.print_info(_lang.t('pytsite.update@applying_updates'))

            # Notify listeners about application update
            _events.fire('pytsite.update@app', v_from=_semver.Version(d['app_version_from']))

            # Notify listeners
            _events.fire('pytsite.update@update')

            # Application's update hook
            import app
            if hasattr(app, 'app_update') and callable(app.app_update):
                app.app_update(v_from=_semver.Version(d['app_version_from']))

            # Mark that update was finished successfully
            d['update_in_progress'] = False
            self._set_update_data(d)

            # Disable maintenance mode
            _maintenance.disable()

            # Reload the application
            _reload.reload()
Пример #47
0
 def __str__(self):
     return _lang.t('pytsite.console@options_not_specified', {'opts_list': self._opts_list})
Пример #48
0
 def __str__(self):
     return _lang.t('pytsite.console@required_option_not_specified', {'opt_name': self._opt_name})
Пример #49
0
 def __str__(self):
     return _lang.t('pytsite.console@invalid_option', {'opt_name': self._opt_name})
Пример #50
0
 def __str__(self) -> str:
     return _lang.t(self._msg_id, self._msg_args)
Пример #51
0
def on_pytsite_update_stage_2():
    # Update all installed plugins
    _console.print_info(_lang.t('pytsite.plugman@updating_plugins'))
    _console.run_command('plugman:install', {'reload': False})
Пример #52
0
 def __str__(self):
     return _lang.t(self._msg_id, {'arg_index': self._arg_index})
Пример #53
0
def on_pytsite_load():
    update_info = _api.get_update_info()

    if not update_info:
        return

    # If there waiting updates exist, reload the application
    if _reg.get('env.type') == 'wsgi':
        _logger.warn('Application needs to be loaded in console to finish plugins update')
        return

    failed_plugins = []

    # Call 'plugin_pre_install()' hooks
    for p_name, info in update_info.items():
        v_to = _semver.Version(info['version_to'])

        try:
            # Check if the plugin is installed and loaded
            plugin = _api.get(p_name)

            # Call plugin_pre_install() hook
            if hasattr(plugin, 'plugin_pre_install') and callable(plugin.plugin_pre_install):
                plugin.plugin_pre_install()

            # Fire 'pre_install' event
            _events.fire('pytsite.plugman@pre_install', name=p_name, version=v_to)

        except _error.PluginNotLoaded as e:
            _logger.error(e)
            _console.print_warning(_lang.t('pytsite.plugman@plugin_install_error', {
                'plugin': p_name,
                'version': v_to,
                'msg': str(e),
            }))
            failed_plugins.append(p_name)
            continue

    # Finish installing/updating plugins
    for p_name, info in update_info.items():
        if p_name in failed_plugins:
            continue

        plugin = _api.get(p_name)
        v_from = _semver.Version(info['version_from'])
        v_to = _semver.Version(info['version_to'])

        try:
            _logger.info(_lang.t('pytsite.plugman@installing_plugin', {
                'plugin': p_name,
                'version': v_to,
            }))

            # Call plugin_install() hook
            if hasattr(plugin, 'plugin_install') and callable(plugin.plugin_install):
                plugin.plugin_install()

            # Fire 'install' event
            _events.fire('pytsite.plugman@install', name=p_name, version=v_to)

            _console.print_success(_lang.t('pytsite.plugman@plugin_install_success', {
                'plugin': p_name,
                'version': v_to,
            }))

        except Exception as e:
            _logger.error(e)
            _console.print_warning(_lang.t('pytsite.plugman@plugin_install_error', {
                'plugin': p_name,
                'version': v_to,
                'msg': str(e),
            }))
            continue

        # Update plugin
        if v_from != '0.0.0':
            try:
                _console.print_info(_lang.t('pytsite.plugman@updating_plugin', {
                    'plugin': p_name,
                    'v_from': v_from,
                    'v_to': v_to,
                }))

                # Call plugin_update() hook
                if hasattr(plugin, 'plugin_update') and callable(plugin.plugin_update):
                    plugin.plugin_update(v_from=v_from)

                # Fire 'update' event
                _events.fire('pytsite.plugman@update', name=p_name, v_from=v_from)

                _console.print_success(_lang.t('pytsite.plugman@plugin_update_success', {
                    'plugin': p_name,
                    'version': v_to,
                }))

            except Exception as e:
                _console.print_warning(_lang.t('pytsite.plugman@plugin_update_error', {
                    'plugin': p_name,
                    'version': v_to,
                    'msg': str(e),
                }))
                continue

        # Remove info from update queue
        _api.rm_update_info(p_name)