def clean(self) -> Dict[str, Any]: username = self.cleaned_data.get("username") password = self.cleaned_data.get("password") if username is not None and password: subdomain = get_subdomain(self.request) realm = get_realm(subdomain) return_data: Dict[str, Any] = {} try: self.user_cache = authenticate( request=self.request, username=username, password=password, realm=realm, return_data=return_data, ) except RateLimited as e: assert e.secs_to_freedom is not None secs_to_freedom = int(e.secs_to_freedom) raise ValidationError( AUTHENTICATION_RATE_LIMITED_ERROR.format(secs_to_freedom)) if return_data.get("inactive_realm"): raise AssertionError( "Programming error: inactive realm in authentication form") if return_data.get("password_reset_needed"): raise ValidationError(mark_safe(PASSWORD_RESET_NEEDED_ERROR)) if return_data.get("inactive_user" ) and not return_data.get("is_mirror_dummy"): # We exclude mirror dummy accounts here. They should be treated as the # user never having had an account, so we let them fall through to the # normal invalid_login case below. error_message = DEACTIVATED_ACCOUNT_ERROR.format( username=username) raise ValidationError(mark_safe(error_message)) if return_data.get("invalid_subdomain"): logging.warning( "User %s attempted password login to wrong subdomain %s", username, subdomain) error_message = WRONG_SUBDOMAIN_ERROR.format(username=username) raise ValidationError(mark_safe(error_message)) if self.user_cache is None: raise forms.ValidationError( self.error_messages["invalid_login"], code="invalid_login", params={"username": self.username_field.verbose_name}, ) self.confirm_login_allowed(self.user_cache) return self.cleaned_data
def remote_installation_stats_link(server_id: int, hostname: str) -> mark_safe: from analytics.views.stats import stats_for_remote_installation url = reverse(stats_for_remote_installation, kwargs=dict(remote_server_id=server_id)) stats_link = f'<a href="{escape(url)}"><i class="fa fa-pie-chart"></i>{escape(hostname)}</a>' return mark_safe(stats_link)
def user_activity_link(email: str, user_profile_id: int) -> mark_safe: from analytics.views.user_activity import get_user_activity url = reverse(get_user_activity, kwargs=dict(user_profile_id=user_profile_id)) email_link = f'<a href="{escape(url)}">{escape(email)}</a>' return mark_safe(email_link)
def clean_password(self) -> str: password = self.cleaned_data["password"] if self.fields["password"].required and not check_password_strength( password): # The frontend code tries to stop the user from submitting the form with a weak password, # but if the user bypasses that protection, this error code path will run. raise ValidationError(mark_safe(PASSWORD_TOO_WEAK_ERROR)) return password
def email_is_not_mit_mailing_list(email: str) -> None: """Prevent MIT mailing lists from signing up for Zulip""" if "@mit.edu" in email: username = email.rsplit("@", 1)[0] # Check whether the user exists and can get mail. try: DNS.dnslookup(f"{username}.pobox.ns.athena.mit.edu", DNS.Type.TXT) except DNS.Base.ServerError as e: if e.rcode == DNS.Status.NXDOMAIN: raise ValidationError(mark_safe(MIT_VALIDATION_ERROR)) else: raise AssertionError("Unexpected DNS error")
def user_activity_intervals() -> Tuple[mark_safe, Dict[str, float]]: day_end = timestamp_to_datetime(time.time()) day_start = day_end - timedelta(hours=24) output = "Per-user online duration for the last 24 hours:\n" total_duration = timedelta(0) all_intervals = (UserActivityInterval.objects.filter( end__gte=day_start, start__lte=day_end, ).select_related( "user_profile", "user_profile__realm", ).only( "start", "end", "user_profile__delivery_email", "user_profile__realm__string_id", ).order_by( "user_profile__realm__string_id", "user_profile__delivery_email", )) by_string_id = lambda row: row.user_profile.realm.string_id by_email = lambda row: row.user_profile.delivery_email realm_minutes = {} for string_id, realm_intervals in itertools.groupby( all_intervals, by_string_id): realm_duration = timedelta(0) output += f"<hr>{string_id}\n" for email, intervals in itertools.groupby(realm_intervals, by_email): duration = timedelta(0) for interval in intervals: start = max(day_start, interval.start) end = min(day_end, interval.end) duration += end - start total_duration += duration realm_duration += duration output += f" {email:<37}{duration}\n" realm_minutes[string_id] = realm_duration.total_seconds() / 60 output += f"\nTotal duration: {total_duration}\n" output += f"\nTotal duration in minutes: {total_duration.total_seconds() / 60.}\n" output += f"Total duration amortized to a month: {total_duration.total_seconds() * 30. / 60.}" content = mark_safe("<pre>" + output + "</pre>") return content, realm_minutes
def sanitize_name(value: str) -> str: """ Sanitizes a value to be safe to store in a Linux filesystem, in S3, and in a URL. So Unicode is allowed, but not special characters other than ".", "-", and "_". This implementation is based on django.utils.text.slugify; it is modified by: * adding '.' to the list of allowed characters. * preserving the case of the value. * not stripping trailing dashes and underscores. """ value = unicodedata.normalize("NFKC", value) value = re.sub(r"[^\w\s.-]", "", value, flags=re.U).strip() value = re.sub(r"[-\s]+", "-", value, flags=re.U) assert value not in {"", ".", ".."} return mark_safe(value)
def update_login_page_context(request: HttpRequest, context: Dict[str, Any]) -> None: for key in ("email", "already_registered"): try: context[key] = request.GET[key] except KeyError: pass deactivated_email = request.GET.get("is_deactivated") if deactivated_email is None: return try: validate_email(deactivated_email) context["deactivated_account_error"] = mark_safe( DEACTIVATED_ACCOUNT_ERROR.format(username=escape(deactivated_email)) ) except ValidationError: logging.info("Invalid email in is_deactivated param to login page: %s", deactivated_email)
def realm_stats_link(realm_str: str) -> mark_safe: from analytics.views.stats import stats_for_realm url = reverse(stats_for_realm, kwargs=dict(realm_str=realm_str)) stats_link = f'<a href="{escape(url)}"><i class="fa fa-pie-chart"></i>{escape(realm_str)}</a>' return mark_safe(stats_link)
def realm_activity_link(realm_str: str) -> mark_safe: from analytics.views.realm_activity import get_realm_activity url = reverse(get_realm_activity, kwargs=dict(realm_str=realm_str)) realm_link = f'<a href="{escape(url)}">{escape(realm_str)}</a>' return mark_safe(realm_link)