예제 #1
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'))
예제 #2
0
    def get_comments_count(self, thread_uid: str) -> int:
        """Get comments count for particular thread.
        """
        short_name = reg.get('disqus.short_name')
        secret_key = reg.get('disqus.secret_key')

        if not short_name or not secret_key:
            return 0

        count = 0

        try:
            r = requests.get(
                'https://disqus.com/api/3.0/forums/listThreads.json', {
                    'api_secret': secret_key,
                    'forum': short_name,
                    'thread': 'ident:' + thread_uid,
                    'limit': 1,
                }).json()

            if r['code'] == 0 and r['response']:
                count = r['response'][0]['posts']

        except Exception as e:
            logger.error(e)

        return count
예제 #3
0
파일: _eh.py 프로젝트: pytsite/pytsite
def _cleanup_tmp_files():
    success, failed = _util.cleanup_files(_reg.get('paths.tmp'), 86400)  # 24h

    for f_path in success:
        _logger.debug('Obsolete tmp file removed: {}'.format(f_path))

    for f_path, e in failed:
        _logger.error('Error while removing obsolete tmp file {}: {}'.format(f_path, e))
예제 #4
0
파일: _message.py 프로젝트: pytsite/pytsite
 def do_send(msg: Message):
     try:
         engine = _SMTP('localhost')
         engine.sendmail(msg._from_addr, msg._to_addrs, str(msg))
         log_msg = "Message '{}' has been sent to {}.".format(msg.subject, msg.to_addrs)
         _logger.info(log_msg)
     except Exception as e:
         _logger.error('Unable to send message to {}: {}'.format(msg.to_addrs, e), exc_info=e)
예제 #5
0
 def exec(self):
     try:
         _api.dispense_bot(self.arg('bot_uid')).process_update(
             types.Update(json.loads(self.request.data)))
     except error.BotNotRegistered as e:
         logger.warn(str(e))
     except Exception as e:
         logger.error(e)
예제 #6
0
 def get_file(self, file_id: str) -> types.File:
     try:
         return types.File(self._request('getFile', {
             'file_id': file_id,
         }))
     except error.ApiRequestError as e:
         logger.error(e)
         raise error.FileNotFound(file_id)
예제 #7
0
파일: _eh.py 프로젝트: pytsite/pytsite
def on_cleanup():
    success, failed = _util.cleanup_files(_reg.get('paths.session'), _reg.get('router.session_ttl', 86400))

    for f_path in success:
        _logger.debug('Obsolete session file removed: {}'.format(f_path))

    for f_path, e in failed:
        _logger.error('Error while removing obsolete session file {}: {}'.format(f_path, e))
예제 #8
0
파일: _eh.py 프로젝트: pytsite/pytsite
def cleanup():
    success, failed = _util.cleanup_files(_reg.get('paths.log'), _reg.get('logger.file_ttl', 2592000))  # 30d

    for f_path in success:
        _logger.debug('Obsolete log file removed: {}'.format(f_path))

    for f_path, e in failed:
        _logger.error('Error while removing obsolete log file {}: {}'.format(f_path, e))
예제 #9
0
def pytsite_cleanup():
    root = _path.join(_reg.get('paths.static'), 'image', 'resize')
    ttl = _reg.get('file_storage_odm.static_ttl', 2592000)  # 1 month

    success, failed = _util.cleanup_files(root, ttl)

    for f_path in success:
        _logger.debug('Obsolete static file removed: {}'.format(f_path))

    for f_path, e in failed:
        _logger.error('Error while removing obsolete static file {}: {}'.format(f_path, e))
예제 #10
0
def dispense(uid: str, request: Request = None) -> Form:
    """Dispense a form from the cache
    """
    try:
        if not _FORMS.has(uid):
            raise KeyError(f"Form '{uid}' is not found")

        form = _FORMS.get(uid)
        form.request = request or router.request()
        return form

    except Exception as e:
        logger.error(e)
        raise RuntimeError('Unexpected form exception')
