def create_comment( self, thread_uid: str, body: str, author: auth.model.AbstractUser, status: str = 'published', parent_uid: str = None) -> comments.model.AbstractComment: """Create a new comment """ body = body.strip() comment = odm.dispense('comment') # type: _model.ODMComment comment.f_set('thread_uid', thread_uid) comment.f_set('body', body) comment.f_set('author', author.uid) comment.f_set('status', status) comment.save() if parent_uid: parent = odm.get_by_ref('comment:' + parent_uid) if parent.depth == comments.get_comment_max_depth(): raise RuntimeError('Comment depth is too big') try: auth.switch_user_to_system() parent.append_child(comment).save() finally: auth.restore_user() return _model.Comment(comment)
def sign_up(self, data: dict) -> auth.model.AbstractUser: """Sign up a new user """ # Create user try: auth.switch_user_to_system() user = auth.create_user(data.get('login'), data.get('password')) # Fill additional fields for k, v in data.items(): if k not in ('email', 'first_name', 'last_name', 'nickname') or not v: continue user.set_field(k, v) # Set nickname if 'nickname' not in data: user.nickname = user.first_last_name user.save() finally: auth.restore_user() return user
def _on_pre_delete(self, **kwargs): """Hook """ super()._on_pre_delete(**kwargs) # Delete linkes, bookmarks, etc try: auth.switch_user_to_system() flag.delete_all(self) finally: auth.restore_user()
def on_content_view(entity: ContentWithURL): if entity.has_field('comments_count') and entity.has_field( 'route_alias') and entity.route_alias: # Update entity's comments count try: auth.switch_user_to_system() cnt = comments.get_all_comments_count(entity.route_alias.alias) entity.f_set('comments_count', cnt).save(fast=True) return cnt finally: auth.restore_user()
def exec(self) -> int: entity = _api.dispense(self.arg('model'), self.arg('uid')) if entity and entity.has_field('views_count'): try: auth.switch_user_to_system() entity.f_inc('views_count').save(fast=True) finally: auth.restore_user() return entity.f_get('views_count') return 0
def on_flag_toggle(flg: flag.Flag): if not isinstance(flg.entity, Content): return f_name = '{}_count'.format(lang.english_plural(flg.variant)) if flg.entity.has_field(f_name): try: auth.switch_user_to_system() flg.entity.f_set(f_name, flag.count(flg.entity, flg.variant)).save(fast=True) finally: auth.restore_user()
def exec(self) -> dict: # Is current user authorized current_user = auth.get_current_user() if current_user.is_anonymous: raise self.forbidden() # Load user to unblock try: user = auth.get_user(uid=self.arg('uid')) auth.switch_user_to_system() current_user.remove_blocked_user(user).save() except auth.error.UserNotFound: raise self.not_found() finally: auth.restore_user() return {'status': True}
def _on_after_save(self, first_save: bool = False, **kwargs): """Hook """ from . import _api # Recalculate tags weights if first_save and self.has_field('tags'): for t in self.tags: weight = 0 for model in _api.get_models().keys(): try: weight += _api.find(model, language=self.language).inc('tags', [t]).count() except odm.error.FieldNotDefined: pass try: auth.switch_user_to_system() t.f_set('weight', weight).save(fast=True) finally: auth.restore_user() # Update localization entities references # For each language except current one for lng in lang.langs(False): # Get localization ref for lng localization = self.f_get('localization_' + lng) # If localization is set if isinstance(localization, Content): # If localized entity hasn't reference to this entity, set it if localization.f_get('localization_' + self.language) != self: localization.f_set('localization_' + self.language, self).save() # If localization is not set elif localization is None: # Clear references from localized entities f = _api.find(self.model, language=lng).eq('localization_' + self.language, self) for referenced in f.get(): referenced.f_set('localization_' + self.language, None).save() # Notify content status change if self.has_field('status') and self.has_field('prev_status') and self.status != self.prev_status: self.content_on_status_change() events.fire('*****@*****.**', entity=self) events.fire('content@entity.{}.save'.format(self.model), entity=self)
def f_get(self, field_name: str, **kwargs): """Get field's value """ if not self.is_new and field_name == 'author': try: return super().f_get(field_name, **kwargs) # Owner was deleted or for some reason cannot be accessed except auth.error.UserNotFound: try: # Set first admin as owner auth.switch_user_to_system() self.f_set(field_name, auth.get_admin_user()).save() finally: auth.restore_user() return super().f_get(field_name, **kwargs) return super().f_get(field_name, **kwargs)
def _on_f_get(self, field_name: str, value, **kwargs): if field_name == 'picture': if not self.get_field('picture').get_val() and \ not (self.is_new or self.is_deleted or self.is_being_deleted): try: # Load user picture from Gravatar img_url = 'https://www.gravatar.com/avatar/' + util.md5_hex_digest( self.f_get('login')) + '?s=512' img = file.create(img_url) auth.switch_user_to_system() self.f_set('picture', img).save() value = img finally: auth.restore_user() elif field_name == 'is_confirmed': value = not self.f_get('confirmation_hash') return value
def _on_after_delete(self, **kwargs): """Hook """ super()._on_after_delete() # Delete comments try: auth.switch_user_to_system() comments.delete_thread(self.route_alias.alias) except (NotImplementedError, comments.error.NoDriversRegistered): pass finally: auth.restore_user() # Delete linked route alias try: self.route_alias.delete() except odm.error.EntityDeleted: # Entity was deleted by another instance pass
def _on_submit(self): """Hook """ try: token = self.attr('token') user = auth.get_user(_RESET_TOKENS_POOL.get(token)) auth.switch_user_to_system() user.password = self.val('password') user.save() auth.restore_user() _RESET_TOKENS_POOL.rm(token) router.session().add_success_message( lang.t('auth_ui_password@reset_password_success')) self.redirect = router.rule_url('auth_ui@sign_in', {'driver': 'password'}) except auth.error.UserNotFound: raise RuntimeError('Invalid token')
def exec(self): try: # Search for user user = next( auth.find_users( query.Query(query.Eq('confirmation_hash', self.arg('code'))))) except StopIteration: # No user found, redirect to sign in URL return self.redirect(_api.sign_in_url(redirect=router.base_url())) try: auth.switch_user_to_system() user.confirmation_hash = None if user.status == auth.USER_STATUS_WAITING: user.status = auth.get_new_user_status() user.save() finally: auth.restore_user() router.session().add_success_message( lang.t('auth_ui@registration_confirm_success')) return self.redirect(_api.sign_in_url(redirect=router.base_url()))
def sign_up(self, data: dict) -> _auth.model.AbstractUser: # Searching for token in input data token = data.get('token') if not token: for k, v in data.items(): if k.endswith('token'): token = v break if not token: raise ValueError('No uLogin token received') # Getting user's data from uLogin response = _urlopen( 'http://ulogin.ru/token.php?token={}&host={}'.format( token, _router.request().host)) if response.status != 200: raise _auth.error.AuthenticationError( "Bad response status code from uLogin: {}.".format( response.status)) ulogin_data = _json.loads(response.read().decode('utf-8')) if 'error' in ulogin_data: raise _auth.error.AuthenticationError( "Bad response from uLogin: '******'.".format(ulogin_data['error'])) if 'email' not in ulogin_data or ulogin_data['verified_email'] != '1': raise _auth.error.AuthenticationError( "Email '{}' is not verified by uLogin.".format( ulogin_data['email'])) email = ulogin_data['email'] try: user = _auth.get_user(email) is_new_user = False except _auth.error.UserNotFound: # User is not exists and its creation is not allowed if not _auth.is_sign_up_enabled(): raise _auth.error.AuthenticationError( _lang.t('auth_ui_ulogin@signup_is_disabled')) else: # New users can be created only by system user _auth.switch_user_to_system() # Create new user user = _auth.create_user(email) is_new_user = True # As soon as user created or loaded, set it as current _auth.switch_user(user) # Picture if is_new_user: current_pic = user.picture picture_url = ulogin_data.get('photo_big') if not picture_url: picture_url = ulogin_data.get('photo') # Replace existing picture with provided by uLogin if picture_url: user.picture = _file.create(picture_url) current_pic.delete() # Name if not user.first_name: user.first_name = ulogin_data.get('first_name') if not user.last_name: user.last_name = ulogin_data.get('last_name') # Alter nickname if is_new_user: user.nickname = user.first_last_name # Gender if user.gender not in ('m', 'f') and 'sex' in ulogin_data: user.gender = 'f' if int(ulogin_data['sex']) == 1 else 'm' # Birth date if 'bdate' in ulogin_data: try: b_date = _strptime(ulogin_data['bdate'], '%d.%m.%Y') user.birth_date = _datetime(*b_date[0:5]) except ValueError: # Yes, sometimes uLogin provides strange data here :( pass # Link to profile if 'profile' in ulogin_data and ulogin_data['profile']: user.urls = user.urls + (ulogin_data['profile'], ) # Options options = dict(user.options) options['ulogin'] = ulogin_data user.options = options user.save() return user