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'))
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'), })
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'))
def exec(self) -> dict: if not _auth.get_current_user().has_role(['admin', 'dev']): raise self.forbidden() _reload.reload() return {'status': True}
def __init__(self, model: str, **kwargs): """Init """ if not model: raise RuntimeError('No model specified') if not odm_auth.check_model_permissions(model, [ PERM_CREATE, PERM_MODIFY, PERM_DELETE, PERM_MODIFY_OWN, PERM_DELETE_OWN ]): raise errors.ForbidOperation( "Current user is not allowed to browse '{}' entities".format( model)) # Model self._model = model # Model class self._model_class = _api.get_model_class(self._model) self._current_user = auth.get_current_user() self._browse_rule = kwargs.get('browse_rule', self._model_class.odm_ui_browse_rule()) self._m_form_rule = kwargs.get('m_form_rule', self._model_class.odm_ui_m_form_rule()) self._d_form_rule = kwargs.get('d_form_rule', self._model_class.odm_ui_d_form_rule()) # Widget widget_class = self._model_class.odm_ui_browser_widget_class() if not (issubclass(widget_class, widget.misc.DataTable)): raise TypeError('Subclass of {} expected, got'.format( widget.misc.DataTable, widget_class)) self._widget = widget_class(uid='odm-ui-browser-' + model, rows_url=http_api.url( 'odm_ui@get_browser_rows', { 'model': self._model, 'browse_rule': self._browse_rule, 'm_form_rule': self._m_form_rule, 'd_form_rule': self._d_form_rule, }), update_rows_url=http_api.url( 'odm_ui@put_browser_rows', {'model': model})) # Call model's class to perform setup tasks _api.dispense_entity(self._model).odm_ui_browser_setup(self) # Notify external events listeners events.fire('odm_ui@browser_setup.{}'.format(self._model), browser=self) # Check if the model specified data fields if not self.data_fields: raise RuntimeError('No data fields was defined') # Actions column if self._model_class.odm_ui_entity_actions_enabled() and \ (self._model_class.odm_ui_modification_allowed() or self._model_class.odm_ui_deletion_allowed()): self.insert_data_field('entity-actions', 'odm_ui@actions', False)
def exec(self): if auth.get_current_user().is_anonymous: raise self.forbidden() if not self.request.files: raise RuntimeError('No files received') r = [] for field_name, f in self.request.files.items(): tmp_file_path = util.mk_tmp_file()[1] f.save(tmp_file_path) f = file.create(tmp_file_path, f.filename, 'Uploaded via HTTP API') unlink(tmp_file_path) r.append({ 'uid': str(f.uid), }) # Request was from CKEditor if self.arg('CKEditor') and self.arg('CKEditorFuncNum'): script = 'window.parent.CKEDITOR.tools.callFunction("{}", "{}", "");' \ .format(self.arg('CKEditorFuncNum'), file.get(r[0]['uid']).get_url()) # CKEditor requires such response format r = http.Response( '<script type="text/javascript">{}</script>'.format(script), mimetype='text/html') return r
def _format_option_text(user: auth.AbstractUser) -> str: r = user.first_last_name if auth.get_current_user().is_admin: r += ' ({})'.format(user.login) return r
def odm_auth_check_entity_permissions( self, perm: Union[str, List[str]], user: auth.AbstractUser = None) -> bool: """Check if the user can perform operation against entity """ # Current user is default user = user or auth.get_current_user() # Check for model-wide permission if self.odm_auth_check_model_permissions(self.model, perm, user): return True # Search for at least one permission in list of permissions if isinstance(perm, (list, tuple)): for p in perm: if self.odm_auth_check_entity_permissions(p, user): return True # Check for exact permission elif self.has_field('author') and self.f_get('author') == user: if perm.endswith('_own'): raise ValueError( "Permissions that ends with '_own' must not be checked directly by this method" ) perm_name = f'odm_auth@{perm}_own.{self.model}' if permissions.is_permission_defined( perm_name) and user.has_permission(perm_name): return True # No permission found return False
def exec(self): if not auth.get_current_user().is_admin: raise self.forbidden() _api.uninstall(self.arg('package_name')) return {'status': True}
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'))
def odm_auth_check_model_permissions( cls, model: str, perm: Union[str, List[str]], user: auth.AbstractUser = None) -> bool: """Check if the user can perform operation against ANY entity of model """ # Current user is default user = user or auth.get_current_user() # Admins have any permission if user.is_admin: return True # Search for at least one permission in list of permissions if isinstance(perm, (list, tuple)): for p in perm: if cls.odm_auth_check_model_permissions(model, p, user): return True # Check for exact permission else: perm_name = f'odm_auth@{perm}.{model}' if permissions.is_permission_defined( perm_name) and user.has_permission(perm_name): return True # No permission found return False
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')}
def exec(self) -> dict: user = auth.get_current_user() if not user.is_anonymous: self.args['uid'] = user.uid return http_api.call('auth_http_api@get_user_followers', self.args) else: raise self.forbidden()
def exec(self) -> dict: current_user = auth.get_current_user() try: user = auth.get_user(uid=self.arg('uid')) except auth.error.UserNotFound: raise self.not_found() if user != current_user and not (current_user.is_admin or user.is_public): raise self.forbidden() skip = self.arg('skip', 0) count = self.arg('count', 10) if self.arg('_pytsite_http_api_rule_name' ) == 'auth_http_api@get_user_follows': users = [ u.as_jsonable() for u in user.get_field('follows', skip=skip, count=count) ] remains = user.follows_count - (skip + count) return {'result': users, 'remains': remains if remains > 0 else 0} elif self.arg('_pytsite_http_api_rule_name' ) == 'auth_http_api@get_user_followers': users = [ u.as_jsonable() for u in user.get_field('followers', skip=skip, count=count) ] remains = user.followers_count - (skip + count) return {'result': users, 'remains': remains if remains > 0 else 0} else: raise self.not_found()
def get_permissions(user: auth.model.AbstractUser = None, driver_name: str = None) -> dict: """Get permissions definition for user """ if not user: user = auth.get_current_user() return get_driver(driver_name).get_permissions(user)
def exec(self) -> dict: if not _auth.get_current_user().has_permission('plugman_ui@manage'): raise self.forbidden() _plugman.install(self.arg('name')) _reload.reload() return {'status': True}
def exec(self) -> dict: if auth.get_current_user().is_anonymous: raise self.forbidden() try: return file.get(self.arg('uid')).as_jsonable(**self.args) except file.error.FileNotFound as e: raise self.not_found(str(e))
def router_dispatch(): """'pytsite.router.dispatch' event handler. """ try: _metatag.t_set('fb:app_id', _api.get_app_id()) except (_error.AppIdNotSet, _error.AppSecretNotSet): if _auth.get_current_user().is_dev: _router.session().add_warning_message( _lang.t('facebook@plugin_setup_required_warning'))
def _on_setup_form(self): if not self.attr('role_uid'): raise RuntimeError("Form's attribute 'role_uid' was not provided") if not auth.get_current_user().is_admin: raise errors.ForbidOperation() self.name = 'auth_ui_role' self.css += ' auth-ui-form-role'
def exec(self) -> dict: if not _auth.get_current_user().has_permission('plugman_ui@manage'): raise self.forbidden() plugin_name = self.arg('name') _plugman.install(plugin_name) _reload.reload() return _plugman.local_plugin_info(plugin_name, False)
def router_dispatch(): """'pytsite.router.dispatch' handler. """ counter_id = _reg.get('yandex_metrika.counter_id') if not counter_id and _auth.get_current_user().has_role('dev'): _router.session().add_warning_message( _lang.t('yandex_metrika@plugin_setup_required_warning')) else: _assetman.add_inline_js( _tpl.render('yandex_metrika@counter', {'counter_id': counter_id}))
def router_dispatch(): """'pytsite.router.dispatch' handler. """ t_id = _reg.get('google_analytics.tracking_id') if not t_id and _auth.get_current_user().has_role('dev'): _router.session().add_warning_message( _lang.t('google_analytics@plugin_setup_required_warning')) else: _assetman.inline_js( _tpl.render('google_analytics@counter', {'tracking_id': t_id}))
def _get_element(self, **kwargs) -> htmler.Element: value = self.get_val(**kwargs) if value: text = value.first_last_name if auth.get_current_user().is_admin: text += ' ({})'.format(value.login) self._items.append([value.uid, text]) return super()._get_element(**kwargs)
def router_dispatch(): """pytsite.router.dispatch """ try: client_id = auth_google.get_client_id() metatag.t_set('google-signin-client_id', client_id) metatag.t_set('pytsite-auth-google-client-id', client_id) except auth_google.error.ClientIdNotDefined: if auth.get_current_user().has_role('dev'): router.session().add_warning_message(lang.t('auth_ui_google@plugin_setup_required_warning'))
def exec(self) -> dict: try: auth.sign_out(auth.get_current_user()) if 'access_token' in self.args: auth.revoke_access_token(self.arg('access_token')) return {'status': True} except (auth.error.UserNotFound, auth.error.InvalidAccessToken) as e: raise self.forbidden(e)
def exec(self): # 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: auth.sign_up(self.arg('driver'), self.args) except auth.error.SignupDisabled as e: raise self.forbidden(e) return {'status': True}
def odm_ui_browser_setup(self, browser: odm_ui.Browser): """Hook """ super().odm_ui_browser_setup(browser) # Section if self.has_field('section'): browser.insert_data_field('section', 'article@section') # Starred if self.has_field('starred') and auth.get_current_user().has_permission('article@set_starred.' + browser.model): browser.insert_data_field('starred', 'article@starred')
def _content_notify_author_status_change(self): """Notify content author about status change by another user """ if auth.get_current_user() == self.author: return m_subject = lang.t('content@content_status_change_mail_subject') m_body = tpl.render('content@mail/{}/content-status-change'.format(lang.get_current()), { 'entity': self, 'status': self.t('content_status_{}_{}'.format(self.model, self.status)), }) mail.Message(self.author.login, m_subject, m_body).send()
def before(self) -> Optional[http.RedirectResponse]: if not auth.get_current_user().is_anonymous: return # Redirecting to the authorization endpoint inp = self.request.inp.copy() inp.update({ 'driver': _api.get_driver().name, '__redirect': util.escape_html(router.current_url(True)), }) return self.redirect(router.rule_url('auth_ui@sign_in', inp))
def odm_ui_m_form_setup_widgets(self, frm: form.Form): """Hook """ super().odm_ui_m_form_setup_widgets(frm) if self.has_field('route_alias') and auth.get_current_user().is_admin: # Route alias frm.add_widget(widget.input.Text( uid='route_alias', label=self.t('path'), value=self.route_alias.alias if self.route_alias else '', ))