예제 #11
0
    def _on_submit(self):
        from ._api import dispense_entity

        model = self.attr('model')

        try:
            # Ask entities to process deletion
            for eid in self.attr('eids', self.attr('ids', [])):
                dispense_entity(model, eid).odm_ui_d_form_submit()

            router.session().add_info_message(
                lang.t('odm_ui@operation_successful'))

        # Entity deletion was forbidden
        except errors.ForbidDeletion as e:
            logger.error(e)
            router.session().add_error_message(
                lang.t('odm_ui@entity_deletion_forbidden') + '. ' + str(e))
예제 #12
0
    def get_comments_count(self, thread_uid: str) -> int:
        """Get comments count for particular thread.
        """
        count = 0

        try:
            r = _requests.get('https://graph.facebook.com/v2.4', {
                'fields': 'share{comment_count}',
                'id': thread_uid,
            }).json()

            if 'share' in r:
                count = int(r['share']['comment_count'])

        except Exception as e:
            _logger.error(e)

        return count
예제 #13
0
    def call_command(self,
                     name: str,
                     msg: Union[types.Message, types.CallbackQuery],
                     step: int = None):
        """Process an incoming command
        """
        self.command_name = name
        if step is not None:
            self.command_step = step

        try:
            cmd_method = 'cmd_{}'.format(name)
            if hasattr(self, cmd_method):
                getattr(self, cmd_method)(msg)
            else:
                self.handle_command(name, msg)

        except error.CommandExecutionError as e:
            logger.error(e)
            self.send_message(e.msg, reply_markup=e.reply_markup)
예제 #14
0
    def exec(self):
        del self.args['_pytsite_router_rule_name']
        endpoint = '/' + self.args.pop('http_api_endpoint')
        current_path = router.current_path(False)
        request_method = router.request().method

        # Switch language
        language = router.request().headers.get('Accept-Language')  # type: str
        if language:
            for lng in language.split(','):
                lng = lng.strip()
                if not lng.startswith('q=') and lang.is_defined(language):
                    lang.set_current(language)
                    break
        try:
            events.fire('http_api@pre_request')
            rule = _api.match(router.request().method, endpoint)
            events.fire('http_api@request')

            controller = rule.controller_class()  # type: routing.Controller
            controller.request = self.request
            controller.args.update(self.args)
            controller.args.update(rule.args)
            controller.args['_pytsite_http_api_rule_name'] = rule.name
            controller.args.validate()

            response = controller.exec()
            return response if isinstance(
                response, http.Response) else http.JSONResponse(response)

        except (http.error.Base, errors.ForbidOperation) as e:
            if reg.get('debug'):
                logger.error(e)
            else:
                logger.error('{} {}: {}'.format(request_method, current_path,
                                                e.description))

            if isinstance(e, errors.ForbidOperation):
                e = http.error.Forbidden(e)

            if e.response and isinstance(e.response, http.JSONResponse):
                response = e.response
                response.status_code = e.code
            else:
                # It is important to do `str(e.description)`, because `e.description` might be an exception
                response = http.JSONResponse({'error': str(e.description)},
                                             e.code)

            return response

        except UserWarning as e:
            logger.warn('{} {}: {}'.format(request_method, current_path, e))
            return http.JSONResponse({'warning': str(e)}, 200)

        except Exception as e:
            logger.error('{} {}: {}'.format(request_method, current_path, e),
                         exc_info=e)
            return http.JSONResponse({'error': str(e)}, 500)
예제 #15
0
파일: _api.py 프로젝트: pytsite/plugin-form
def dispense(request: _http.Request, uid: str) -> _form.Form:
    """Dispense a form
    """
    try:
        # Determine form's class
        cid = uid.replace('cid:', '') if uid.startswith(
            'cid:') else _cache.get_pool('form.form_cid').get(uid)
        cls = _util.get_module_attr(cid)

        # Prevent instantiating other classes via HTTP API
        if not issubclass(cls, _form.Form):
            raise RuntimeError('Form class is not found')

        # Instantiate form
        return cls(request) if uid.startswith('cid:') else cls(request,
                                                               _uid=uid)

    except _cache.error.KeyNotExist:
        raise RuntimeError('Invalid form UID')

    # Hide all other exceptions info from outer world
    except Exception as e:
        _logger.error(e)
        raise RuntimeError('Unexpected form exception')
