def user_create(grant_admin): """Creates new user""" update_session_options(db) 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 error('Email already exists') first_name = prompt("First name") last_name = prompt("Last name") affiliation = prompt("Affiliation", '') print() while True: username = prompt("Enter username").lower() if not Identity.find(provider='indico', identifier=username).count(): break error('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 prompt_bool(cformat("%{yellow}Create the new {}?").format(user_type), default=True): db.session.add(user) db.session.commit() success("New {} created successfully with ID: {}".format(user_type, user.id))
def sendAndLog(cls, notification, conference, module=None, user=None, skipQueue=False): if isinstance(notification, dict): # Wrap a raw dictionary in a notification class from MaKaC.webinterface.mail import GenericNotification notification = GenericNotification(notification) cls.send(notification, skipQueue=skipQueue) log_data = { u"content_type": to_unicode(notification.getContentType()), u"from": to_unicode(notification.getFromAddr()), u"to": map(to_unicode, notification.getToList()), u"cc": map(to_unicode, notification.getCCList()), u"bcc": map(to_unicode, notification.getBCCList()), u"subject": to_unicode(notification.getSubject()).strip(), u"body": to_unicode(notification.getBody()).strip(), } summary = u"Sent email: {}".format(log_data[u"subject"]) conference.log( EventLogRealm.emails, EventLogKind.other, to_unicode(module or u"Unknown"), summary, user, type_=u"email", data=log_data, )
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.query.filter(User.all_emails == email, ~User.is_deleted, ~User.is_pending).has_rows(): 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 user_create(grant_admin): """Creates new user""" user = User() user_type = 'user' if not grant_admin else 'admin' print() name = prompt("First name") surname = prompt("Last name") affiliation = prompt("Affiliation") print() username = prompt("Enter username") email = prompt_email() if email is None: return password = prompt_pass() if password is None: return user.first_name = to_unicode(name) user.last_name = to_unicode(surname) user.affiliation = to_unicode(affiliation) user.email = email user.is_admin = grant_admin print_user_info(user) if prompt_bool(cformat("%{yellow}Create the new {}?").format(user_type), default=True): # TODO: adapt to new authentication system, create local identity with username/password # user.identities.append(UserIdentity(..., identifier=username, password=password)) db.session.add(user) transaction.commit() success("New {} created successfully with ID: {}".format(user_type, user.id))
def serialize_event(cal, fossil, now, id_prefix="indico-event"): event = ical.Event() event.add('uid', '{}-{}@{}'.format(id_prefix, fossil['id'], url_parse(config.BASE_URL).host)) event.add('dtstamp', now) event.add('dtstart', _deserialize_date(fossil['startDate'])) event.add('dtend', _deserialize_date(fossil['endDate'])) event.add('url', fossil['url']) event.add('summary', to_unicode(fossil['title'])) loc = fossil['location'] or '' if loc: loc = to_unicode(loc) if fossil['roomFullname']: loc += ' ' + to_unicode(fossil['roomFullname']) event.add('location', loc) description = '' if fossil.get('speakers'): speakers = ('{} ({})'.format(speaker['fullName'].encode('utf-8'), speaker['affiliation'].encode('utf-8')) for speaker in fossil['speakers']) description += 'Speakers: {}\n'.format(', '.join(speakers)) if fossil['description']: desc_text = fossil['description'].strip() if not desc_text: desc_text = '<p/>' try: description += '{}\n\n{}'.format(to_unicode(html.fromstring(to_unicode(desc_text)) .text_content()).encode('utf-8'), fossil['url'].encode('utf-8')) except ParserError: # this happens e.g. if desc_text contains only a html comment description += fossil['url'].encode('utf-8') else: description += fossil['url'] event.add('description', description) cal.add_component(event)
def display(self, **params): from indico.modules.admin import RHAdminBase from indico.modules.core.settings import core_settings, social_settings title_parts = [self.title] if self.MANAGEMENT: title_parts.insert(0, _('Management')) elif isinstance(self._rh, RHAdminBase): title_parts.insert(0, _('Administration')) injected_bundles = values_from_signal(signals.plugin.inject_bundle.send(self.__class__), as_list=True, multi_value_types=list) custom_js = list(current_app.manifest['__custom.js']) custom_css = list(current_app.manifest['__custom.css']) css_files = map(self._fix_path, self.get_extra_css_files() + custom_css) js_files = map(self._fix_path, custom_js) body = to_unicode(self._display(params)) bundles = itertools.chain((current_app.manifest[x] for x in self._resolve_bundles() if x in current_app.manifest._entries), self.additional_bundles['screen'], injected_bundles) print_bundles = itertools.chain((current_app.manifest[x] for x in self.print_bundles), self.additional_bundles['print']) return render_template('indico_base.html', css_files=css_files, js_files=js_files, bundles=bundles, print_bundles=print_bundles, site_name=core_settings.get('site_title'), social=social_settings.get_all(), page_title=' - '.join(unicode(x) for x in title_parts if x), head_content=to_unicode(self._getHeadContent()), body=body)
def _process_POST(self): if User.has_rows(): return redirect(url_for('misc.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', to_unicode(setup_form.language.data)) 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) minfo.setLang(setup_form.language.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('misc.index'))
def display(self, **params): from indico.modules.admin import RHAdminBase from indico.modules.core.settings import core_settings, social_settings title_parts = [to_unicode(self._getTitle())] if self.MANAGEMENT: title_parts.append(_('Management area')) elif isinstance(self._rh, RHAdminBase): title_parts.append(_('Administration area')) plugin_css = values_from_signal(signals.plugin.inject_css.send(self.__class__), as_list=True, multi_value_types=list) plugin_js = values_from_signal(signals.plugin.inject_js.send(self.__class__), as_list=True, multi_value_types=list) custom_js = self._asset_env['custom_js'].urls() if 'custom_js' in self._asset_env else [] custom_css = self._asset_env['custom_sass'].urls() if 'custom_sass' in self._asset_env else [] css_files = map(self._fix_path, self.getCSSFiles() + plugin_css + self.get_extra_css_files() + custom_css) print_css_files = map(self._fix_path, self.getPrintCSSFiles()) js_files = map(self._fix_path, self.getJSFiles() + plugin_js + custom_js) body = to_unicode(self._display(params)) return render_template('indico_base.html', css_files=css_files, print_css_files=print_css_files, js_files=js_files, site_name=core_settings.get('site_title'), social=social_settings.get_all(), page_title=' - '.join(title_parts), head_content=to_unicode(self._getHeadContent()), body=body)
def _get_email_subject(self, **mail_params): return u'{prefix}[{room}] {subject} {date} {suffix}'.format( prefix=to_unicode(mail_params.get('subject_prefix', '')), room=self.reservation.room.full_name, subject=to_unicode(mail_params.get('subject', '')), date=to_unicode(self.start_dt), suffix=to_unicode(mail_params.get('subject_suffix', '')) ).strip()
def _format_contrib(contrib): if contrib.getSession() is None: return to_unicode(contrib.getTitle()) else: return _('{contrib} (in session "{session}")').format( session=to_unicode(contrib.getSession().getTitle()), contrib=to_unicode(contrib.getTitle()) )
def make_email(to_list=None, cc_list=None, bcc_list=None, from_address=None, reply_address=None, attachments=None, subject=None, body=None, template=None, html=False): """Creates an email. The preferred way to specify the email content is using the `template` argument. To do so, use :func:`.get_template_module` on a template inheriting from ``emails/base.txt`` for text emails or ``emails/base.html`` for HTML emails. :param to_list: The recipient email or a collection of emails :param cc_list: The CC email or a collection of emails :param bcc_list: The BCC email or a collection of emails :param from_address: The sender address. Defaults to noreply. :param reply_address: The reply-to address or a collection of addresses. Defaults to empty. :param attachments: A list of attachments. Each attachment can be a `MIMEBase` subclass, a 3-tuple of the form ``(filename, content, mimetype)``, or a 2-tuple ``(filename, content)`` in which case the mime type will be guessed from the file name. :param subject: The subject of the email. :param body: The body of the email: :param template: A template module containing ``get_subject`` and ``get_body`` macros. :param html: ``True`` if the email body is HTML """ if template is not None and (subject is not None or body is not None): raise ValueError("Only subject/body or template can be passed") if template: subject = template.get_subject() body = template.get_body() if config.DEBUG and '\n' in subject: raise ValueError('Email subject contains linebreaks') subject = re.sub(r'\s+', ' ', subject) if to_list is None: to_list = set() if cc_list is None: cc_list = set() if bcc_list is None: bcc_list = set() to_list = {to_list} if isinstance(to_list, basestring) else to_list cc_list = {cc_list} if isinstance(cc_list, basestring) else cc_list bcc_list = {bcc_list} if isinstance(bcc_list, basestring) else bcc_list reply_address = {reply_address} if isinstance(reply_address, basestring) else (reply_address or set()) return { 'to': set(map(to_unicode, to_list)), 'cc': set(map(to_unicode, cc_list)), 'bcc': set(map(to_unicode, bcc_list)), 'from': to_unicode(from_address or config.NO_REPLY_EMAIL), 'reply_to': set(map(to_unicode, reply_address)), 'attachments': attachments or [], 'subject': to_unicode(subject).strip(), 'body': to_unicode(body).strip(), 'html': html, }
def handle_exception(exc, message=None): Logger.get('flask').exception(to_unicode(exc.message) or 'Uncaught Exception') if not current_app.debug or request.is_xhr or request.is_json: sentry_log_exception() if message is None: message = '{}: {}'.format(type(exc).__name__, to_unicode(exc.message)) return render_error(exc, _('Something went wrong'), message, 500) # Let the exception propagate to middleware /the webserver. # This triggers the Flask debugger in development and sentry # logging (if enabled) (via got_request_exception). raise
def format_event_date(self, event): day_month = 'dd MMM' tzinfo = self.category.display_tzinfo start_dt = event.start_dt.astimezone(tzinfo) end_dt = event.end_dt.astimezone(tzinfo) if start_dt.year != end_dt.year: return '{} - {}'.format(to_unicode(format_date(start_dt, timezone=tzinfo)), to_unicode(format_date(end_dt, timezone=tzinfo))) elif (start_dt.month != end_dt.month) or (start_dt.day != end_dt.day): return '{} - {}'.format(to_unicode(format_date(start_dt, day_month, timezone=tzinfo)), to_unicode(format_date(end_dt, day_month, timezone=tzinfo))) else: return to_unicode(format_date(start_dt, day_month, timezone=tzinfo))
def __init__(self, rh, event_, **kwargs): assert event_ == kwargs.setdefault('event', event_) self.event = event_ WPDecorated.__init__(self, rh, **kwargs) start_dt_local = event_.start_dt_display.astimezone(event_.display_tzinfo) end_dt_local = event_.end_dt_display.astimezone(event_.display_tzinfo) dates = ' ({})'.format(to_unicode(format_date(start_dt_local, format='long'))) if start_dt_local.date() != end_dt_local.date(): if start_dt_local.year == end_dt_local.year and start_dt_local.month == end_dt_local.month: dates = ' ({}-{})'.format(start_dt_local.day, to_unicode(format_date(end_dt_local, format='long'))) else: dates = ' ({} - {})'.format(to_unicode(format_date(start_dt_local, format='long')), to_unicode(format_date(end_dt_local, format='long'))) self.title = '{} {}'.format(strip_tags(self.event.title), dates)
def generate_spreadsheet_from_registrations(registrations, regform_items, special_items): """Generates a spreadsheet data from a given registration list. :param registrations: The list of registrations to include in the file :param regform_items: The registration form items to be used as columns :param special_items: Registration form information as extra columns """ field_names = ['ID', 'Name'] special_item_mapping = OrderedDict([ ('reg_date', ('Registration date', lambda x: to_unicode(format_datetime(x.submitted_dt)))), ('state', ('Registration state', lambda x: x.state.title)), ('price', ('Price', lambda x: x.render_price())), ('checked_in', ('Checked in', lambda x: x.checked_in)), ('checked_in_date', ('Check-in date', lambda x: (to_unicode(format_datetime(x.checked_in_dt)) if x.checked_in else ''))) ]) for item in regform_items: field_names.append('{}_{}'.format(item.title, item.id)) if item.input_type == 'accommodation': field_names.append('{}_{}_{}'.format(item.title, 'Arrival', item.id)) field_names.append('{}_{}_{}'.format(item.title, 'Departure', item.id)) field_names.extend(title for name, (title, fn) in special_item_mapping.iteritems() if name in special_items) rows = [] for registration in registrations: data = registration.data_by_field registration_dict = { 'ID': registration.friendly_id, 'Name': "{} {}".format(registration.first_name, registration.last_name) } for item in regform_items: key = '{}_{}'.format(item.title, item.id) if item.input_type == 'accommodation': registration_dict[key] = _prepare_data(data[item.id].friendly_data.get('choice') if item.id in data else '') key = '{}_{}_{}'.format(item.title, 'Arrival', item.id) arrival_date = data[item.id].friendly_data.get('arrival_date') if item.id in data else None registration_dict[key] = _prepare_data(format_date(arrival_date) if arrival_date else '') key = '{}_{}_{}'.format(item.title, 'Departure', item.id) departure_date = data[item.id].friendly_data.get('departure_date') if item.id in data else None registration_dict[key] = _prepare_data(format_date(departure_date) if departure_date else '') else: registration_dict[key] = _prepare_data(data[item.id].friendly_data if item.id in data else '') for name, (title, fn) in special_item_mapping.iteritems(): if name not in special_items: continue value = fn(registration) registration_dict[title] = value rows.append(registration_dict) return field_names, rows
def _getAnswer(self): event_persons = [] users = searchUsers(self._surName, self._name, self._organisation, self._email, self._exactMatch, self._searchExt) if self._event: fields = {EventPerson.first_name: self._name, EventPerson.last_name: self._surName, EventPerson.email: self._email, EventPerson.affiliation: self._organisation} criteria = [unaccent_match(col, val, exact=self._exactMatch) for col, val in fields.iteritems()] event_persons = self._event.persons.filter(*criteria).all() fossilized_users = fossilize(sorted(users, key=lambda av: (av.getStraightFullName(), av.getEmail()))) fossilized_event_persons = map(serialize_event_person, event_persons) unique_users = {to_unicode(user['email']): user for user in chain(fossilized_users, fossilized_event_persons)} return sorted(unique_users.values(), key=lambda x: (to_unicode(x['name']).lower(), to_unicode(x['email'])))
def get_allowed_sender_emails(self, include_current_user=True, include_creator=True, include_managers=True, include_support=True, include_chairs=True, extra=None): """ Return the emails of people who can be used as senders (or rather Reply-to contacts) in emails sent from within an event. :param include_current_user: Whether to include the email of the currently logged-in user :param include_creator: Whether to include the email of the event creator :param include_managers: Whether to include the email of all event managers :param include_support: Whether to include the "event support" email :param include_chairs: Whether to include the emails of event chairpersons (or lecture speakers) :param extra: An email address that is always included, even if it is not in any of the included lists. :return: An OrderedDict mapping emails to pretty names """ emails = {} # Support if include_support: support = self.as_legacy.getSupportInfo() emails[support.getEmail()] = support.getCaption() or support.getEmail() # Current user if include_current_user and has_request_context() and session.user: emails[session.user.email] = session.user.full_name # Creator if include_creator: emails[self.creator.email] = self.creator.full_name # Managers if include_managers: emails.update((p.principal.email, p.principal.full_name) for p in self.acl_entries if p.type == PrincipalType.user and p.full_access) # Chairs if include_chairs: emails.update((pl.email, pl.full_name) for pl in self.person_links if pl.email) # Extra email (e.g. the current value in an object from the DB) if extra: emails.setdefault(extra, extra) # Sanitize and format emails emails = {to_unicode(email.strip().lower()): '{} <{}>'.format(to_unicode(name), to_unicode(email)) for email, name in emails.iteritems() if email and email.strip()} own_email = session.user.email if has_request_context() and session.user else None return OrderedDict(sorted(emails.items(), key=lambda x: (x[0] != own_email, x[1].lower())))
def _build_match(column, value, exact): value = to_unicode(value).replace('%', r'\%').replace('_', r'\_').lower() if not exact: value = '%{}%'.format(value) # we always use LIKE, even for an exact match. when using the pg_trgm indexes this is # actually faster than `=` return db.func.indico_unaccent(db.func.lower(column)).ilike(db.func.indico_unaccent(value))
def render(cls, regform, registration): event = registration.registration_form.event return Markup( '<a href="{url}" title="{title}">{url}</a>'.format( url=event.getURL(), title=escape(to_unicode(event.title)) ) )
def verbose_iterator(iterable, total, get_id, get_title): """Iterates large iterables verbosely :param iterable: An iterable :param total: The number of items in `iterable` :param get_id: callable to retrieve the ID of an item :param get_title: callable to retrieve the title of an item """ term_width = terminal_size()[0] start_time = time.time() fmt = cformat( '[%{cyan!}{:6}%{reset}/%{cyan}{}%{reset} %{yellow!}{:.3f}%{reset}% %{green!}{}%{reset}] {:>8} %{grey!}{}' ) for i, item in enumerate(iterable, 1): if i % 10 == 0 or i == total: remaining_seconds = int((time.time() - start_time) / i * (total - i)) remaining = '{:02}:{:02}'.format(remaining_seconds // 60, remaining_seconds % 60) title = to_unicode(get_title(item).replace('\n', ' ')) text = fmt.format(i, total, (i / total * 100.0), remaining, get_id(item), title) print('\r', ' ' * term_width, end='', sep='') # terminal width + ansi control code length - trailing reset code (4) print('\r', text[:term_width + len(text.value_colors) - len(text.value_no_colors) - 4], cformat('%{reset}'), end='', sep='') sys.stdout.flush() yield item print()
def _iterate_objs(query_string): query = (Event.query .filter(Event.title_matches(to_unicode(query_string)), ~Event.is_deleted) .options(undefer('effective_protection_mode'))) sort_dir = db.desc if self._descending else db.asc if self._orderBy == 'start': query = query.order_by(sort_dir(Event.start_dt)) elif self._orderBy == 'end': query = query.order_by(sort_dir(Event.end_dt)) elif self._orderBy == 'id': query = query.order_by(sort_dir(Event.id)) elif self._orderBy == 'title': query = query.order_by(sort_dir(db.func.lower(Event.title))) counter = 0 # Query the DB in chunks of 1000 records per query until the limit is satisfied for event in query.yield_per(1000): if event.can_access(self._user): counter += 1 # Start yielding only when the counter reaches the given offset if (self._offset is None) or (counter > self._offset): yield event # Stop querying the DB when the limit is satisfied if (self._limit is not None) and (counter == self._offset + self._limit): break
def all_recipients(self): """Returns all recipients of the notifications. This includes both explicit recipients and, if enabled, participants of the event. """ recipients = set(self.recipients) if self.send_to_participants: event = self.event if event.getType() == 'conference': recipients.update(to_unicode(r.getEmail().strip().lower()) for r in event.getRegistrantsList()) else: recipients.update(to_unicode(p.getEmail().strip().lower()) for p in event.getParticipation().getParticipantList()) recipients.discard('') # just in case there was an empty email address somewhere return recipients
def serialize_category_atom(category, url, user, event_filter): """Export the events in a category to Atom :param category: The category to export :param url: The URL of the feed :param user: The user who needs to be able to access the events :param event_filter: A SQLalchemy criterion to restrict which events will be returned. Usually something involving the start/end date of the event. """ query = (Event.query .filter(Event.category_chain.contains([int(category.getId())]), ~Event.is_deleted, event_filter) .options(load_only('id', 'start_dt', 'title', 'description', 'protection_mode'), subqueryload('acl_entries')) .order_by(Event.start_dt)) events = [e for e in query if e.can_access(user)] feed = AtomFeed(feed_url=url, title='Indico Feed [{}]'.format(to_unicode(category.getTitle()))) for event in events: feed.add(title=event.title, summary=unicode(event.description), # get rid of RichMarkup url=url_for('event.conferenceDisplay', confId=event.id, _external=True), updated=event.start_dt) return BytesIO(feed.to_string().encode('utf-8'))
def removeParticipant(self, participant, responsibleUser=None): if participant is None: return False # If 'participant' is an object from Participant if isinstance(participant, Participant): # remove all entries with participant for key, value in self._participantList.items(): if value == participant: del self._participantList[key] # If 'participant' is a key else: key = participant if key not in self._participantList: return False participant = self._participantList[key] del self._participantList[key] self.getConference().log(EventLogRealm.management, EventLogKind.negative, u'Participants', u'Participant removed: {}'.format(to_unicode(participant.getName())), session.user, data=participant.getParticipantData()) avatar = participant.getAvatar() if avatar: avatar.unlinkTo(self._conference,"participant") if participant._status in {'added', 'accepted'}: signals.event.participant_changed.send(self._conference, user=avatar, participant=participant, old_status=participant._status, action='removed') self.notifyModification() return True
def get_time_changes_notifications(changes, tzinfo, entry=None): notifications = [] for obj, change in changes.iteritems(): if entry: if entry.object == obj: continue if not isinstance(obj, Event) and obj.timetable_entry in entry.children: continue msg = None if isinstance(obj, Event): if 'start_dt' in change: new_time = change['start_dt'][1] msg = _("Event start time changed to {}") elif 'end_dt' in change: new_time = change['end_dt'][1] msg = _("Event end time changed to {}") else: raise ValueError("Invalid change in event.") elif isinstance(obj, SessionBlock): if 'start_dt' in change: new_time = change['start_dt'][1] msg = _("Session block start time changed to {}") elif 'end_dt' in change: new_time = change['end_dt'][1] msg = _("Session block end time changed to {}") else: raise ValueError("Invalid change in session block.") if msg: notifications.append(msg.format(to_unicode(format_time(new_time, timezone=tzinfo)))) return notifications
def _process(self): if self._getUser() is not None and self._getUser().isRegisteredInConf(self._conf): if ( not self._conf.getRegistrationForm().inRegistrationPeriod() and not self._conf.getRegistrationForm().inModificationPeriod() ): flash(_("Your modification could not be recorded since the modification period is over."), "error") return redirect(url_for("event.confRegistrationFormDisplay", self._conf)) else: rp = self._getUser().getRegistrantById(self._conf.getId()) # Check if the email matches an existing user params = self._getRequestParams() email = self._regForm.getPersonalData().getValueFromParams(params, "email") or "" user = get_user_by_email(email) if user: if not session.user: flash( _( "The provided email ({email}) is linked to an Indico account. Please sign in with it " "first." ).format(email=email), "error", ) return redirect(url_for("event.confRegistrationFormDisplay-modify", self._conf)) elif session.user != user: flash( _( "The provided email ({email}) is linked to another Indico account. Please sign in with " "it first." ).format(email=email), "error", ) return redirect(url_for("event.confRegistrationFormDisplay-modify", self._conf)) # check if the email is being changed by another one that already exists if email != rp.getEmail() and self._conf.hasRegistrantByEmail(email): raise FormValuesError( _('There is already a user with the email "{email}". ' "Please choose another one.").format( email or "--no email--" ) ) rp.setValues(self._getRequestParams(), self._getUser()) log_msg = u"User modified his registration data: {}" self._conf.log( EventLogRealm.participants, EventLogKind.positive, u"Registration", log_msg.format(to_unicode(rp.getFullName(title=False, firstNameFirst=True))), session.user, data={u"Indico user": u"{} ({})".format(user.full_name, user.id) if user else u"None"}, ) notify_registration_modification(self._conf, rp) flash(_(u"Your registration has been modified successfully."), "success") if rp.doPay(): self._redirect(urlHandlers.UHConfRegistrationFormCreationDone.getURL(rp)) else: self._redirect(urlHandlers.UHConfRegistrationForm.getURL(self._conf)) else: self._redirect(urlHandlers.UHConfRegistrationForm.getURL(self._conf))
def _get_reg_details(reg_form, registrant): reg_details = {'misc_details': OrderedDict(), 'personal_data': OrderedDict()} for section in reg_form.getSortedForms(): if section.getId() == 'reasonParticipation': reg_details['reason'] = registrant.getReasonParticipation() elif section.getId() == 'sessions': reg_details['sessions_type'] = 'priorities' if section.getType() == '2priorities' else None reg_details['sessions'] = [to_unicode(session.getTitle()) for session in registrant.getSessionList()] elif section.getId() == 'accommodation' and section.isEnabled(): accommodation = registrant.getAccommodation() if accommodation.getAccommodationType(): reg_details['accommodation_type'] = accommodation.getAccommodationType().getCaption() reg_details['accommodation_arrival'] = accommodation.getArrivalDate().strftime('%d %B %Y') reg_details['accommodation_departure'] = accommodation.getDepartureDate().strftime('%d %B %Y') elif section.getId() == 'socialEvents' and section.isEnabled(): reg_details['social'] = {} for social_event in registrant.getSocialEvents(): reg_details['social'][social_event.getCaption()] = social_event.getNoPlaces() elif section.getId() == 'furtherInformation': pass elif section.isEnabled(): misc = registrant.getMiscellaneousGroupById(section.getId()) if not misc: continue title = to_unicode(misc.getTitle()) fields = OrderedDict() for field in section.getSortedFields(): response_item = misc.getResponseItemById(field.getId()) if not response_item: continue input_field = response_item.getGeneralField().getInput() form_field = {'value': response_item.getValue(), 'caption': to_unicode(response_item.getCaption())} if response_item.isBillable(): form_field['price'] = response_item.getPrice() form_field['currency'] = response_item.getCurrency() if form_field['value']: try: form_field['value'] = to_unicode(input_field.getValueDisplay(form_field['value'])) except Exception: form_field['value'] = to_unicode(form_field['value']).strip() fields[field.getId()] = form_field if isinstance(section, PersonalDataForm): reg_details['personal_data'][title] = fields else: reg_details['misc_details'][title] = fields return reg_details
def _process(self): canManageRegistration = self._conf.canManageRegistration(self._getUser()) if not canManageRegistration and not self._regForm.isActivated(): p = registrationForm.WPRegFormInactive(self, self._conf) return p.display() params = self._getRequestParams() email = self._regForm.getPersonalData().getValueFromParams(params, 'email') if email is None: raise FormValuesError(_("An email address has to be set in order to make the registration in the event.")) elif not validMail(email, False): raise FormValuesError(_("The given email address is not valid.")) # Check if the email matches an existing user user = get_user_by_email(email) avatar = user.as_avatar if user else None # Check if the user can register if not canManageRegistration: # normal user registering. Managers can. if self._conf.getRegistrationForm().isFull(): self._redirect(urlHandlers.UHConfRegistrationFormDisplay.getURL(self._conf)) return elif not self._conf.getRegistrationForm().inRegistrationPeriod(): flash(_("Your registration couldn't be recorded."), 'error') return redirect(url_for('event.confRegistrationFormDisplay', self._conf)) if user is None: if self._conf.hasRegistrantByEmail(email): raise FormValuesError("There is already a user with the email \"%s\". Please choose another one" % email) else: if avatar.isRegisteredInConf(self._conf) or self._conf.hasRegistrantByEmail(email): if canManageRegistration: raise FormValuesError("There is already a user with the email \"%s\". Please choose another one" % email) else: raise FormValuesError("You have already registered with the email address \"%s\". If you need to modify your registration, please contact the managers of the conference." % email) rp = registration.Registrant() self._conf.addRegistrant(rp, avatar) rp.setValues(self._getRequestParams(), avatar) if avatar is not None: rp.setAvatar(avatar) notify_registration_confirmation(self._conf, rp) self._conf.log(EventLogRealm.management if self.is_manager else EventLogRealm.participants, EventLogKind.positive, u'Registration', u'User registered: {}'.format(to_unicode(rp.getFullName(title=False, firstNameFirst=True))), session.user, data={u'Indico user': u'{} ({})'.format(user.full_name, user.id) if user else u'None'}) if self.is_manager: self._redirect(RHRegistrantListModif._uh.getURL(self._conf)) else: params = {} if not rp.doPay() or not payment_event_settings.get(self._conf, 'enabled'): flash(_(u"Your registration has been recorded successfully."), 'success') if not session.user or session.user != user: params.update(rp.getLocator(), **{'authkey': rp.getRandomId()}) else: params.update(self._conf.getLocator()) return redirect(url_for('event.confRegistrationFormDisplay', **params))
def _set_email_choices(self): # User emails = {session.user.email: session.user.full_name} # Creator emails[self.event.getCreator().getEmail()] = self.event.getCreator().getStraightFullName(upper=False) # Support support = self.event.getSupportInfo() emails[support.getEmail()] = support.getCaption() or support.getEmail() # Chairs emails.update((x.getEmail(), x.getDirectFullName()) for x in self.event.getChairList()) # Current email to avoid destructive modifications emails.setdefault(self.reply_to_address.object_data, self.reply_to_address.object_data) # Sanitize and format emails emails = {to_unicode(email.strip().lower()): '{} <{}>'.format(to_unicode(name), to_unicode(email)) for email, name in emails.iteritems() if email and email.strip()} self.reply_to_address.choices = sorted(emails.items(), key=lambda x: (x[0] != session.user.email, x[1].lower()))
def setStatusDeclined(self, responsibleUser=None): if self._status != "pending" : return False self._status = "declined" self.getConference().log(EventLogRealm.management, EventLogKind.negative, u'Participants', u"Participation request declined: {}".format(to_unicode(self.getName())), session.user, data=self.getParticipantData()) return True
if responseUtil.status == 405: responseUtil.headers[ 'Allow'] = 'GET' if request.method == 'POST' else 'POST' if result is None and error is None: # TODO: usage page raise NotFound else: if ak and error is None: # Commit only if there was an API key and no error norm_path, norm_query = normalizeQuery(path, query, remove=('signature', 'timestamp'), separate=True) uri = to_unicode('?'.join(filter(None, (norm_path, norm_query)))) ak.register_used(request.remote_addr, uri, not onlyPublic) transaction.commit() else: # No need to commit stuff if we didn't use an API key (nothing was written) # XXX do we even need this? transaction.abort() # Log successful POST api requests if error is None and request.method == 'POST': logger.info('API request: %s?%s' % (path, query)) serializer = Serializer.create(dformat, query_params=queryParams, pretty=pretty, typeMap=typeMap,
def __init__(self, text, style, part="", bulletText=None, frags=None, caseSensitive=1): platypus.Paragraph.__init__(self, to_unicode(text), style, bulletText, frags, caseSensitive) self._part = part
def handle_badrequestkeyerror(exc): if current_app.debug: raise msg = _('Required argument missing: {}').format(to_unicode(exc.message)) return render_error(exc, exc.name, msg, exc.code)
def handle_indico_exception(exc): return render_error(exc, _('Something went wrong'), to_unicode(exc.message), getattr(exc, 'http_status_code', 500))
def setName(self, name, reindex=False): self.user.first_name = to_unicode(name)
def setOrganisation(self, affiliation, reindex=False): self.user.affiliation = to_unicode(affiliation)
def setTimezone(self, tz): self.user.settings.set('timezone', to_unicode(tz))
def modify(self, data, user): """Modifies an existing reservation. :param data: A dict containing the booking data, usually from a :class:`ModifyBookingForm` instance :param user: The :class:`.User` who modifies the booking. """ populate_fields = ('start_dt', 'end_dt', 'repeat_frequency', 'repeat_interval', 'booked_for_user', 'contact_email', 'contact_phone', 'booking_reason', 'used_equipment', 'needs_assistance', 'uses_vc', 'needs_vc_assistance') # fields affecting occurrences occurrence_fields = { 'start_dt', 'end_dt', 'repeat_frequency', 'repeat_interval' } # fields where date and time are compared separately date_time_fields = {'start_dt', 'end_dt'} # fields for the repetition repetition_fields = {'repeat_frequency', 'repeat_interval'} # pretty names for logging field_names = { 'start_dt/date': u"start date", 'end_dt/date': u"end date", 'start_dt/time': u"start time", 'end_dt/time': u"end time", 'repetition': u"booking type", 'booked_for_user': u"'Booked for' user", 'contact_email': u"contact email", 'contact_phone': u"contact phone number", 'booking_reason': u"booking reason", 'used_equipment': u"list of equipment", 'needs_assistance': u"option 'General Assistance'", 'uses_vc': u"option 'Uses Videoconference'", 'needs_vc_assistance': u"option 'Videoconference Setup Assistance'" } self.room.check_advance_days(data['end_dt'].date(), user) self.room.check_bookable_hours(data['start_dt'].time(), data['end_dt'].time(), user) changes = {} update_occurrences = False old_repetition = self.repetition for field in populate_fields: if field not in data: continue old = getattr(self, field) new = data[field] converter = unicode if field == 'used_equipment': # Dynamic relationship old = sorted(old.all()) converter = lambda x: u', '.join(x.name for x in x) if old != new: # Booked for user updates the (redundant) name if field == 'booked_for_user': old = self.booked_for_name new = self.booked_for_name = data[field].full_name # Apply the change setattr(self, field, data[field]) # If any occurrence-related field changed we need to recreate the occurrences if field in occurrence_fields: update_occurrences = True # Record change for history entry if field in date_time_fields: # The date/time fields create separate entries for the date and time parts if old.date() != new.date(): changes[field + '/date'] = { 'old': old.date(), 'new': new.date(), 'converter': format_date } if old.time() != new.time(): changes[field + '/time'] = { 'old': old.time(), 'new': new.time(), 'converter': format_time } elif field in repetition_fields: # Repetition needs special handling since it consists of two fields but they are tied together # We simply update it whenever we encounter such a change; after the last change we end up with # the correct change data changes['repetition'] = { 'old': old_repetition, 'new': self.repetition, 'converter': lambda x: RepeatMapping.get_message(*x) } else: changes[field] = { 'old': old, 'new': new, 'converter': converter } if not changes: return False # Create a verbose log entry for the modification log = [u'Booking modified'] for field, change in changes.iteritems(): field_title = field_names.get(field, field) converter = change['converter'] old = to_unicode(converter(change['old'])) new = to_unicode(converter(change['new'])) if not old: log.append(u"The {} was set to '{}'".format(field_title, new)) elif not new: log.append(u"The {} was cleared".format(field_title)) else: log.append(u"The {} was changed from '{}' to '{}'".format( field_title, old, new)) self.edit_logs.append( ReservationEditLog(user_name=user.full_name, info=log)) # Recreate all occurrences if necessary if update_occurrences: cols = [ col.name for col in ReservationOccurrence.__table__.columns if not col.primary_key and col.name not in {'start_dt', 'end_dt'} ] old_occurrences = {occ.date: occ for occ in self.occurrences} self.occurrences.delete(synchronize_session='fetch') self.create_occurrences(True, user) db.session.flush() # Restore rejection data etc. for recreated occurrences for occurrence in self.occurrences: old_occurrence = old_occurrences.get(occurrence.date) # Copy data from old occurrence UNLESS the new one is invalid (e.g. because of collisions) # Otherwise we'd end up with valid occurrences ignoring collisions! if old_occurrence and occurrence.is_valid: for col in cols: setattr(occurrence, col, getattr(old_occurrence, col)) # Don't cause new notifications for the entire booking in case of daily repetition if self.repeat_frequency == RepeatFrequency.DAY and all( occ.notification_sent for occ in old_occurrences.itervalues()): for occurrence in self.occurrences: occurrence.notification_sent = True # Sanity check so we don't end up with an "empty" booking if not any(occ.is_valid for occ in self.occurrences): raise NoReportError(_(u'Reservation has no valid occurrences')) notify_modification(self, changes) return True
def _applyDecoration(self, body): if request.args.get('frame') == 'no' or request.args.get( 'fr') == 'no' or request.args.get('print') == '1': return to_unicode(WPrintPageFrame().getHTML({'content': body})) else: return WPConferenceBase._applyDecoration(self, body)
def force_text(val): if is_lazy_string(val): val = val.value return to_unicode(val)
def _process_POST(self): if User.query.filter_by(is_system=False).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.DEFAULT_TIMEZONE) user.settings.set('lang', session.lang or config.DEFAULT_LOCALE) login_user(user, identity) full_name = user.full_name # needed after the session closes db.session.commit() # Configuring server's settings core_settings.set('site_organization', 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 _apply_decoration(self, body): breadcrumbs = self._get_breadcrumbs() return '<div class="header">{}</div>\n<div class="main">{}<div>{}</div></div>\n{}'.format( self._get_header(), breadcrumbs, to_unicode(body), self._get_footer())
def render(cls, regform, registration): event = registration.registration_form.event return Markup('<a href="{url}" title="{title}">{url}</a>'.format(url=event.getURL(), title=escape(to_unicode(event.title))))
def setEmail(self, email, reindex=False): self.user.email = to_unicode(email)
def setAddress(self, address): self.user.address = to_unicode(address)
def _getBody(self, params): # Legacy handling for pages that do not use Jinja inheritance. tpl = u"{% extends 'events/management/base.html' %}{% block content %}{{ _body | safe }}{% endblock %}" body = to_unicode(self._getPageContent(params)) return render_template_string(tpl, _body=body, **self._kwargs)
def setTitle(self, title): self.user.title = to_unicode(title)
def _lower(text): return to_unicode(text).lower()
def setSurName(self, surname, reindex=False): self.user.last_name = to_unicode(surname)
def make_email(to_list=None, cc_list=None, bcc_list=None, from_address=None, reply_address=None, attachments=None, subject=None, body=None, template=None, html=False): """Creates an email. The preferred way to specify the email content is using the `template` argument. To do so, use :func:`.get_template_module` on a template inheriting from ``emails/base.txt`` for text emails or ``emails/base.html`` for HTML emails. :param to_list: The recipient email or a collection of emails :param cc_list: The CC email or a collection of emails :param bcc_list: The BCC email or a collection of emails :param from_address: The sender address. Defaults to noreply. :param reply_address: The reply-to address or a collection of addresses. Defaults to empty. :param attachments: A list of attachments. Each attachment can be a `MIMEBase` subclass, a 3-tuple of the form ``(filename, content, mimetype)``, or a 2-tuple ``(filename, content)`` in which case the mime type will be guessed from the file name. :param subject: The subject of the email. :param body: The body of the email: :param template: A template module containing ``get_subject`` and ``get_body`` macros. :param html: ``True`` if the email body is HTML """ if template is not None and (subject is not None or body is not None): raise ValueError("Only subject/body or template can be passed") if template: subject = template.get_subject() body = template.get_body() if config.DEBUG and '\n' in subject: raise ValueError('Email subject contains linebreaks') subject = re.sub(r'\s+', ' ', subject) if to_list is None: to_list = set() if cc_list is None: cc_list = set() if bcc_list is None: bcc_list = set() to_list = {to_list} if isinstance(to_list, basestring) else to_list cc_list = {cc_list} if isinstance(cc_list, basestring) else cc_list bcc_list = {bcc_list} if isinstance(bcc_list, basestring) else bcc_list reply_address = {reply_address} if isinstance( reply_address, basestring) else (reply_address or set()) return { 'to': set(map(to_unicode, to_list)), 'cc': set(map(to_unicode, cc_list)), 'bcc': set(map(to_unicode, bcc_list)), 'from': to_unicode(from_address or config.NO_REPLY_EMAIL), 'reply_to': set(map(to_unicode, reply_address)), 'attachments': attachments or [], 'subject': to_unicode(subject).strip(), 'body': to_unicode(body).strip(), 'html': html, }
def setLang(self, lang): self.user.settings.set('lang', to_unicode(lang))
def setTelephone(self, phone): self.user.phone = to_unicode(phone)
def handle_baddata(exc): return render_error(exc, _('Invalid or expired token'), to_unicode(exc.message), 400)
def setSecondaryEmails(self, emails, reindex=False): self.user.secondary_emails = { to_unicode(email.strip().lower()) for email in emails }
def __init__(self, text, pageNumber, style, part="", bulletText=None, frags=None, caseSensitive=1): Paragraph.__init__(self, to_unicode(text), style, part, bulletText, frags, caseSensitive) self._part = part self._pageNumber = pageNumber
def addSecondaryEmail(self, email, reindex=False): return self.user.secondary_emails.add(to_unicode( email.strip().lower()))
def import_contributions_from_csv(event, f): """Import timetable contributions from a CSV file into an event.""" reader = csv.reader(f.read().splitlines()) contrib_data = [] for num_row, row in enumerate(reader, 1): try: start_dt, duration, title, first_name, last_name, affiliation, email = \ [to_unicode(value).strip() for value in row] email = email.lower() except ValueError: raise UserValueError( _('Row {}: malformed CSV data - please check that the number of columns is correct' ).format(num_row)) try: parsed_start_dt = event.tzinfo.localize( dateutil.parser.parse(start_dt)) if start_dt else None except ValueError: raise UserValueError( _("Row {row}: can't parse date: \"{date}\"").format( row=num_row, date=start_dt)) try: parsed_duration = timedelta( minutes=int(duration)) if duration else None except ValueError: raise UserValueError( _("Row {row}: can't parse duration: {duration}").format( row=num_row, duration=duration)) if not title: raise UserValueError( _("Row {}: contribution title is required").format(num_row)) if email and not validate_email(email): raise UserValueError( _("Row {row}: invalid email address: {email}").format( row=num_row, email=email)) contrib_data.append({ 'start_dt': parsed_start_dt, 'duration': parsed_duration or timedelta(minutes=20), 'title': title, 'speaker': { 'first_name': first_name, 'last_name': last_name, 'affiliation': affiliation, 'email': email } }) # now that we're sure the data is OK, let's pre-allocate the friendly ids # for the contributions in question Contribution.allocate_friendly_ids(event, len(contrib_data)) contributions = [] all_changes = defaultdict(list) for contrib_fields in contrib_data: speaker_data = contrib_fields.pop('speaker') with track_time_changes() as changes: contribution = create_contribution(event, contrib_fields, extend_parent=True) contributions.append(contribution) for key, val in changes[event].viewitems(): all_changes[key].append(val) email = speaker_data['email'] if not email: continue # set the information of the speaker person = get_event_person( event, { 'firstName': speaker_data['first_name'], 'familyName': speaker_data['last_name'], 'affiliation': speaker_data['affiliation'], 'email': email }) link = ContributionPersonLink(person=person, is_speaker=True) link.populate_from_dict({ 'first_name': speaker_data['first_name'], 'last_name': speaker_data['last_name'], 'affiliation': speaker_data['affiliation'] }) contribution.person_links.append(link) return contributions, all_changes
def test_to_unicode(input, output): assert to_unicode(input) == output
def handler(prefix, path): path = posixpath.join('/', prefix, path) clearCache() # init fossil cache logger = Logger.get('httpapi') if request.method == 'POST': # Convert POST data to a query string queryParams = [(key, [x.encode('utf-8') for x in values]) for key, values in request.form.iterlists()] query = urllib.urlencode(queryParams, doseq=1) # we only need/keep multiple values so we can properly validate the signature. # the legacy code below expects a dict with just the first value. # if you write a new api endpoint that needs multiple values get them from # ``request.values.getlist()`` directly queryParams = {key: values[0] for key, values in queryParams} else: # Parse the actual query string queryParams = dict((key, value.encode('utf-8')) for key, value in request.args.iteritems()) query = request.query_string apiKey = get_query_parameter(queryParams, ['ak', 'apikey'], None) cookieAuth = get_query_parameter(queryParams, ['ca', 'cookieauth'], 'no') == 'yes' signature = get_query_parameter(queryParams, ['signature']) timestamp = get_query_parameter(queryParams, ['timestamp'], 0, integer=True) noCache = get_query_parameter(queryParams, ['nc', 'nocache'], 'no') == 'yes' pretty = get_query_parameter(queryParams, ['p', 'pretty'], 'no') == 'yes' onlyPublic = get_query_parameter(queryParams, ['op', 'onlypublic'], 'no') == 'yes' onlyAuthed = get_query_parameter(queryParams, ['oa', 'onlyauthed'], 'no') == 'yes' scope = 'read:legacy_api' if request.method == 'GET' else 'write:legacy_api' if not request.headers.get('Authorization', '').lower().startswith('basic '): try: oauth_valid, oauth_request = oauth.verify_request([scope]) if not oauth_valid and oauth_request and oauth_request.error_message != 'Bearer token not found.': raise BadRequest('OAuth error: {}'.format( oauth_request.error_message)) elif g.get( 'received_oauth_token' ) and oauth_request.error_message == 'Bearer token not found.': raise BadRequest('OAuth error: Invalid token') except ValueError: # XXX: Dirty hack to workaround a bug in flask-oauthlib that causes it # not to properly urlencode request query strings # Related issue (https://github.com/lepture/flask-oauthlib/issues/213) oauth_valid = False else: oauth_valid = False # Get our handler function and its argument and response type hook, dformat = HTTPAPIHook.parseRequest(path, queryParams) if hook is None or dformat is None: raise NotFound # Disable caching if we are not just retrieving data (or the hook requires it) if request.method == 'POST' or hook.NO_CACHE: noCache = True ak = error = result = None ts = int(time.time()) typeMap = {} status_code = None is_response = False try: used_session = None if cookieAuth: used_session = session if not used_session.user: # ignore guest sessions used_session = None if apiKey or oauth_valid or not used_session: if not oauth_valid: # Validate the API key (and its signature) ak, enforceOnlyPublic = checkAK(apiKey, signature, timestamp, path, query) if enforceOnlyPublic: onlyPublic = True # Create an access wrapper for the API key's user user = ak.user if ak and not onlyPublic else None else: # Access Token (OAuth) at = load_token(oauth_request.access_token.access_token) user = at.user if at and not onlyPublic else None # Get rid of API key in cache key if we did not impersonate a user if ak and user is None: cacheKey = normalizeQuery( path, query, remove=('_', 'ak', 'apiKey', 'signature', 'timestamp', 'nc', 'nocache', 'oa', 'onlyauthed')) else: cacheKey = normalizeQuery(path, query, remove=('_', 'signature', 'timestamp', 'nc', 'nocache', 'oa', 'onlyauthed')) if signature: # in case the request was signed, store the result under a different key cacheKey = 'signed_' + cacheKey else: # We authenticated using a session cookie. token = request.headers.get( 'X-CSRF-Token', get_query_parameter(queryParams, ['csrftoken'])) if used_session.csrf_protected and used_session.csrf_token != token: raise HTTPAPIError('Invalid CSRF token', 403) user = used_session.user if not onlyPublic else None userPrefix = 'user-{}_'.format(used_session.user.id) cacheKey = userPrefix + normalizeQuery( path, query, remove=('_', 'nc', 'nocache', 'ca', 'cookieauth', 'oa', 'onlyauthed', 'csrftoken')) # Bail out if the user requires authentication but is not authenticated if onlyAuthed and not user: raise HTTPAPIError('Not authenticated', 403) addToCache = not hook.NO_CACHE cache = GenericCache('HTTPAPI') cacheKey = RE_REMOVE_EXTENSION.sub('', cacheKey) if not noCache: obj = cache.get(cacheKey) if obj is not None: result, extra, ts, complete, typeMap = obj addToCache = False if result is None: g.current_api_user = user # Perform the actual exporting res = hook(user) if isinstance(res, current_app.response_class): addToCache = False is_response = True result, extra, complete, typeMap = res, {}, True, {} elif isinstance(res, tuple) and len(res) == 4: result, extra, complete, typeMap = res else: result, extra, complete, typeMap = res, {}, True, {} if result is not None and addToCache: ttl = api_settings.get('cache_ttl') if ttl > 0: cache.set(cacheKey, (result, extra, ts, complete, typeMap), ttl) except HTTPAPIError as e: error = e if e.getCode(): status_code = e.getCode() if result is None and error is None: # TODO: usage page raise NotFound else: if ak and error is None: # Commit only if there was an API key and no error norm_path, norm_query = normalizeQuery(path, query, remove=('signature', 'timestamp'), separate=True) uri = to_unicode('?'.join(filter(None, (norm_path, norm_query)))) ak.register_used(request.remote_addr, uri, not onlyPublic) db.session.commit() else: # No need to commit stuff if we didn't use an API key (nothing was written) # XXX do we even need this? db.session.rollback() # Log successful POST api requests if error is None and request.method == 'POST': logger.info('API request: %s?%s', path, query) if is_response: return result serializer = Serializer.create(dformat, query_params=queryParams, pretty=pretty, typeMap=typeMap, **hook.serializer_args) if error: if not serializer.schemaless: # if our serializer has a specific schema (HTML, ICAL, etc...) # use JSON, since it is universal serializer = Serializer.create('json') result = fossilize(error) else: if serializer.encapsulate: result = fossilize( HTTPAPIResult(result, path, query, ts, complete, extra), IHTTPAPIExportResultFossil) del result['_fossil'] try: data = serializer(result) response = current_app.make_response(data) content_type = serializer.get_response_content_type() if content_type: response.content_type = content_type if status_code: response.status_code = status_code return response except Exception: logger.exception('Serialization error in request %s?%s', path, query) raise
def __init__(self, group_id): self.id = to_unicode(group_id).encode('utf-8')