def _resolve_user( allow_system: bool, allow_anonymous: bool, disallowed_users: List[auth.AbstractUser], value: Union[auth.AbstractUser, str, DBRef]) -> Optional[auth.AbstractUser]: """Helper """ if isinstance(value, auth.AbstractUser): user = value elif isinstance(value, str): user = auth.get_user(uid=value) elif isinstance(value, DBRef): user = auth.get_user(uid=value.id) else: raise TypeError("User object, str or DB ref expected, got {}".format( type(value))) if user.is_anonymous and not allow_anonymous: raise ValueError('Anonymous user is not allowed here') if user.is_system and not allow_system: raise ValueError('System user is not allowed here') for u in disallowed_users: # type: auth.model.AbstractUser if u.uid == user.uid: raise ValueError("User '{}' is not allowed here".format( user.login)) return user
def _on_submit(self): e_type = self.attr('e_type') eids = self.attr('eids', []) try: for eid in eids: if e_type == 'role': auth.get_role(uid=eid).delete() elif e_type == 'user': auth.get_user(uid=eid).delete() except errors.ForbidDeletion as e: router.session().add_error_message(str(e)) return
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')
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
def sign_in(self, data: dict) -> AbstractUser: """Authenticate an existing user """ oauth_code = data.get('code') if not oauth_code: raise auth.error.AuthenticationError('No oAuth code') oauth_token = _api.get_access_token(oauth_code, current_url(True), data.get('state')) info = _api.get_user_info(oauth_token['access_token'], oauth_token['user_id']) email = info['email'].lower() if not email: raise auth.error.AuthenticationError('Service returned no email') user = auth.get_user(email) if not user: user = auth.create_user(email) opts = dict(user.options) opts.update({ 'id_gov_ua': info, }) user.set_field('options', opts) user.set_field('first_name', info['givenname'].title()) user.set_field('middle_name', info['middlename'].title()) user.set_field('last_name', info['lastname'].title()) user.set_field('phone', info['phone']) return user.save()
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 exec(self) -> dict: try: user = auth.get_user(uid=self.arg('uid')) jsonable = user.as_jsonable() events.fire('auth_http_api@get_user', user=user, json=jsonable) return jsonable except auth.error.UserNotFound: raise self.not_found()
def set_val(self, value): if isinstance(value, auth.model.AbstractUser): value = value.uid elif isinstance(value, str): value = value.strip() value = auth.get_user(uid=value).uid if value else None elif value is not None: raise TypeError('User object, str or None expected, not {}'.format( repr(value))) return super().set_val(value)
def _on_validate(self): """Hook """ errors = {} try: auth.get_user(self.val('login')) errors['login'] = lang.t('auth_ui_password@login_already_taken') except auth.error.UserNotFound: pass if self.val('password') != self.val('password_confirm'): err_msg = lang.t('auth_ui_password@passwords_not_match') errors.update({ 'password': err_msg, 'password_confirm': err_msg, }) if errors: raise form.FormValidationError(errors)
def exec(self) -> str: try: self.args['form'] = _api.user_form( self.request, auth.get_user(nickname=self.arg('nickname')).uid) except auth.error.UserNotFound: raise self.not_found() metatag.t_set('title', lang.t('auth_ui@profile_edit_title')) try: return router.call('auth_ui_user_profile_modify', self.args) except routing.error.RuleNotFound: return tpl.render('auth_ui/user-profile-modify', self.args)
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 _sanitize_nickname(self, s: str) -> str: """Generate unique nickname. """ cnt = 0 s = util.transform_str_2(s[:32], lang.get_current()) nickname = s while True: try: user = auth.get_user(nickname=nickname) # If nickname of THIS user was not changed if user.nickname == self.f_get('nickname'): return s except auth.error.UserNotFound: return nickname cnt += 1 nickname = s + '-' + str(cnt)
def http_api_pre_request(): access_token = None auth_header = router.request().headers.get('Authorization', '').split(' ') if len(auth_header) == 2 and auth_header[0].lower() == 'token': access_token = auth_header[1].strip() if not access_token: return try: # Authorize user by access token auth.switch_user(auth.get_user(access_token=access_token)) auth.prolong_access_token(access_token) except (auth.error.InvalidAccessToken, auth.error.UserNotFound, auth.error.AuthenticationError) as e: raise http.error.Forbidden( response=http.JSONResponse({'error': str(e)}))
def _on_setup_form(self): user_uid = self.attr('user_uid') if not user_uid: raise ValueError("Form's attribute 'user_uid' was not provided") c_user = auth.get_current_user() # Only profile owners and admins can modify profiles if user_uid != '0': user = auth.get_user(uid=self.attr('user_uid')) if not (c_user.is_admin or c_user == user): raise errors.ForbidOperation() # Only admins can create new users elif not c_user.is_admin: raise errors.ForbidOperation() self.name = 'auth_ui_user' self.css += ' auth-ui-form-user' self.area_footer_css += ' text-center'
def exec(self): try: user = auth.get_user(uid=self.arg('uid')) except auth.error.UserNotFound: raise self.not_found() current_user = auth.get_current_user() if current_user.is_anonymous or not (current_user == user or current_user.is_admin): raise self.forbidden() skip = self.arg('skip', 0) count = self.arg('count', 10) users = [ u.as_jsonable() for u in user.get_field('blocked_users', skip=skip, count=count) ] remains = user.blocked_users_count - (skip + count) return {'result': users, 'remains': remains if remains > 0 else 0}
def _on_submit(self): user_uid = self.attr('user_uid') c_user = auth.get_current_user() if user_uid == '0': user = auth.create_user(self.val('login'), self.val('password')) else: user = auth.get_user(uid=user_uid) for k, v in self.values.items(): if not user.has_field(k): continue if k in ('login', 'status', 'roles') and not c_user.is_admin: continue user.set_field(k, v) user.save() if not self.redirect: self.redirect = router.rule_url('auth_ui@user_profile_view', {'nickname': user.nickname})
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) -> list: uids = self.arg('uids') exclude = self.arg('exclude') search = self.arg('search') or self.arg('q') r = [] if uids: for uid in self.arg('uids'): try: user = auth.get_user(uid=uid) json = user.as_jsonable() events.fire('auth_http_api@get_user', user=user, json=json) r.append(json) except Exception as e: # Any exception is ignored due to safety reasons logger.warn(e) elif search and reg.get('auth_http_api.search', False): q = query.Query() q.add( query.Or([ query.Regex('first_name', '^{}'.format(search), True), query.Regex('last_name', '^{}'.format(search), True), ])) if not auth.get_current_user().is_admin: q.add(query.Eq('is_public', True)) if exclude: q.add(query.Nin('uid', exclude)) for user in auth.find_users(q, limit=self.arg('limit'), skip=self.arg('skip')): r.append(user.as_jsonable()) return r
def exec(self) -> str: try: user = auth.get_user(nickname=self.arg('nickname')) except auth.error.UserNotFound: raise self.not_found() if not user.is_active: raise self.not_found() c_user = auth.get_current_user() if not user.is_public and not (c_user == user or c_user.is_admin): raise self.not_found() self.args['user'] = user metatag.t_set( 'title', lang.t('auth_ui@profile_view_title', {'name': user.first_last_name})) try: return router.call('auth_ui_user_profile_view', self.args) except routing.error.RuleNotFound: return tpl.render('auth_ui/user-profile-view', self.args)
def sign_in(self, data: dict) -> auth.model.AbstractUser: """Authenticate user """ login = data.get('login') password = data.get('password') if not (login and password): raise auth.error.AuthenticationError( 'Login or password is not specified') # Check if the user exists user = auth.get_user(login) if not user: logger.warn("User with login '{}' is not found".format(login)) raise auth.error.AuthenticationError() # Check password if not auth.verify_password(password, user.password): logger.warn( "Incorrect password provided for user with login '{}'".format( login)) raise auth.error.AuthenticationError() return user
def exec(self): """Execute teh command """ model = self.arg(0) # Checking if the content model registered if not _api.is_model_registered(model): raise console.error.CommandExecutionError("'{}' is not a registered content model".format(model)) author_login = self.opt('author') num = self.opt('num') images_num = self.opt('images') language = self.opt('lang') no_html = self.opt('no-html') short = self.opt('short') title_len = self.opt('title-len') description_len = self.opt('description-len') if no_html: self.lorem_txt_args['format'] = 'text' if short: self.lorem_txt_args['paras'] = 1 users = list(auth.find_users(query.Query(query.Eq('status', 'active')), limit=10)) # Generate content entities for m in range(0, num): entity = _api.dispense(model) # Author if entity.has_field('author'): if author_login: author = auth.get_user(author_login) if not author: raise console.error.CommandExecutionError("'{}' is not a registered user".format(author_login)) else: if not users: raise console.error.CommandExecutionError(lang.t('content@no_users_found')) rand = randint(0, len(users) - 1) author = users[rand:rand + 1][0] entity.f_set('author', author.uid) # Title if entity.has_field('title'): entity.f_set('title', self._generate_title(title_len)) # Description if entity.has_field('description'): entity.f_set('description', self._generate_title(description_len)) # Body if entity.has_field('body'): body = [] for n in range(1, (images_num or 1) + 1): body.append(requests.get(self.lorem_txt_url, self.lorem_txt_args).content.decode('utf-8')) if not no_html and n > 1: body.append('\n<p>[img:{}]</p>\n'.format(n)) entity.f_set('body', ''.join(body)) # Images if entity.has_field('images') and images_num: for n in range(0, images_num): entity.f_add('images', file.create(self.lorem_img_url.format(randint(0, 1000)))) # Language if entity.has_field('language'): entity.f_set('language', language) # Status if entity.has_field('status'): entity.f_set('status', CONTENT_STATUS_PUBLISHED) events.fire('content@generate', entity=entity) entity.save() console.print_info(lang.t('content@new_content_created', {'model': entity.model, 'title': entity.title}))
def _on_setup_widgets(self): user_uid = self.attr('user_uid') user = auth.get_user(uid=user_uid) if user_uid != '0' else None c_user = auth.get_current_user() row_1 = self.add_widget(widget.container.Card( uid='row_1', header=self.t('registration_info'), body_css='row', )) row_1_left = row_1.append_child(widget.container.Container( uid='row_1_left', css='col-xs-12 col-12 col-sm-4 col-md-2', )) row_1_center = row_1.append_child(widget.container.Container( uid='row_1_center', css='col-xs-12 col-12 col-sm-4 col-md-5', )) row_1_right = row_1.append_child(widget.container.Container( uid='row_1_right', css='col-xs-12 col-12 col-sm-4 col-md-5', )) # Picture row_1_left.append_child(file_ui.widget.ImagesUpload( uid='picture', value=user.picture if user else None, max_file_size=3, label=self.t('photo'), )) # Login row_1_center.append_child(widget.input.Email( uid='login', value=user.login if user else None, label=self.t('email'), required=True, enabled=c_user.is_admin, max_length=auth.LOGIN_MAX_LENGTH, )) self.add_rule('login', auth.validation.AuthEntityFieldUnique( e_type='user', field_name='login', exclude_uids=user.uid if user else None, )) # Nickname row_1_center.append_child(widget.input.Text( uid='nickname', value=user.nickname if user else None, label=self.t('nickname'), required=True, max_length=auth.NICKNAME_MAX_LENGTH, )) self.add_rules('nickname', ( auth.user_nickname_rule, auth.validation.AuthEntityFieldUnique( e_type='user', field_name='nickname', exclude_uids=user.uid if user else None, ) )) # Birth date row_1_center.append_child(widget.select.DateTime( uid='birth_date', value=user.birth_date if user else None, label=self.t('birth_date'), timepicker=False, )) # Gender row_1_center.append_child(widget.select.Select( uid='gender', value=user.gender if user else None, label=self.t('gender'), items=[ ('m', self.t('male')), ('f', self.t('female')), ] )) # First name row_1_right.append_child(widget.input.Text( uid='first_name', value=user.first_name if user else None, label=self.t('first_name'), required=True, max_length=auth.FIRST_NAME_MAX_LENGTH, )) # Middle name row_1_right.append_child(widget.input.Text( uid='middle_name', value=user.middle_name if user else None, label=self.t('middle_name'), max_length=auth.MIDDLE_NAME_MAX_LENGTH, )) # Last name row_1_right.append_child(widget.input.Text( uid='last_name', value=user.last_name if user else None, label=self.t('last_name'), max_length=auth.LAST_NAME_MAX_LENGTH, )) # Position row_1_right.append_child(widget.input.Text( uid='position', value=user.position if user else None, label=self.t('position'), max_length=auth.USER_POSITION_MAX_LENGTH, )) # Row 2 row_2 = self.add_widget(widget.container.Container( uid='row_2', body_css='row', )) # Row 2 left row_2_left = row_2.append_child(widget.container.Container( uid='row_2_left', css='col-xs-12 col-12 col-sm-6 col-lg-8', )) # Contact info contact = row_2_left.append_child(widget.container.Card( uid='contact', body_css='row', header=self.t('contact_info'), )) # Contact info left contact_left = contact.append_child(widget.container.Container( uid='contact_left', css='col-xs-12 col-12 col-lg-6' )) # Country contact_left.append_child(widget.input.Text( uid='country', value=user.country if user else None, label=self.t('country'), max_length=auth.COUNTRY_MAX_LENGTH, )) # Province contact_left.append_child(widget.input.Text( uid='province', value=user.province if user else None, label=self.t('province'), max_length=auth.PROVINCE_MAX_LENGTH, )) # City contact_left.append_child(widget.input.Text( uid='city', value=user.city if user else None, label=self.t('city'), max_length=auth.CITY_MAX_LENGTH, )) # District contact_left.append_child(widget.input.Text( uid='district', value=user.district if user else None, label=self.t('district'), max_length=auth.DISTRICT_MAX_LENGTH, )) # Contact info right contact_right = contact.append_child(widget.container.Container( uid='contact_right', css='col-xs-12 col-12 col-lg-6' )) # Street contact_right.append_child(widget.input.Text( uid='street', value=user.street if user else None, label=self.t('street'), max_length=auth.STREET_MAX_LENGTH, )) # House number contact_right.append_child(widget.input.Text( uid='building', value=user.building if user else None, label=self.t('building'), max_length=auth.BUILDING_MAX_LENGTH, )) # Apt number contact_right.append_child(widget.input.Text( uid='apt_number', value=user.apt_number if user else None, label=self.t('apt_number'), max_length=auth.APT_NUMBER_MAX_LENGTH, )) # Phone contact_right.append_child(widget.input.Text( uid='phone', value=user.phone if user else None, label=self.t('phone'), max_length=auth.PHONE_MAX_LENGTH, )) # URLs contact.append_child(widget.input.StringList( uid='urls', value=user.urls if user else None, label=self.t('social_links'), max_rows=10, add_btn_label=self.t('add_link'), css='col-xs-12 col-12', )) self.add_rule('urls', validation.rule.Url()) # Row 2 right row_2_right = row_2.append_child(widget.container.Container( uid='row_2_right', css='col-xs-12 col-12 col-sm-6 col-lg-4', )) # Cover picture card cover_picture_card = row_2_right.append_child(widget.container.Card( uid='cover_picture_card', header=self.t('cover_picture'), )) # Cover picture cover_picture_card.append_child(file_ui.widget.ImagesUpload( uid='cover_picture', thumb_width=1200, thumb_height=450, max_file_size=5, value=user.cover_picture if user else None, )) # Security card security = row_2_right.append_child(widget.container.Card( uid='security', header=self.t('security'), )) # User account confirmed if c_user.is_admin and auth.is_sign_up_confirmation_required(): security.append_child(widget.select.Checkbox( uid='is_confirmed', value=user.is_confirmed if (user and user.is_confirmed) else None, label=self.t('user_account_is_confirmed'), )) # Profile is public security.append_child(widget.select.Checkbox( uid='is_public', value=user.is_public if user else None, label=self.t('this_is_public_profile'), )) # New password security.append_child(widget.input.Password( uid='password', label=self.t('new_password'), autocomplete='new-password', )) # New password confirm security.append_child(widget.input.Password( uid='password_confirm', label=self.t('new_password_confirmation'), autocomplete='new-password', )) # Row 3 row_3 = self.add_widget(widget.container.Card( uid='row_3', header=self.t('about_yourself'), )) # Description row_3.append_child(widget.input.TextArea( uid='description', value=user.description if user else '', max_length=auth.USER_DESCRIPTION_MAX_LENGTH, )) # Row 4 if c_user.is_admin: admin = self.add_widget(widget.container.Card( uid='admin', header=self.t('administration'), body_css='row', )) admin.append_child(widget.select.Select( uid='status', value=user.status if user else auth.get_new_user_status(), label=self.t('status'), items=auth.get_user_statuses(), required=True, append_none_item=False, css='col-xs-12 col-12 col-md-3' )) admin.append_child(_widget.RolesCheckboxes( uid='roles', value=user.roles if user else [auth.get_role(r) for r in auth.get_new_user_roles()], label=self.t('roles'), css='col-xs-12 col-12 col-md-3' )) # "Cancel" button self.add_widget(widget.button.Link( uid='action_cancel', weight=100, form_area='footer', icon='fa fas fa-fw fa-ban', value=self.t('cancel'), href=self.referer or self.redirect or router.base_url(), ))
def get_val(self, **kwargs) -> auth.model.AbstractUser: value = super().get_val(**kwargs) if value: value = auth.get_user(uid=value) return value
def _on_get(self, value: List[str], **kwargs) -> List[auth.AbstractUser]: """Hook """ return [auth.get_user(uid=uid) for uid in value]
def _on_get(self, value: Dict[str, str], **kwargs) -> Dict[Any, auth.AbstractUser]: """Hook """ return {k: auth.get_user(uid=v) for k, v in value.items()}
def _on_get(self, value: dict, **kwargs) -> Dict[auth.AbstractUser, Any]: return {auth.get_user(uid=k): v for k, v in value.items()}
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
def exec(self): # Delayed import to prevent circular dependency from . import _api # Checking if the model is registered model = self.arg('model') if not _api.is_model_registered(model): raise self.not_found() # Getting finder f = _api.find(model) # Breadcrumb breadcrumb = widget.select.Breadcrumb('content-index-breadcrumb') breadcrumb.append_item(lang.t('content@home_page'), router.base_url()) # Filter by term term_field_name = self.arg('term_field') term_alias = self.arg('term_alias') term = None if term_field_name and f.mock.has_field(term_field_name): term_field = f.mock.get_field( term_field_name) # type: odm.field.Ref if term_alias and term_field.model: for term_model in term_field.model: term = taxonomy.find(term_model).eq('alias', term_alias).first() if term: self.args['term'] = term if isinstance(f.mock.fields[term_field_name], odm.field.Ref): f.eq(term_field_name, term) elif isinstance(f.mock.fields[term_field_name], odm.field.RefsList): f.inc(term_field_name, term) metatag.t_set('title', term.title) breadcrumb.append_item(term.title) else: raise self.not_found() else: raise self.not_found() # Filter by author author_nickname = self.arg('author') if author_nickname: try: author = auth.get_user(nickname=author_nickname) f.eq('author', author.uid) self.args['author'] = author metatag.t_set( 'title', lang.t('content@articles_of_author', {'name': author.first_last_name})) if term: breadcrumb.pop_item() breadcrumb.append_item( term.title, router.rule_url( 'content@index', { 'model': model, 'term_field': term_field_name, 'term_alias': term_alias, })) breadcrumb.append_item(author.first_last_name) except auth.error.UserNotFound: raise self.not_found() self.args.update({ 'finder': f, 'breadcrumb': breadcrumb, }) try: # Call a controller provided by application return router.call('content_index', self.args) except routing.error.RuleNotFound: # Render a template provided by application return tpl.render('content/index', self.args)