예제 #16
0
def _entity_save(args: dict):
    """Save an entity
    """
    fields_data = args['fields_data']
    collection = mongodb.get_collection(args['collection_name'])

    # Save data to the database
    try:
        # New entity
        if args['is_new']:
            collection.insert_one(fields_data)

        # Existing entity
        else:
            collection.replace_one({'_id': fields_data['_id']}, fields_data)

        # Update cache
        c_key = '{}.{}'.format(fields_data['_model'], fields_data['_id'])
        _ENTITIES_CACHE.put_hash(c_key, fields_data, _CACHE_TTL)

    except (bson_errors.BSONError, PyMongoError) as e:
        logger.error(e)
        logger.error('Document dump: {}'.format(fields_data))
        raise e
예제 #17
0
def cron_1min():
    """pytsite.cron.1min
    """
    global _working

    if _working:
        _logger.warn('Content import is still working')
        return

    _working = True

    max_errors = _reg.get('content_import.max_errors', 13)
    max_items = _reg.get('content_import.max_items', 10)
    delay_errors = _reg.get('content_import.delay_errors', 120)

    importer_finder = _odm.find('content_import') \
        .eq('enabled', True) \
        .lt('paused_till', _datetime.now()) \
        .sort([('errors', _odm.I_ASC)])

    for importer in importer_finder.get():  # type: _model.ContentImport
        options = dict(importer.driver_opts)
        options.update({
            'content_author': importer.content_author,
            'content_model': importer.content_model,
            'content_language': importer.content_language,
            'content_status': importer.content_status,
            'content_section': importer.content_section,
        })

        driver = _api.get_driver(importer.driver)
        items_imported = 0
        try:
            _logger.info('Content import started. Driver: {}. Options: {}'.format(driver.get_name(), options))

            # Get entities from driver and save them
            for entity in driver.get_entities(_frozendict(options)):
                if items_imported == max_items:
                    break

                try:
                    # Append additional tags
                    if entity.has_field('tags'):
                        for tag_title in importer.add_tags:
                            tag = _tag.find_by_title(tag_title, language=importer.content_language)
                            if not tag:
                                tag = _tag.dispense(tag_title, language=importer.content_language).save()
                            entity.f_add('tags', tag)

                    # Save entity
                    entity.save()

                    # Notify listeners
                    _events.fire('content_import@import', driver=driver, entity=entity)

                    _logger.info("Content entity imported: '{}'".format(entity.f_get('title')))
                    items_imported += 1

                # Entity was not successfully saved; make record in the log and skip to the next entity
                except Exception as e:
                    # Delete already attached images to free space
                    if entity.has_field('images') and entity.images:
                        for img in entity.images:
                            img.delete()

                    _logger.error("Error while creating entity '{}'. {}".format(entity.title, str(e)), exc_info=e)

            # Mark that driver made its work without errors
            importer.f_set('errors', 0)

            _logger.info('Content import finished. Entities imported: {}.'.format(items_imported))

        except Exception as e:
            # Increment errors counter
            importer.f_inc('errors')

            # Store info about error
            importer.f_set('last_error', str(e))

            if importer.errors >= max_errors:
                # Disable if maximum errors count reached
                importer.f_set('enabled', False)
            else:
                # Pause importer
                importer.f_set('paused_till', _datetime.now() + _timedelta(minutes=delay_errors))

            _logger.error(e)

            # Continue to the next importer
            continue

        finally:
            importer.save()

    _working = False
예제 #18
0
파일: _eh.py 프로젝트: pytsite/pytsite
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)