def _create_user(self, form, handler): data = form.data existing_user_id = session.get('register_pending_user') if existing_user_id: # Get pending user and set it as non-pending user = User.get(existing_user_id) user.is_pending = False else: user = User(first_name=data['first_name'], last_name=data['last_name'], email=data['email'], address=data.get('address', ''), phone=data.get('phone', ''), affiliation=data['affiliation']) identity = handler.create_identity(data) user.identities.add(identity) user.secondary_emails = handler.extra_emails - {user.email} user.favorite_users.add(user) db.session.add(user) minfo = HelperMaKaCInfo.getMaKaCInfoInstance() timezone = session.timezone if timezone == 'LOCAL': timezone = minfo.getTimezone() user.settings.set('timezone', timezone) user.settings.set('lang', session.lang or minfo.getLang()) handler.update_user(user, form) db.session.flush() login_user(user, identity) msg = _('You have sucessfully registered your Indico profile. ' 'Check <a href="{url}">your profile</a> for further details and settings.') flash(Markup(msg).format(url=url_for('users.user_profile')), 'success') return handler.redirect_success()
def _getAnswer(self): for fossil in self._userList: user = User.get(int(fossil['id'])) if user is not None: user.is_admin = True admins = User.find(is_admin=True, is_deleted=False).order_by(User.first_name, User.last_name).all() return fossilize([u.as_avatar for u in admins])
def _process(self): source = User.get_one(request.args['source']) target = User.get_one(request.args['target']) problems = [] if source == target: problems.append((_("Users are the same!"), 'error')) if (source.first_name.strip().lower() != target.first_name.strip().lower() or source.last_name.strip().lower() != target.last_name.strip().lower()): problems.append((_("Users' names seem to be different!"), 'warning')) if source.is_pending: problems.append((_("Source user has never logged in to Indico!"), 'warning')) if target.is_pending: problems.append((_("Target user has never logged in to Indico!"), 'warning')) if source.is_deleted: problems.append((_("Source user has been deleted!"), 'error')) if target.is_deleted: problems.append((_("Target user has been deleted!"), 'error')) return jsonify({ 'problems': problems })
def _original_user(self): # A proper user, with an id that can be mapped directly to sqlalchemy if isinstance(self.id, int) or self.id.isdigit(): return User.get(int(self.id)) # A user who had no real indico account but an ldap identifier/email. # In this case we try to find his real user and replace the ID of this object # with that user's ID. data = self.id.split(':') # TODO: Once everything is in SQLAlchemy this whole thing needs to go away! user = None if data[0] == 'LDAP': identifier = data[1] email = data[2] # You better have only one ldap provider or at least different identifiers ;) identity = Identity.find_first(Identity.provider != 'indico', Identity.identifier == identifier) if identity: user = identity.user elif data[0] == 'Nice': email = data[1] else: return None if not user: user = User.find_first(User.all_emails.contains(email)) if user: self._old_id = self.id self.id = str(user.id) logger.info("Updated legacy user id (%s => %s)", self._old_id, self.id) return user
def rb_merge_users(new_id, old_id): """Updates RB data after an Avatar merge :param new_id: Target user :param old_id: Source user (being deleted in the merge) """ from indico.modules.rb import settings as rb_settings from indico.modules.rb.models.blocking_principals import BlockingPrincipal from indico.modules.rb.models.blockings import Blocking from indico.modules.rb.models.reservations import Reservation from indico.modules.rb.models.rooms import Room old_user = User.get(int(old_id)) new_user = User.get(int(new_id)) for bp in BlockingPrincipal.find(): if bp.principal == old_user: bp.principal = new_user Blocking.find(created_by_id=old_id).update({'created_by_id': new_id}) Reservation.find(created_by_id=old_id).update({'created_by_id': new_id}) Reservation.find(booked_for_id=old_id).update({'booked_for_id': new_id}) Room.find(owner_id=old_id).update({'owner_id': new_id}) for key in ('authorized_principals', 'admin_principals'): principals = rb_settings.get(key) principals = principals_merge_users(principals, new_id, old_id) rb_settings.set(key, principals)
def test_deletion_no_primary_email(): # this tests setting the is_deleted property on a user with no primary email # very unlikely case but let's make sure we never try to set the deleted # flag on a None primary email. user = User() assert user.email is None user.is_deleted = True
def test_can_be_modified(): user = User() # user can modify himself assert user.can_be_modified(user) # admin can modify anyone assert user.can_be_modified(User(is_admin=True)) # normal users can't assert not user.can_be_modified(User())
def test_get_full_name_empty_names(first_name, last_name): user = User(first_name=first_name, last_name=last_name, title=UserTitle.none) for last_name_first, last_name_upper, abbrev_first_name in itertools.product((True, False), repeat=3): # Just make sure it doesn't fail. We don't really care about the output. # It's only allowed for pending users so in most cases it only shows up # in the ``repr`` of such a user. user.get_full_name(last_name_first=last_name_first, last_name_upper=last_name_upper, abbrev_first_name=abbrev_first_name)
def principal_from_fossil(fossil, allow_pending=False, allow_groups=True, legacy=True, allow_missing_groups=False, allow_emails=False, allow_networks=False): from indico.modules.networks.models.networks import IPNetworkGroup from indico.modules.groups import GroupProxy from indico.modules.users import User type_ = fossil['_type'] id_ = fossil['id'] if type_ == 'Avatar': if isinstance(id_, int) or id_.isdigit(): # regular user user = User.get(int(id_)) elif allow_pending: data = GenericCache('pending_identities').get(id_) if not data: raise ValueError("Cannot find user '{}' in cache".format(id_)) data = {k: '' if v is None else v for (k, v) in data.items()} email = data['email'].lower() # check if there is not already a (pending) user with that e-mail # we need to check for non-pending users too since the search may # show a user from external results even though the email belongs # to an indico account in case some of the search criteria did not # match the indico account user = User.find_first(User.all_emails.contains(email), ~User.is_deleted) if not user: user = User(first_name=data.get('first_name') or '', last_name=data.get('last_name') or '', email=email, address=data.get('address', ''), phone=data.get('phone', ''), affiliation=data.get('affiliation', ''), is_pending=True) db.session.add(user) db.session.flush() else: raise ValueError("Id '{}' is not a number and allow_pending=False".format(id_)) if user is None: raise ValueError('User does not exist: {}'.format(id_)) return user.as_avatar if legacy else user elif allow_emails and type_ == 'Email': return EmailPrincipal(id_) elif allow_networks and type_ == 'IPNetworkGroup': group = IPNetworkGroup.get(int(id_)) if group is None: raise ValueError('IP network group does not exist: {}'.format(id_)) return group elif allow_groups and type_ in {'LocalGroupWrapper', 'LocalGroup'}: group = GroupProxy(int(id_)) if group.group is None: raise ValueError('Local group does not exist: {}'.format(id_)) return group.as_legacy_group if legacy else group elif allow_groups and type_ in {'LDAPGroupWrapper', 'MultipassGroup'}: provider = fossil['provider'] group = GroupProxy(id_, provider) if group.group is None and not allow_missing_groups: raise ValueError('Multipass group does not exist: {}:{}'.format(provider, id_)) return group.as_legacy_group if legacy else group else: raise ValueError('Unexpected fossil type: {}'.format(type_))
def test_deletion(db): user = User(first_name='Guinea', last_name='Pig', email='*****@*****.**', secondary_emails=['[email protected]']) db.session.add(user) db.session.flush() assert not user.is_deleted assert all(not ue.is_user_deleted for ue in user._all_emails) user.is_deleted = True db.session.flush() assert all(ue.is_user_deleted for ue in user._all_emails)
def test_title(db): user = User(first_name='Guinea', last_name='Pig') db.session.add(user) db.session.flush() assert user.title == '' user.title = UserTitle.prof assert user.title == UserTitle.prof.title assert is_lazy_string(user.title) assert User.find_one(title=UserTitle.prof) == user
def test_emails(db): user = User(first_name='Guinea', last_name='Pig') db.session.add(user) db.session.flush() assert user.email is None assert not user.secondary_emails user.email = '*****@*****.**' db.session.flush() assert user.all_emails == {'*****@*****.**'} user.secondary_emails.add('*****@*****.**') db.session.flush() assert user.all_emails == {'*****@*****.**', '*****@*****.**'}
def test_emails(db): user = User(first_name='Guinea', last_name='Pig') db.session.add(user) db.session.flush() assert user.email is None assert not user.secondary_emails user.email = '*****@*****.**' db.session.flush() assert user.all_emails == {'*****@*****.**'} user.secondary_emails.add('*****@*****.**') db.session.flush() db.session.expire(user) # all_emails is only updated after expire (or commit) assert user.all_emails == {'*****@*****.**', '*****@*****.**'}
def test_get_full_name(last_name_first, last_name_upper, abbrev_first_name, expected): user = User(first_name='Guinea', last_name='Pig', title=UserTitle.none) name = user.get_full_name(last_name_first=last_name_first, last_name_upper=last_name_upper, abbrev_first_name=abbrev_first_name, show_title=False) assert name == expected # titled name with no title is the same titled_name = user.get_full_name(last_name_first=last_name_first, last_name_upper=last_name_upper, abbrev_first_name=abbrev_first_name, show_title=True) assert titled_name == expected # titled name with a non-empty title user.title = UserTitle.mr titled_name = user.get_full_name(last_name_first=last_name_first, last_name_upper=last_name_upper, abbrev_first_name=abbrev_first_name, show_title=True) assert titled_name == 'Mr. {}'.format(expected)
def principal_from_fossil(fossil, allow_pending=False, allow_groups=True, legacy=True, allow_missing_groups=False, allow_emails=False): """Gets a GroupWrapper or AvatarUserWrapper from a fossil""" from indico.modules.groups import GroupProxy from indico.modules.users import User type_ = fossil['_type'] id_ = fossil['id'] if type_ == 'Avatar': if isinstance(id_, int) or id_.isdigit(): # regular user user = User.get(int(id_)) elif allow_pending: data = GenericCache('pending_identities').get(id_) if not data: raise ValueError("Cannot find user '{}' in cache".format(id_)) data = {k: '' if v is None else v for (k, v) in data.items()} email = data['email'].lower() # check if there is not already a pending user with that e-mail user = User.find_first(email=email, is_pending=True) if not user: user = User(first_name=data.get('first_name') or '', last_name=data.get('last_name') or '', email=email, address=data.get('address', ''), phone=data.get('phone', ''), affiliation=data.get('affiliation', ''), is_pending=True) db.session.add(user) db.session.flush() else: raise ValueError("Id '{}' is not a number and allow_pending=False".format(id_)) if user is None: raise ValueError('User does not exist: {}'.format(id_)) return user.as_avatar if legacy else user elif allow_emails and type_ == 'Email': return EmailPrincipal(id_) elif allow_groups and type_ in {'LocalGroupWrapper', 'LocalGroup'}: group = GroupProxy(int(id_)) if group.group is None: raise ValueError('Local group does not exist: {}'.format(id_)) return group.as_legacy_group if legacy else group elif allow_groups and type_ in {'LDAPGroupWrapper', 'MultipassGroup'}: provider = fossil['provider'] group = GroupProxy(id_, provider) if group.group is None and not allow_missing_groups: raise ValueError('Multipass group does not exist: {}:{}'.format(provider, id_)) return group.as_legacy_group if legacy else group else: raise ValueError('Unexpected fossil type: {}'.format(type_))
def migrate_event_notes(self): self.print_step('migrating event notes') janitor_user = User.get_one(self.janitor_user_id) self.print_msg('Using janitor user {}'.format(janitor_user), always=True) for event, obj, minutes, special_prot in committing_iterator(self._iter_minutes()): if special_prot: self.print_warning( cformat('%{yellow!}{} minutes have special permissions; skipping them').format(obj), event_id=event.id ) continue path = get_archived_file(minutes, self.archive_dirs)[1] if path is None: self.print_error(cformat('%{red!}{} minutes not found on disk; skipping them').format(obj), event_id=event.id) continue with open(path, 'r') as f: data = convert_to_unicode(f.read()).strip() if not data: self.print_warning(cformat('%{yellow}{} minutes are empty; skipping them').format(obj), always=False, event_id=event.id) continue note = EventNote(linked_object=obj) note.create_revision(RenderMode.html, data, janitor_user) db.session.add(note) if not self.quiet: self.print_success(cformat('%{cyan}{}').format(obj), event_id=event.id)
def migrate_groups(self): print cformat('%{white!}migrating groups') for old_group in committing_iterator(self.zodb_root['groups'].itervalues()): if old_group.__class__.__name__ != 'Group': continue group = LocalGroup(id=int(old_group.id), name=convert_to_unicode(old_group.name).strip()) print cformat('%{green}+++%{reset} %{white!}{:6d}%{reset} %{cyan}{}%{reset}').format(group.id, group.name) members = set() for old_member in old_group.members: if old_member.__class__.__name__ != 'Avatar': print cformat('%{yellow!}!!! Unsupported group member type: {}').format( old_member.__class__.__name__) continue user = User.get(int(old_member.id)) if user is None: print cformat('%{yellow!}!!! User not found: {}').format(old_member.id) continue while user.merged_into_user: user = user.merged_into_user if user.is_deleted: print cformat('%{yellow!}!!! User deleted: {}').format(user.id) continue members.add(user) for member in sorted(members, key=attrgetter('full_name')): print cformat('%{blue!}<->%{reset} %{white!}{:6d} %{yellow}{} ({})').format( member.id, member.full_name, member.email) group.members = members db.session.add(group)
def retrieve_principal(principal, allow_groups=True, legacy=True): """Retrieves principal object from a `(type, id)` tuple. Valid principal types are 'Avatar', 'User' and 'Group'. :param principal: The principal (a tuple/list) :param allow_groups: If group principals are allowed :param legacy: If legacy wrappers or new objects should be returned. """ from indico.modules.groups import GroupProxy from indico.modules.groups.legacy import LocalGroupWrapper, LDAPGroupWrapper from indico.modules.users import User type_, id_ = principal if type_ in {'Avatar', 'User'}: user = User.get(int(id_)) if not user: return None return user.as_avatar if legacy else user elif type_ == 'Group' and allow_groups: if isinstance(id_, (int, basestring)): # legacy group group = LocalGroupWrapper(id_) if unicode(id_).isdigit() else LDAPGroupWrapper(id_) return group if legacy else group.group else: # new group provider, name_or_id = id_ group = GroupProxy(name_or_id, provider) return group.as_legacy_group if legacy else group else: raise ValueError('Unexpected type: {}'.format(type_))
def getVars( self ): vars = wcomponents.WTemplated.getVars( self ) minfo = info.HelperMaKaCInfo.getMaKaCInfoInstance() vars["title"] = minfo.getTitle() vars["organisation"] = minfo.getOrganisation() vars['supportEmail'] = Config.getInstance().getSupportEmail() vars['publicSupportEmail'] = Config.getInstance().getPublicSupportEmail() vars['noReplyEmail'] = Config.getInstance().getNoReplyEmail() vars["lang"] = minfo.getLang() vars["address"] = "" if minfo.getCity() != "": vars["address"] = minfo.getCity() if minfo.getCountry() != "": if vars["address"] != "": vars["address"] = "%s (%s)"%(vars["address"], minfo.getCountry()) else: vars["address"] = "%s"%minfo.getCountry() vars["timezone"] = Config.getInstance().getDefaultTimezone() vars["systemIconAdmins"] = Config.getInstance().getSystemIconURL( "admin" ) iconDisabled = str(Config.getInstance().getSystemIconURL( "disabledSection" )) iconEnabled = str(Config.getInstance().getSystemIconURL( "enabledSection" )) url = urlHandlers.UHAdminSwitchNewsActive.getURL() icon = iconEnabled if minfo.isNewsActive() else iconDisabled vars["features"] = i18nformat("""<a href="%s"><img src="%s" border="0" style="float:left; padding-right: 5px">_("News Pages")</a>""") % (url, icon) vars["administrators"] = fossilize(sorted([u.as_avatar for u in User.find(is_admin=True, is_deleted=False)], key=methodcaller('getStraightFullName'))) return vars
def _process(self): if session.user: return redirect(url_for('misc.index')) handler = MultipassRegistrationHandler(self) if self.identity_info else LocalRegistrationHandler(self) verified_email = self._get_verified_email() if verified_email is not None: handler.email_verified(verified_email) flash(_('You have successfully validated your email address and can now proceeed with the registration.'), 'success') return redirect(url_for('.register', provider=self.provider_name)) form = handler.create_form() # Check for pending users if we have verified emails pending = None if not handler.must_verify_email: pending = User.find_first(~User.is_deleted, User.is_pending, User.all_emails.contains(db.func.any(list(handler.get_all_emails(form))))) if form.validate_on_submit(): if handler.must_verify_email: return self._send_confirmation(form.email.data) else: return self._create_user(form, handler, pending) elif not form.is_submitted() and pending: # If we have a pending user, populate empty fields with data from that user for field in form: value = getattr(pending, field.short_name, '') if value and not field.data: field.data = value if pending: flash(_("There is already some information in Indico that concerns you. " "We are going to link it automatically."), 'info') return WPAuth.render_template('register.html', form=form, local=(not self.identity_info), must_verify_email=handler.must_verify_email, widget_attrs=handler.widget_attrs, email_sent=session.pop('register_verification_email_sent', False))
def _getNavigationDrawer(self): if "user_id" in request.view_args: user = User.get(request.view_args["user_id"]) profile_breadcrumb = _("Profile of {name}").format(name=user.full_name) else: profile_breadcrumb = _("My Profile") return WSimpleNavigationDrawer(profile_breadcrumb)
def category_cleanup(): cfg = Config.getInstance() janitor_user = User.get_one(cfg.getJanitorUserId()) logger.debug("Checking whether any categories should be cleaned up") for categ_id, days in cfg.getCategoryCleanup().iteritems(): try: category = CategoryManager().getById(categ_id) except KeyError: logger.warning("Category {} does not exist!".format(categ_id)) continue now = now_utc() to_delete = [ev for ev in category.conferences if (now - ev._creationDS) > timedelta(days=days)] if not to_delete: continue logger.info("Category {}: {} events were created more than {} days ago and will be deleted".format( categ_id, len(to_delete), days )) for i, event in enumerate(to_delete, 1): logger.info("Deleting {}".format(event)) event.delete(user=janitor_user) if i % 100 == 0: db.session.commit() DBMgr.getInstance().commit() db.session.commit() DBMgr.getInstance().commit()
def _process(self): form = SearchForm(obj=FormDefaults(exact=True)) form_data = form.data search_results = None num_of_users = User.query.count() num_deleted_users = User.find(is_deleted=True).count() if form.validate_on_submit(): search_results = [] exact = form_data.pop('exact') include_deleted = form_data.pop('include_deleted') include_pending = form_data.pop('include_pending') external = form_data.pop('external') form_data = {k: v for (k, v) in form_data.iteritems() if v and v.strip()} matches = search_users(exact=exact, include_deleted=include_deleted, include_pending=include_pending, external=external, **form_data) for entry in matches: if isinstance(entry, User): search_results.append(UserEntry( profile_url=url_for('.user_profile', entry), **{k: getattr(entry, k) for k in IDENTITY_ATTRIBUTES} )) else: search_results.append(UserEntry( profile_url=None, full_name="{first_name} {last_name}".format(**entry.data.to_dict()), **{k: entry.data.get(k) for k in (IDENTITY_ATTRIBUTES - {'full_name'})} )) search_results.sort(key=attrgetter('first_name', 'last_name')) num_reg_requests = RegistrationRequest.query.count() return WPUsersAdmin.render_template('users_admin.html', form=form, search_results=search_results, num_of_users=num_of_users, num_deleted_users=num_deleted_users, num_reg_requests=num_reg_requests)
def get_user_by_email(email, create_pending=False): """finds a user based on his email address. :param email: The email address of the user. :param create_pending: If True, this function searches for external users and creates a new pending User in case no existing user was found. :return: A :class:`.User` instance or ``None`` if not exactly one user was found. """ email = email.lower().strip() if not email: return None if not create_pending: res = User.find_all(~User.is_deleted, User.all_emails.contains(email)) else: res = search_users(exact=True, include_pending=True, external=True, email=email) if len(res) != 1: return None user_or_identity = next(iter(res)) if isinstance(user_or_identity, User): return user_or_identity elif not create_pending: return None # Create a new pending user data = user_or_identity.data user = User(first_name=data.get('first_name') or '', last_name=data.get('last_name') or '', email=data['email'], address=data.get('address', ''), phone=data.get('phone', ''), affiliation=data.get('affiliation', ''), is_pending=True) db.session.add(user) db.session.flush() return user
def _getNavigationDrawer(self): if 'user_id' in request.view_args: user = User.get(request.view_args['user_id']) profile_breadcrumb = _('Profile of {name}').format(name=user.full_name) else: profile_breadcrumb = _('My Profile') return WSimpleNavigationDrawer(profile_breadcrumb)
def migrate(self): # disable onupdate for attachment lastmod timestamp # see https://bitbucket.org/zzzeek/sqlalchemy/issue/3471/ why it's needed Attachment.__table__.columns.modified_dt.onupdate = None janitor_user = User.get_one(self.janitor_user_id) self.print_msg('Using janitor user {}'.format(janitor_user), always=True) self.janitor_user_id = janitor_user.id self.todo = OrderedDict([ (AttachmentFolder, []), (AttachmentFolderPrincipal, []), (Attachment, []), (AttachmentPrincipal, []), (AttachmentFile, []), (LegacyAttachmentFolderMapping, []), (LegacyAttachmentMapping, []) ]) self.ids = { AttachmentFolder: _get_pg_id(AttachmentFolder.id), Attachment: _get_pg_id(Attachment.id), AttachmentFile: _get_pg_id(AttachmentFile.id), } with patch_default_group_provider(self.default_group_provider): self.migrate_category_attachments() self.migrate_event_attachments() self.fix_attachment_file_ids() self.print_step('fixing id sequences') self.fix_sequences('attachments') self.update_merged_ids()
def category_cleanup(): from indico.modules.events import Event cfg = Config.getInstance() janitor_user = User.get_one(cfg.getJanitorUserId()) logger.debug("Checking whether any categories should be cleaned up") for categ_id, days in cfg.getCategoryCleanup().iteritems(): try: category = Category.get(int(categ_id), is_deleted=False) except KeyError: logger.warning("Category %s does not exist!", categ_id) continue now = now_utc() to_delete = Event.query.with_parent(category).filter(Event.created_dt < (now - timedelta(days=days))).all() if not to_delete: continue logger.info("Category %s: %s events were created more than %s days ago and will be deleted", categ_id, len(to_delete), days) for i, event in enumerate(to_delete, 1): logger.info("Deleting %s", event) event.as_legacy.delete(user=janitor_user) if i % 100 == 0: db.session.commit() DBMgr.getInstance().commit() db.session.commit() DBMgr.getInstance().commit()
def getVars(self): wvars = wcomponents.WTemplated.getVars(self) minfo = info.HelperMaKaCInfo.getMaKaCInfoInstance() wvars['title'] = minfo.getTitle() wvars['organisation'] = minfo.getOrganisation() wvars['supportEmail'] = Config.getInstance().getSupportEmail() wvars['publicSupportEmail'] = Config.getInstance().getPublicSupportEmail() wvars['noReplyEmail'] = Config.getInstance().getNoReplyEmail() wvars['lang'] = Config.getInstance().getDefaultLocale() wvars['address'] = '' if minfo.getCity() != '': wvars['address'] = minfo.getCity() if minfo.getCountry() != '': if wvars['address'] != '': wvars['address'] = '{0} ({1})'.format(wvars['address'], minfo.getCountry()) else: wvars['address'] = minfo.getCountry() wvars['timezone'] = Config.getInstance().getDefaultTimezone() wvars['systemIconAdmins'] = Config.getInstance().getSystemIconURL('admin') wvars['administrators'] = fossilize(sorted([u.as_avatar for u in User.find(is_admin=True, is_deleted=False)], key=methodcaller('getStraightFullName'))) wvars['tracker_url'] = urljoin(Config.getInstance().getTrackerURL(), 'api/instance/{}'.format(cephalopod_settings.get('uuid'))) wvars['cephalopod_data'] = {'enabled': cephalopod_settings.get('joined'), 'contact': cephalopod_settings.get('contact_name'), 'email': cephalopod_settings.get('contact_email'), 'url': Config.getInstance().getBaseURL(), 'organisation': minfo.getOrganisation()} return wvars
def create(grant_admin): """Creates a new user""" user_type = 'user' if not grant_admin else 'admin' while True: email = prompt_email() if email is None: return email = email.lower() if not User.find(User.all_emails.contains(email), ~User.is_deleted, ~User.is_pending).count(): break print(cformat('%{red}Email already exists')) first_name = click.prompt("First name").strip() last_name = click.prompt("Last name").strip() affiliation = click.prompt("Affiliation", '').strip() print() while True: username = click.prompt("Enter username").lower().strip() if not Identity.find(provider='indico', identifier=username).count(): break print(cformat('%{red}Username already exists')) password = prompt_pass() if password is None: return identity = Identity(provider='indico', identifier=username, password=password) user = create_user(email, {'first_name': to_unicode(first_name), 'last_name': to_unicode(last_name), 'affiliation': to_unicode(affiliation)}, identity) user.is_admin = grant_admin _print_user_info(user) if click.confirm(cformat("%{yellow}Create the new {}?").format(user_type), default=True): db.session.add(user) db.session.commit() print(cformat("%{green}New {} created successfully with ID: %{green!}{}").format(user_type, user.id))
def _getParams(self): super(BookRoomHook, self)._getParams() self._fromDT = utc_to_server(self._fromDT.astimezone(pytz.utc)).replace(tzinfo=None) if self._fromDT else None self._toDT = utc_to_server(self._toDT.astimezone(pytz.utc)).replace(tzinfo=None) if self._toDT else None if not self._fromDT or not self._toDT or self._fromDT.date() != self._toDT.date(): raise HTTPAPIError('from/to must be on the same day') elif self._fromDT >= self._toDT: raise HTTPAPIError('to must be after from') elif self._fromDT < datetime.now(): raise HTTPAPIError('You cannot make bookings in the past') username = get_query_parameter(self._queryParams, 'username') if not username: raise HTTPAPIError('No username provided') users = User.find_all(~User.is_deleted, Identity.identifier == username) if not users: raise HTTPAPIError('Username does not exist') elif len(users) != 1: raise HTTPAPIError('Ambiguous username ({} users found)'.format(len(users))) user = users[0] self._params = { 'room_id': get_query_parameter(self._queryParams, 'roomid'), 'reason': get_query_parameter(self._queryParams, 'reason'), 'booked_for': user, 'from': self._fromDT, 'to': self._toDT } missing = [key for key, val in self._params.iteritems() if not val] if missing: raise HTTPAPIError('Required params missing: {}'.format(', '.join(missing))) self._room = Room.get(self._params['room_id']) if not self._room: raise HTTPAPIError('A room with this ID does not exist')
def user(self): from indico.modules.users import User return User.find_first(~User.is_deleted, User.all_emails.contains(self.email))
def _count_users(self): return User.find(is_deleted=False, is_pending=False).count()
def principal_from_fossil(fossil, allow_pending=False, allow_groups=True, allow_missing_groups=False, allow_emails=False, allow_networks=False, allow_registration_forms=False, existing_data=None, event=None, category=None): from indico.modules.categories.models.roles import CategoryRole from indico.modules.events.models.roles import EventRole from indico.modules.events.registration.models.forms import RegistrationForm from indico.modules.groups import GroupProxy from indico.modules.networks.models.networks import IPNetworkGroup from indico.modules.users import User if event and category is None: category = event.category if existing_data is None: existing_data = set() type_ = fossil['_type'] id_ = fossil['id'] if type_ == 'Avatar': if isinstance(id_, int) or id_.isdigit(): # regular user user = User.get(int(id_)) elif allow_pending: data = GenericCache('pending_identities').get(id_) if not data: raise ValueError(f"Cannot find user '{id_}' in cache") data = {k: '' if v is None else v for k, v in data.items()} email = data['email'].lower() # check if there is not already a (pending) user with that e-mail # we need to check for non-pending users too since the search may # show a user from external results even though the email belongs # to an indico account in case some of the search criteria did not # match the indico account user = User.query.filter(User.all_emails == email, ~User.is_deleted).first() if not user: user = User(first_name=data.get('first_name') or '', last_name=data.get('last_name') or '', email=email, address=data.get('address', ''), phone=data.get('phone', ''), affiliation=data.get('affiliation', ''), is_pending=True) db.session.add(user) db.session.flush() else: raise ValueError( f"Id '{id_}' is not a number and allow_pending=False") if user is None: raise ValueError(f'User does not exist: {id_}') return user elif allow_emails and type_ == 'Email': return EmailPrincipal(id_) elif allow_networks and type_ == 'IPNetworkGroup': group = IPNetworkGroup.get(int(id_)) if group is None or (group.hidden and group not in existing_data): raise ValueError(f'IP network group does not exist: {id_}') return group elif allow_groups and type_ in {'LocalGroupWrapper', 'LocalGroup'}: group = GroupProxy(int(id_)) if group.group is None: raise ValueError(f'Local group does not exist: {id_}') return group elif allow_groups and type_ in {'LDAPGroupWrapper', 'MultipassGroup'}: provider = fossil['provider'] group = GroupProxy(id_, provider) if group.group is None and not allow_missing_groups: raise ValueError( f'Multipass group does not exist: {provider}:{id_}') return group elif category and type_ == 'CategoryRole': role = CategoryRole.get_category_role_by_id(category, id_) role_name = fossil.get('name') if role is None: raise ValueError( f'Category role "{role_name}" is not available in "{category.title}"' ) return role elif event and type_ == 'EventRole': role = EventRole.get(id_) role_name = fossil.get('name') if role is None: raise ValueError(f'Event role "{role_name}" does not exist') if role.event != event: raise ValueError( f'Event role "{role_name}" does not belong to "{event.title}"') return role elif allow_registration_forms and type_ == 'RegistrationForm': registration_form = RegistrationForm.get(id_) reg_form_name = fossil.get('title') if registration_form is None: raise ValueError( f'Registration form "{reg_form_name}" does not exist') if registration_form.event != event: raise ValueError( f'Registration form "{reg_form_name}" does not belong to "{event.title}"' ) return registration_form else: raise ValueError(f'Unexpected fossil type: {type_}')
def _process(self): users = [User.get(int(id_)) for id_ in request.form.getlist('user_id')] self.user.favorite_users |= set(filter(None, users)) tpl = get_template_module('users/_favorites.html') return jsonify(success=True, users=[serialize_user(user) for user in users], html=tpl.favorite_users_list(self.user))
def created_by_user(self): return User.get(self.created_by_id).as_avatar
def getById(self, id): if isinstance(id, int) or id.isdigit(): user = User.get(int(id)) if user: return user.as_avatar
def get_admin_emails(): """Get the email addresses of all Indico admins""" return {u.email for u in User.find(is_admin=True, is_deleted=False)}
def _process_args(self): RHManageCategoryRole._process_args(self) self.user = User.get_or_404(request.view_args['user_id'])
def _event_deleted(event, **kwargs): user = session.user if has_request_context( ) and session.user else User.get(Config.getInstance().getJanitorUserId()) for event_vc_room in VCRoomEventAssociation.find_for_event( event, include_hidden=True, include_deleted=True): event_vc_room.delete(user)
def _process(self): user = User.get(int(request.view_args['fav_user_id'])) if user in self.user.favorite_users: self.user.favorite_users.remove(user) return jsonify(success=True)
def migrate(self): self.janitor_user = User.get_one(self.janitor_user_id) self.migrate_event_pr()
def _check_existing_email(form, field): if User.find_all(~User.is_deleted, ~User.is_pending, User.all_emails.contains(field.data)): raise ValidationError(_('This email address is already in use.'))
def _load_users(self, data): if not data['users']: return missing = {} for uuid, userdata in data['users'].iteritems(): if userdata is None: self.user_map[uuid] = self.system_user_id continue user = (User.query.filter( User.all_emails.in_(userdata['all_emails']), ~User.is_deleted).first()) if user is None: missing[uuid] = userdata else: self.user_map[uuid] = user.id if missing: click.secho( 'The following users from the import data could not be mapped to existing users:', fg='yellow') table_data = [['First Name', 'Last Name', 'Email', 'Affiliation']] for userdata in sorted(missing.itervalues(), key=itemgetter('first_name', 'last_name', 'email')): table_data.append([ userdata['first_name'], userdata['last_name'], userdata['email'], userdata['affiliation'] ]) table = AsciiTable(table_data) click.echo(table.table) if self.create_users is None: click.echo('Do you want to create these users now?') click.echo( 'If you choose to not create them, the behavior depends on where the user would be used:' ) click.echo( '- If the user is not required, it will be omitted.') click.echo( '- If a user is required but using the system user will not cause any problems or look ' 'weird, the system user will be used.') click.echo( '- In case neither is possible, e.g. in abstract reviews or ACLs, these objects will ' 'be skipped altogether!') create_users = click.confirm('Create the missing users?', default=True) else: create_users = self.create_users if create_users: click.secho('Creating missing users', fg='magenta') for uuid, userdata in missing.iteritems(): user = User(first_name=userdata['first_name'], last_name=userdata['last_name'], email=userdata['email'], secondary_emails=set(userdata['all_emails']) - {userdata['email']}, address=userdata['address'], phone=userdata['phone'], affiliation=userdata['affiliation'], title=userdata['title'], is_pending=True) db.session.add(user) db.session.flush() self.user_map[uuid] = user.id if self.verbose: click.echo( cformat("- %{cyan}User%{blue!} '{}' ({})").format( user.full_name, user.email)) else: click.secho('Skipping missing users', fg='magenta')
def _process_args(self): self.user = User.get_or_404( request.view_args['user_id'] ) if 'user_id' in request.view_args else None
def __init__(self, *args, **kwargs): self._set_config_options(**kwargs) self.system_user = User.get_system_user() super(CategoryImporter, self).__init__(*args, **kwargs) self.categ_id_counter = self.zodb_root['counters']['CATEGORY']._Counter__count
def create_mock_abstract(event): """Create a mock abstract that can be used in previews. Brace for geek references. """ User = namedtuple('Author', ['first_name', 'last_name', 'title', 'full_name']) Track = namedtuple('Track', ['title']) Session = namedtuple('Session', ['title']) ContributionType = namedtuple('ContributionType', ['name']) Contribution = namedtuple('Contribution', ['title', 'track', 'session', 'type', 'locator']) Abstract = namedtuple('Abstract', [ 'friendly_id', 'title', 'event', 'submitter', 'contribution', 'primary_authors', 'secondary_authors', 'locator', 'judgment_comment', 'accepted_track', 'accepted_contrib_type', 'state', 'merged_into' ]) englert = User(full_name="Fran\xe7ois Englert", first_name="Fran\xe7ois", last_name="Englert", title="Prof.") brout = User(full_name="Robert Brout", first_name="Robert", last_name="Brout", title="Prof.") guralnik = User(full_name="Gerald Guralnik", first_name="Gerald", last_name="Guralnik", title="Prof.") hagen = User(full_name="Carl Hagen", first_name="Carl", last_name="Hagen", title="Prof.") kibble = User(full_name="Tom Kibble", first_name="Tom", last_name="Kibble", title="Prof.") higgs = User(full_name="Peter Higgs", first_name="Peter", last_name="Higgs", title="Prof.") track = Track(title=_("Higgs Fields")) session = Session(title=_("Higgs Fields Posters")) contribution_type = ContributionType(name=_("Poster")) contribution = Contribution( title="Broken Symmetry and the Mass of Gauge Vector Mesons", track=track, session=session, type=contribution_type, locator={ 'confId': -314, 'contrib_id': 1234 }) target_abstract = Abstract( friendly_id=315, title="Broken Symmetry", accepted_track=track, accepted_contrib_type=contribution_type, event=event, submitter=brout, state=AbstractState.accepted, contribution=contribution, primary_authors=[englert, brout], secondary_authors=[guralnik, hagen, kibble, higgs], locator={ 'confId': -314, 'abstract_id': 1235 }, judgment_comment='Vague but interesting!', merged_into=None) abstract = Abstract( friendly_id=314, title="Broken Symmetry and the Mass of Gauge Vector Mesons", accepted_track=track, accepted_contrib_type=contribution_type, event=event, submitter=brout, state=AbstractState.accepted, contribution=contribution, primary_authors=[englert, brout], secondary_authors=[guralnik, hagen, kibble, higgs], locator={ 'confId': -314, 'abstract_id': 1234 }, judgment_comment='Vague but interesting!', merged_into=target_abstract) return abstract
def user(self): if not self.is_submitted() or not self.email.data: return None return User.find_first(~User.is_deleted, ~User.is_blocked, ~User.is_pending, User.all_emails.contains(self.email.data))
def principal_from_identifier(identifier, allow_groups=False, allow_external_users=False, allow_event_roles=False, allow_category_roles=False, allow_registration_forms=False, allow_emails=False, event_id=None, soft_fail=False): from indico.modules.categories.models.roles import CategoryRole from indico.modules.events.models.events import Event from indico.modules.events.models.roles import EventRole from indico.modules.events.registration.models.forms import RegistrationForm from indico.modules.groups import GroupProxy from indico.modules.users import User try: type_, data = identifier.split(':', 1) except ValueError: raise ValueError('Invalid data') if type_ == 'User': try: user_id = int(data) except ValueError: raise ValueError('Invalid data') user = User.get(user_id, is_deleted=(None if soft_fail else False)) if user is None: raise ValueError(f'Invalid user: {user_id}') return user elif type_ == 'ExternalUser': if not allow_external_users: raise ValueError('External users are not allowed') cache = GenericCache('external-user') external_user_data = cache.get(data) if not external_user_data: raise ValueError('Invalid data') user = User.query.filter( User.all_emails == external_user_data['email'], ~User.is_deleted).first() if user: return user # create a pending user. this user isn't sent to the DB unless it gets added # to the sqlalchemy session somehow (e.g. by adding it to an ACL). # like this processing form data does not result in something being stored in # the database, which is good! return User(first_name=external_user_data['first_name'], last_name=external_user_data['last_name'], email=external_user_data['email'], affiliation=external_user_data['affiliation'], address=external_user_data['address'], phone=external_user_data['phone'], is_pending=True) elif type_ == 'Group': if not allow_groups: raise ValueError('Groups are not allowed') try: provider, name = data.split(':', 1) except ValueError: raise ValueError('Invalid data') if not provider: # local group try: group_id = int(name) except ValueError: raise ValueError('Invalid data') group = GroupProxy(group_id) else: # multipass group group = GroupProxy(name, provider) if not soft_fail and group.group is None: raise ValueError(f'Invalid group: {data}') return group elif type_ == 'EventRole': if not allow_event_roles: raise ValueError('Event roles are not allowed') try: event_role_id = int(data) except ValueError: raise ValueError('Invalid data') event_role = EventRole.get(event_role_id) if event_role is None or event_role.event_id != event_id: raise ValueError(f'Invalid event role: {event_role_id}') return event_role elif type_ == 'CategoryRole': if not allow_category_roles: raise ValueError('Category roles are not allowed') event = Event.get(event_id) if event is None: raise ValueError(f'Invalid event id: {event_id}') try: category_role_id = int(data) except ValueError: raise ValueError('Invalid data') if soft_fail: category_role = CategoryRole.get(category_role_id) else: category_role = CategoryRole.get_category_role_by_id( event.category, category_role_id) if category_role is None: raise ValueError(f'Invalid category role: {category_role_id}') return category_role elif type_ == 'RegistrationForm': if not allow_registration_forms: raise ValueError('Registration forms are not allowed') try: reg_form_id = int(data) except ValueError: raise ValueError('Invalid data') registration_form = RegistrationForm.get( reg_form_id, is_deleted=(None if soft_fail else False)) if registration_form is None or registration_form.event_id != event_id: raise ValueError(f'Invalid registration form: {reg_form_id}') return registration_form elif type_ == 'Email': if not allow_emails: raise ValueError('Emails are not allowed') return EmailPrincipal(data) else: raise ValueError('Invalid data')
def has_data(self): return bool(User.find().count())
def test_full_name(): assert User(first_name='Guinea', last_name='Pig', title=UserTitle.prof).full_name == 'Guinea Pig'
def _event_deleted(event, **kwargs): user = session.user if has_request_context( ) and session.user else User.get_system_user() for event_vc_room in VCRoomEventAssociation.find_for_event( event, include_hidden=True, include_deleted=True): event_vc_room.delete(user)
def _process_args(self): RHManageEventRole._process_args(self) self.user = User.get_one(request.view_args['user_id'])
def _process_POST(self): if User.query.has_rows(): return redirect(url_for_index()) setup_form = BootstrapForm(request.form) if not setup_form.validate(): flash( _("Some fields are invalid. Please, correct them and submit the form again." ), 'error') return redirect(url_for('bootstrap.index')) # Creating new user user = User() user.first_name = to_unicode(setup_form.first_name.data) user.last_name = to_unicode(setup_form.last_name.data) user.affiliation = to_unicode(setup_form.affiliation.data) user.email = to_unicode(setup_form.email.data) user.is_admin = True identity = Identity(provider='indico', identifier=setup_form.username.data, password=setup_form.password.data) user.identities.add(identity) db.session.add(user) db.session.flush() user.settings.set('timezone', Config.getInstance().getDefaultTimezone()) user.settings.set( 'lang', session.lang or Config.getInstance().getDefaultLocale()) login_user(user, identity) full_name = user.full_name # needed after the session closes transaction.commit() # Configuring server's settings minfo = HelperMaKaCInfo.getMaKaCInfoInstance() minfo.setOrganisation(setup_form.affiliation.data) message = get_template_module( 'bootstrap/flash_messages.html').bootstrap_success(name=full_name) flash(Markup(message), 'success') # Activate instance tracking if setup_form.enable_tracking.data: contact_name = setup_form.contact_name.data contact_email = setup_form.contact_email.data try: register_instance(contact_name, contact_email) except (HTTPError, ValueError) as err: message = get_template_module( 'bootstrap/flash_messages.html').community_error(err=err) category = 'error' except Timeout: message = get_template_module( 'bootstrap/flash_messages.html').community_timeout() category = 'error' except RequestException as exc: message = get_template_module('bootstrap/flash_messages.html' ).community_exception(exc=exc) category = 'error' else: message = get_template_module( 'bootstrap/flash_messages.html').community_success() category = 'success' flash(Markup(message), category) return redirect(url_for_index())
def test_no_names(db, first_name, last_name): with pytest.raises(IntegrityError): db.session.add(User(first_name=first_name, last_name=last_name)) db.session.flush()
def principal_from_fossil(fossil, allow_pending=False, allow_groups=True, allow_missing_groups=False, allow_emails=False, allow_networks=False, existing_data=None, event=None): from indico.modules.networks.models.networks import IPNetworkGroup from indico.modules.events.models.roles import EventRole from indico.modules.groups import GroupProxy from indico.modules.users import User if existing_data is None: existing_data = set() type_ = fossil['_type'] id_ = fossil['id'] if type_ == 'Avatar': if isinstance(id_, int) or id_.isdigit(): # regular user user = User.get(int(id_)) elif allow_pending: data = GenericCache('pending_identities').get(id_) if not data: raise ValueError("Cannot find user '{}' in cache".format(id_)) data = {k: '' if v is None else v for k, v in data.items()} email = data['email'].lower() # check if there is not already a (pending) user with that e-mail # we need to check for non-pending users too since the search may # show a user from external results even though the email belongs # to an indico account in case some of the search criteria did not # match the indico account user = User.find_first(User.all_emails.contains(email), ~User.is_deleted) if not user: user = User(first_name=data.get('first_name') or '', last_name=data.get('last_name') or '', email=email, address=data.get('address', ''), phone=data.get('phone', ''), affiliation=data.get('affiliation', ''), is_pending=True) db.session.add(user) db.session.flush() else: raise ValueError( "Id '{}' is not a number and allow_pending=False".format(id_)) if user is None: raise ValueError('User does not exist: {}'.format(id_)) return user elif allow_emails and type_ == 'Email': return EmailPrincipal(id_) elif allow_networks and type_ == 'IPNetworkGroup': group = IPNetworkGroup.get(int(id_)) if group is None or (group.hidden and group not in existing_data): raise ValueError('IP network group does not exist: {}'.format(id_)) return group elif allow_groups and type_ in {'LocalGroupWrapper', 'LocalGroup'}: group = GroupProxy(int(id_)) if group.group is None: raise ValueError('Local group does not exist: {}'.format(id_)) return group elif allow_groups and type_ in {'LDAPGroupWrapper', 'MultipassGroup'}: provider = fossil['provider'] group = GroupProxy(id_, provider) if group.group is None and not allow_missing_groups: raise ValueError('Multipass group does not exist: {}:{}'.format( provider, id_)) return group elif event and type_ == 'EventRole': role = EventRole.get(id_) role_name = fossil.get('name') if role is None: raise ValueError('Role does not exist: {}:{}'.format( role_name, id_)) if role.event != event: raise ValueError( 'Role does not belong to provided event: {}:{} - {}'.format( role_name, id_, event)) return role else: raise ValueError('Unexpected fossil type: {}'.format(type_))
def test_no_names_pending(db): db.session.add(User(first_name='', last_name='', is_pending=True)) db.session.flush()
def _process(self): source = User.get_one(request.args['source']) target = User.get_one(request.args['target']) errors, warnings = _get_merge_problems(source, target) return jsonify(errors=errors, warnings=warnings)
def test_settings(): user = User(id=123) # make sure it's a bound settings proxy assert user.settings._bound_args == (user, )
def _process(self): self.group.members.discard(User.get(request.view_args['user_id'])) return jsonify(success=True)
def _process_args(self, undo, user_id): RHAdminBase._process_args(self) self.user = None if undo else User.get_or_404(user_id, is_deleted=False)