def process_response(self, request, response): # type: (HttpRequest, HttpResponse) -> HttpResponse if settings.REALMS_HAVE_SUBDOMAINS: if (not request.path.startswith("/static/") and not request.path.startswith("/api/") and not request.path.startswith("/json/")): subdomain = get_subdomain(request) if (request.get_host() == "127.0.0.1:9991" or request.get_host() == "localhost:9991"): return redirect( "%s%s" % (settings.EXTERNAL_URI_SCHEME, settings.EXTERNAL_HOST)) if subdomain != "": realm = get_realm_by_string_id(subdomain) if (realm is None): return render_to_response("zerver/invalid_realm.html") """ If request.session was modified, or if the configuration is to save the session every time, save the changes and set a session cookie. """ try: accessed = request.session.accessed modified = request.session.modified except AttributeError: pass else: if accessed: patch_vary_headers(response, ('Cookie', )) if modified or settings.SESSION_SAVE_EVERY_REQUEST: if request.session.get_expire_at_browser_close(): max_age = None expires = None else: max_age = request.session.get_expiry_age() expires_time = time.time() + max_age expires = cookie_date(expires_time) # Save the session data and refresh the client cookie. # Skip session save for 500 responses, refs #3881. if response.status_code != 500: request.session.save() host = request.get_host().split(':')[0] session_cookie_domain = settings.SESSION_COOKIE_DOMAIN # The subdomains feature overrides the # SESSION_COOKIE_DOMAIN setting, since the setting # is a fixed value and with subdomains enabled, # the session cookie domain has to vary with the # subdomain. if settings.REALMS_HAVE_SUBDOMAINS: session_cookie_domain = host response.set_cookie( settings.SESSION_COOKIE_NAME, request.session.session_key, max_age=max_age, expires=expires, domain=session_cookie_domain, path=settings.SESSION_COOKIE_PATH, secure=settings.SESSION_COOKIE_SECURE or None, httponly=settings.SESSION_COOKIE_HTTPONLY or None) return response
def handle(self, *args, **options): # type: (*Any, **str) -> None realm = get_realm_by_string_id(options["string_id"]) if options["op"] == "show": for name, url in six.iteritems(realm.get_emoji()): print(name, url) sys.exit(0) name = options['name'] if name is None: self.print_help("./manage.py", "realm_emoji") sys.exit(1) if options["op"] == "add": img_url = options['img_url'] if img_url is None: self.print_help("./manage.py", "realm_emoji") sys.exit(1) check_add_realm_emoji(realm, name, img_url) sys.exit(0) elif options["op"] == "remove": do_remove_realm_emoji(realm, name) sys.exit(0) else: self.print_help("./manage.py", "realm_emoji") sys.exit(1)
def handle(self, **options): # type: (**Any) -> None if ( options["string_id"] is None or options["streams"] is None or (options["users"] is None and options["all_users"] is None) ): self.print_help("./manage.py", "add_users_to_streams") exit(1) stream_names = set([stream.strip() for stream in options["streams"].split(",")]) realm = get_realm_by_string_id(options["string_id"]) if options["all_users"]: user_profiles = UserProfile.objects.filter(realm=realm) else: emails = set([email.strip() for email in options["users"].split(",")]) user_profiles = [] for email in emails: user_profiles.append(get_user_profile_by_email(email)) for stream_name in set(stream_names): for user_profile in user_profiles: stream, _ = create_stream_if_needed(user_profile.realm, stream_name) _ignore, already_subscribed = bulk_add_subscriptions([stream], [user_profile]) was_there_already = user_profile.id in {tup[0].id for tup in already_subscribed} print( "%s %s to %s" % ("Already subscribed" if was_there_already else "Subscribed", user_profile.email, stream_name) )
def clean_email(self): # type: () -> str """Returns the email if and only if the user's email address is allowed to join the realm they are trying to join.""" email = self.cleaned_data['email'] # If the server has a unique open realm, pass if get_unique_open_realm(): return email # If a realm is specified and that realm is open, pass if completely_open(self.domain): return email # If the subdomain encodes a complete open realm, pass subdomain_realm = get_realm_by_string_id(self.subdomain) if (subdomain_realm is not None and completely_open(subdomain_realm.domain)): return email # If no realm is specified, fail realm = get_valid_realm(email) if realm is None: raise ValidationError(mark_safe(SIGNUP_STRING)) if realm.is_zephyr_mirror_realm: email_is_not_mit_mailing_list(email) return email
def handle(self, *args, **options): # type: (*Any, **Any) -> None try: realm = get_realm_by_string_id(options["realm"]) except ValidationError: raise CommandError("No such realm.") output_dir = options["output_dir"] if output_dir is None: output_dir = tempfile.mkdtemp(prefix="/tmp/zulip-export-") if os.path.exists(output_dir): shutil.rmtree(output_dir) os.makedirs(output_dir) print("Exporting realm %s" % (realm.domain, )) num_threads = int(options['threads']) if num_threads < 1: raise CommandError('You must have at least one thread.') do_export_realm(realm, output_dir, threads=num_threads) print("Finished exporting to %s; tarring" % (output_dir, )) do_write_stats_file_for_realm_export(output_dir) tarball_path = output_dir.rstrip('/') + '.tar.gz' os.chdir(os.path.dirname(output_dir)) subprocess.check_call( ["tar", "-czf", tarball_path, os.path.basename(output_dir)]) print("Tarball written to %s" % (tarball_path, ))
def clean_realm_subdomain(self): # type: () -> str if settings.REALMS_HAVE_SUBDOMAINS: error_strings = { 'too short': _("Subdomain needs to have length 3 or greater."), 'extremal dash': _("Subdomain cannot start or end with a '-'."), 'bad character': _("Subdomain can only have lowercase letters, numbers, and '-'s."), 'unavailable': _("Subdomain unavailable. Please choose a different one.")} else: error_strings = { 'too short': _("Short name needs at least 3 characters."), 'extremal dash': _("Short name cannot start or end with a '-'."), 'bad character': _("Short name can only have lowercase letters, numbers, and '-'s."), 'unavailable': _("Short name unavailable. Please choose a different one.")} subdomain = self.cleaned_data['realm_subdomain'] if not subdomain: return '' if len(subdomain) < 3: raise ValidationError(error_strings['too short']) if subdomain[0] == '-' or subdomain[-1] == '-': raise ValidationError(error_strings['extremal dash']) if not re.match('^[a-z0-9-]*$', subdomain): raise ValidationError(error_strings['bad character']) if is_reserved_subdomain(subdomain) or \ get_realm_by_string_id(subdomain) is not None: raise ValidationError(error_strings['unavailable']) return subdomain
def clean_email(self): # type: () -> str """Returns the email if and only if the user's email address is allowed to join the realm they are trying to join.""" email = self.cleaned_data['email'] if get_unique_open_realm(): return email # Otherwise, the user is trying to join a specific realm. realm = None if self.string_id: realm = get_realm_by_string_id(self.string_id) elif not settings.REALMS_HAVE_SUBDOMAINS: realm = get_realm_by_email_domain(email) if realm is None: if settings.REALMS_HAVE_SUBDOMAINS: raise ValidationError(_("The organization you are trying to join does not exist.")) else: raise ValidationError(_("Your email address does not correspond to any existing organization.")) if realm.invite_required: raise ValidationError(_("Please request an invite from the organization administrator.")) if not email_allowed_for_realm(email, realm): raise ValidationError( _("The organization you are trying to join, %(string_id)s, only allows users with e-mail " "addresses within the organization. Please try a different e-mail address." % {'string_id': realm.string_id})) if realm.is_zephyr_mirror_realm: email_is_not_mit_mailing_list(email) return email
def handle(self, *args, **options): # type: (*Any, **str) -> None realm = get_realm_by_string_id(options["string_id"]) if options["op"] == "show": print("%s: %s" % (realm.domain, all_realm_filters().get(realm.domain, []))) sys.exit(0) pattern = options['pattern'] if not pattern: self.print_help("./manage.py", "realm_filters") sys.exit(1) if options["op"] == "add": url_format_string = options['url_format_string'] if not url_format_string: self.print_help("./manage.py", "realm_filters") sys.exit(1) do_add_realm_filter(realm, pattern, url_format_string) sys.exit(0) elif options["op"] == "remove": do_remove_realm_filter(realm, pattern=pattern) sys.exit(0) else: self.print_help("./manage.py", "realm_filters") sys.exit(1)
def get_realm_from_request(request): # type: (HttpRequest) -> Realm if settings.REALMS_HAVE_SUBDOMAINS: realm_str = get_subdomain(request) else: realm_str = request.session.get("realm_str") return get_realm_by_string_id(realm_str)
def handle(self, **options): # type: (*Any, **Any) -> None if options["string_id"] is None or options["stream"] is None or \ (options["users"] is None and options["all_users"] is None): self.print_help("./manage.py", "remove_users_from_stream") exit(1) realm = get_realm_by_string_id(options["string_id"]) stream_name = options["stream"].strip() stream = get_stream(stream_name, realm) if options["all_users"]: user_profiles = UserProfile.objects.filter(realm=realm) else: emails = set([email.strip() for email in options["users"].split(",")]) user_profiles = [] for email in emails: user_profiles.append(get_user_profile_by_email(email)) result = bulk_remove_subscriptions(user_profiles, [stream]) not_subscribed = result[1] not_subscribed_users = {tup[0] for tup in not_subscribed} for user_profile in user_profiles: if user_profile in not_subscribed_users: print("%s was not subscribed" % (user_profile.email,)) else: print("Removed %s from %s" % (user_profile.email, stream_name))
def handle(self, **options): # type: (**str) -> None if options["string_id"] is None and options["users"] is None: self.print_help("./manage.py", "turn_off_digests") exit(1) if options["string_id"]: realm = get_realm_by_string_id(options["string_id"]) user_profiles = UserProfile.objects.filter(realm=realm) else: emails = set( [email.strip() for email in options["users"].split(",")]) user_profiles = [] for email in emails: user_profiles.append(get_user_profile_by_email(email)) print("Turned off digest emails for:") for user_profile in user_profiles: already_disabled_prefix = "" if user_profile.enable_digest_emails: do_change_enable_digest_emails(user_profile, False) else: already_disabled_prefix = "(already off) " print("%s%s <%s>" % (already_disabled_prefix, user_profile.full_name, user_profile.email))
def handle(self, *args, **options): # type: (*Any, **Any) -> None # To be really conservative while we don't have user timezones or # special-casing for companies with non-standard workweeks, only # try to send mail on Tuesdays, Wednesdays, and Thursdays. if datetime.datetime.utcnow().weekday() not in VALID_DIGEST_DAYS: return deployment_domains = domains_for_this_deployment() for realm in Realm.objects.filter(deactivated=False, show_digest_email=True): domain = realm.domain if not should_process_digest(domain, deployment_domains): continue string_id = realm.string_id user_profiles = UserProfile.objects.filter( realm=get_realm_by_string_id(string_id), is_active=True, is_bot=False, enable_digest_emails=True) for user_profile in user_profiles: cutoff = last_business_day() if inactive_since(user_profile, cutoff): queue_digest_recipient(user_profile, cutoff) logger.info( "%s is inactive, queuing for potential digest" % (user_profile.email, ))
def handle(self, *args, **options): # type: (*Any, **Any) -> None # To be really conservative while we don't have user timezones or # special-casing for companies with non-standard workweeks, only # try to send mail on Tuesdays, Wednesdays, and Thursdays. if datetime.datetime.utcnow().weekday() not in VALID_DIGEST_DAYS: return deployment_domains = domains_for_this_deployment() for realm in Realm.objects.filter(deactivated=False, show_digest_email=True): domain = realm.domain if not should_process_digest(domain, deployment_domains): continue string_id = realm.string_id user_profiles = UserProfile.objects.filter( realm=get_realm_by_string_id(string_id), is_active=True, is_bot=False, enable_digest_emails=True) for user_profile in user_profiles: cutoff = last_business_day() if inactive_since(user_profile, cutoff): queue_digest_recipient(user_profile, cutoff) logger.info("%s is inactive, queuing for potential digest" % ( user_profile.email,))
def handle(self, *args, **options): # type: (*Any, **Any) -> None if options["realm"]: realm = get_realm_by_string_id(options["realm"]) delete_realm_user_sessions(realm) elif options["deactivated_only"]: delete_all_deactivated_user_sessions() else: delete_all_user_sessions()
def handle(self, *args, **options): # type: (*Any, **str) -> None realm = get_realm_by_string_id(options["string_id"]) if realm is None: print("Could not find realm %s" % (options["string_id"], )) sys.exit(1) print("Reactivating", options["string_id"]) do_reactivate_realm(realm) print("Done!")
def handle(self, *args, **options): # type: (*Any, **str) -> None realm = get_realm_by_string_id(options["string_id"]) if realm is None: print("Could not find realm %s" % (options["string_id"],)) sys.exit(1) print("Deactivating", options["string_id"]) do_deactivate_realm(realm) print("Done!")
def process_response(self, request, response): # type: (HttpRequest, HttpResponse) -> HttpResponse if settings.REALMS_HAVE_SUBDOMAINS: if (not request.path.startswith("/static/") and not request.path.startswith("/api/") and not request.path.startswith("/json/")): subdomain = get_subdomain(request) if (request.get_host() == "127.0.0.1:9991" or request.get_host() == "localhost:9991"): return redirect("%s%s" % (settings.EXTERNAL_URI_SCHEME, settings.EXTERNAL_HOST)) if subdomain != "": realm = get_realm_by_string_id(subdomain) if (realm is None): return render_to_response("zerver/invalid_realm.html") """ If request.session was modified, or if the configuration is to save the session every time, save the changes and set a session cookie. """ try: accessed = request.session.accessed modified = request.session.modified except AttributeError: pass else: if accessed: patch_vary_headers(response, ('Cookie',)) if modified or settings.SESSION_SAVE_EVERY_REQUEST: if request.session.get_expire_at_browser_close(): max_age = None expires = None else: max_age = request.session.get_expiry_age() expires_time = time.time() + max_age expires = cookie_date(expires_time) # Save the session data and refresh the client cookie. # Skip session save for 500 responses, refs #3881. if response.status_code != 500: request.session.save() host = request.get_host().split(':')[0] session_cookie_domain = settings.SESSION_COOKIE_DOMAIN # The subdomains feature overrides the # SESSION_COOKIE_DOMAIN setting, since the setting # is a fixed value and with subdomains enabled, # the session cookie domain has to vary with the # subdomain. if settings.REALMS_HAVE_SUBDOMAINS: session_cookie_domain = host response.set_cookie(settings.SESSION_COOKIE_NAME, request.session.session_key, max_age=max_age, expires=expires, domain=session_cookie_domain, path=settings.SESSION_COOKIE_PATH, secure=settings.SESSION_COOKIE_SECURE or None, httponly=settings.SESSION_COOKIE_HTTPONLY or None) return response
def handle(self, *args, **options): # type: (*Any, **Any) -> None string_id = options["string_id"] name = options["name"] domain = options["domain"] if not name or not string_id: print("\033[1;31mPlease provide a name and string_id.\033[0m\n", file=sys.stderr) self.print_help("python manage.py", "create_realm") exit(1) if options[ "deployment_id"] is not None and not settings.ZILENCER_ENABLED: print( "\033[1;31mExternal deployments are not supported on voyager deployments.\033[0m\n", file=sys.stderr) exit(1) if domain is not None: self.validate_domain(domain) if get_realm_by_string_id(string_id) is not None: raise ValueError("string_id taken. Please choose another one.") realm, created = do_create_realm(string_id, name, org_type=options["org_type"]) if created: print(string_id, "created.") if domain: RealmAlias.objects.create(realm=realm, domain=domain) print("RealmAlias %s created for realm %s" % (domain, string_id)) if options["deployment_id"] is not None: deployment = Deployment.objects.get( id=options["deployment_id"]) deployment.realms.add(realm) deployment.save() print("Added to deployment", str(deployment.id)) elif settings.PRODUCTION and settings.ZILENCER_ENABLED: deployment = Deployment.objects.get( base_site_url="https://zulip.com/") deployment.realms.add(realm) deployment.save() # In the else case, we are not using the Deployments feature. set_default_streams(realm, ["social", "engineering"]) print( "\033[1;36mDefault streams set to social,engineering,zulip!\033[0m" ) else: print(string_id, "already exists.")
def handle(self, *args, **options): # type: (*Any, **str) -> None string_id = options['realm'] encoding = sys.getfilesystemencoding() stream_name = options['stream_name'] realm = get_realm_by_string_id(force_text(string_id, encoding)) if realm is None: print("Unknown string_id %s" % (string_id,)) exit(1) else: do_create_stream(realm, force_text(stream_name, encoding))
def create_preregistration_user(email, request, realm_creation=False): # type: (Text, HttpRequest, bool) -> HttpResponse realm_str = request.session.pop('realm_str', None) if realm_str is not None: # realm_str was set in accounts_home_with_realm_str. # The user is trying to sign up for a completely open realm, # so create them a PreregistrationUser for that realm return PreregistrationUser.objects.create(email=email, realm=get_realm_by_string_id(realm_str), realm_creation=realm_creation) return PreregistrationUser.objects.create(email=email, realm_creation=realm_creation)
def accounts_home_with_realm_str(request, realm_str): # type: (HttpRequest, str) -> HttpResponse if not settings.REALMS_HAVE_SUBDOMAINS and completely_open(get_realm_by_string_id(realm_str)): # You can sign up for a completely open realm through a # special registration path that contains the domain in the # URL. We store this information in the session rather than # elsewhere because we don't have control over URL or form # data for folks registering through OpenID. request.session["realm_str"] = realm_str return accounts_home(request) else: return HttpResponseRedirect(reverse('zerver.views.accounts_home'))
def handle(self, *args, **options): # type: (*Any, **str) -> None string_id = options['realm'] encoding = sys.getfilesystemencoding() stream_name = options['stream_name'] realm = get_realm_by_string_id(force_text(string_id, encoding)) if realm is None: print("Unknown string_id %s" % (string_id, )) exit(1) else: do_create_stream(realm, force_text(stream_name, encoding))
def handle(self, *args, **options): # type: (*Any, **Any) -> None realm = get_realm_by_string_id(options["string_id"]) streams = Stream.objects.filter(realm=realm, invite_only=False) recipients = Recipient.objects.filter( type=Recipient.STREAM, type_id__in=[stream.id for stream in streams]) cutoff = datetime.datetime.fromtimestamp(options["since"]) messages = Message.objects.filter(pub_date__gt=cutoff, recipient__in=recipients) for message in messages: print(message.to_dict(False))
def handle(self, **options): # type: (*Any, **str) -> None if options["string_id"] is None or options["streams"] is None: print("Please provide both a subdomain name or string_id and a default \ set of streams (which can be empty, with `--streams=`).", file=sys.stderr) exit(1) stream_dict = { stream.strip(): {"description": stream.strip(), "invite_only": False} for stream in options["streams"].split(",") } # type: Dict[Text, Dict[Text, Any]] realm = get_realm_by_string_id(options["string_id"]) set_default_streams(realm, stream_dict)
def handle(self, *args, **options): # type: (*Any, **str) -> None string_id = options['string_id'] old_name = options['old_name'] new_name = options['new_name'] encoding = sys.getfilesystemencoding() realm = get_realm_by_string_id(force_text(string_id, encoding)) if realm is None: print("Unknown subdomain or string_id %s" % (string_id,)) exit(1) do_rename_stream(realm, force_text(old_name, encoding), force_text(new_name, encoding))
def handle(self, *args, **options): # type: (*Any, **str) -> None if options["to"]: users = [get_user_profile_by_email(options["to"])] elif options["realm"]: realm = get_realm_by_string_id(options["realm"]) users = UserProfile.objects.filter(realm=realm, is_active=True, is_bot=False, is_mirror_dummy=False) elif options["server"] == "YES": users = UserProfile.objects.filter(is_active=True, is_bot=False, is_mirror_dummy=False) else: raise RuntimeError("Missing arguments") self.send(users)
def handle(self, *args, **options): # type: (*Any, **Any) -> None string_id = options["string_id"] name = options["name"] domain = options["domain"] if not name or not string_id: print("\033[1;31mPlease provide a name and string_id.\033[0m\n", file=sys.stderr) self.print_help("./manage.py", "create_realm") exit(1) if options["deployment_id"] is not None and not settings.ZILENCER_ENABLED: print("\033[1;31mExternal deployments are not supported on voyager deployments.\033[0m\n", file=sys.stderr) exit(1) if domain is not None: self.validate_domain(domain) if get_realm_by_string_id(string_id) is not None: raise ValueError("string_id taken. Please choose another one.") realm, created = do_create_realm(string_id, name, org_type=options["org_type"]) if created: print(string_id, "created.") if domain: RealmAlias.objects.create(realm=realm, domain=domain) print("RealmAlias %s created for realm %s" % (domain, string_id)) if options["deployment_id"] is not None: deployment = Deployment.objects.get(id=options["deployment_id"]) deployment.realms.add(realm) deployment.save() print("Added to deployment", str(deployment.id)) elif settings.PRODUCTION and settings.ZILENCER_ENABLED: deployment = Deployment.objects.get(base_site_url="https://zulip.com/") deployment.realms.add(realm) deployment.save() # In the else case, we are not using the Deployments feature. stream_dict = { "social": {"description": "For socializing", "invite_only": False}, "engineering": {"description": "For engineering", "invite_only": False} } # type: Dict[Text, Dict[Text, Any]] set_default_streams(realm, stream_dict) print("\033[1;36mDefault streams set to social,engineering,zulip!\033[0m") else: print(string_id, "already exists.")
def handle(self, **options): # type: (*Any, **str) -> None if options["string_id"] is None or options["streams"] is None: print( "Please provide both a subdomain name or string_id and a default \ set of streams (which can be empty, with `--streams=`).", file=sys.stderr) exit(1) stream_dict = { stream.strip(): { "description": stream.strip(), "invite_only": False } for stream in options["streams"].split(",") } # type: Dict[Text, Dict[Text, Any]] realm = get_realm_by_string_id(options["string_id"]) set_default_streams(realm, stream_dict)
def handle(self, *args, **options): # type: (*Any, **Any) -> None duplicates = False for email in options['emails']: try: get_user_profile_by_email(email) print( email + ": There is already a user registered with that address.") duplicates = True continue except UserProfile.DoesNotExist: pass if duplicates: return realm = None string_id = options["string_id"] if string_id: realm = get_realm_by_string_id(string_id) if not realm: print("The realm %s doesn't exist yet, please create it first." % (string_id, )) print("Don't forget default streams!") exit(1) for email in options['emails']: if realm: if not email_allowed_for_realm(email, realm) and not options["force"]: print( "You've asked to add an external user (%s) to a closed realm (%s)." % (email, string_id)) print("Are you sure? To do this, pass --force.") exit(1) else: prereg_user = PreregistrationUser(email=email, realm=realm) else: prereg_user = PreregistrationUser(email=email) prereg_user.save() print(email + ": " + Confirmation.objects.get_link_for_object( prereg_user, host=realm.host))
def handle(self, *args, **options): # type: (*Any, **str) -> None realm_name = options['realm'] try: realm = get_realm_by_string_id(realm_name) except Realm.DoesNotExist: print('There is no realm called %s.' % (realm_name,)) sys.exit(1) users = realm.get_admin_users() if users: print('Admins:\n') for user in users: print(' %s (%s)' % (user.email, user.full_name)) else: print('There are no admins for this realm!') print('\nYou can use the "knight" management command to knight admins.')
def add_settings(request): # type: (HttpRequest) -> Dict[str, Any] realm = None if hasattr(request.user, "realm"): realm = request.user.realm elif settings.REALMS_HAVE_SUBDOMAINS: subdomain = get_subdomain(request) realm = get_realm_by_string_id(subdomain) if realm is not None: realm_uri = realm.uri else: realm_uri = settings.SERVER_URI return { 'custom_logo_url': settings.CUSTOM_LOGO_URL, 'register_link_disabled': settings.REGISTER_LINK_DISABLED, 'login_link_disabled': settings.LOGIN_LINK_DISABLED, 'about_link_disabled': settings.ABOUT_LINK_DISABLED, 'show_oss_announcement': settings.SHOW_OSS_ANNOUNCEMENT, 'zulip_admin': settings.ZULIP_ADMINISTRATOR, 'terms_of_service': settings.TERMS_OF_SERVICE, 'login_url': settings.HOME_NOT_LOGGED_IN, 'only_sso': settings.ONLY_SSO, 'external_api_path': settings.EXTERNAL_API_PATH, 'external_api_uri': settings.EXTERNAL_API_URI, 'external_host': settings.EXTERNAL_HOST, 'external_uri_scheme': settings.EXTERNAL_URI_SCHEME, 'realm_uri': realm_uri, 'server_uri': settings.SERVER_URI, 'api_site_required': settings.EXTERNAL_API_PATH != "api.zulip.com", 'email_integration_enabled': settings.EMAIL_GATEWAY_BOT != "", 'email_gateway_example': settings.EMAIL_GATEWAY_EXAMPLE, 'open_realm_creation': settings.OPEN_REALM_CREATION, 'password_auth_enabled': password_auth_enabled(realm), 'dev_auth_enabled': dev_auth_enabled(realm), 'google_auth_enabled': google_auth_enabled(realm), 'github_auth_enabled': github_auth_enabled(realm), 'development_environment': settings.DEVELOPMENT, 'support_email': settings.ZULIP_ADMINISTRATOR, }
def clean_email(self): # type: () -> str """Returns the email if and only if the user's email address is allowed to join the realm they are trying to join.""" email = self.cleaned_data['email'] if get_unique_open_realm(): return email # Otherwise, the user is trying to join a specific realm. realm = None if self.string_id: realm = get_realm_by_string_id(self.string_id) elif not settings.REALMS_HAVE_SUBDOMAINS: realm = get_realm_by_email_domain(email) if realm is None: if settings.REALMS_HAVE_SUBDOMAINS: raise ValidationError( _("The organization you are trying to join does not exist." )) else: raise ValidationError( _("Your email address does not correspond to any existing organization." )) if realm.invite_required: raise ValidationError( _("Please request an invite from the organization administrator." )) if not email_allowed_for_realm(email, realm): raise ValidationError( _("The organization you are trying to join, %(string_id)s, only allows users with e-mail " "addresses within the organization. Please try a different e-mail address." % {'string_id': realm.string_id})) if realm.is_zephyr_mirror_realm: email_is_not_mit_mailing_list(email) return email
def add_settings(request): # type: (HttpRequest) -> Dict[str, Any] if hasattr(request.user, "realm"): realm = request.user.realm realm_uri = realm.uri else: if settings.REALMS_HAVE_SUBDOMAINS: subdomain = get_subdomain(request) realm = get_realm_by_string_id(subdomain) else: realm = None # TODO: Figure out how to add an assertion that this is not used realm_uri = settings.SERVER_URI return { 'custom_logo_url': settings.CUSTOM_LOGO_URL, 'register_link_disabled': settings.REGISTER_LINK_DISABLED, 'login_link_disabled': settings.LOGIN_LINK_DISABLED, 'about_link_disabled': settings.ABOUT_LINK_DISABLED, 'show_oss_announcement': settings.SHOW_OSS_ANNOUNCEMENT, 'zulip_admin': settings.ZULIP_ADMINISTRATOR, 'terms_of_service': settings.TERMS_OF_SERVICE, 'login_url': settings.HOME_NOT_LOGGED_IN, 'only_sso': settings.ONLY_SSO, 'external_api_path': settings.EXTERNAL_API_PATH, 'external_api_uri': settings.EXTERNAL_API_URI, 'external_host': settings.EXTERNAL_HOST, 'external_uri_scheme': settings.EXTERNAL_URI_SCHEME, 'realm_uri': realm_uri, 'server_uri': settings.SERVER_URI, 'api_site_required': settings.EXTERNAL_API_PATH != "api.zulip.com", 'email_integration_enabled': settings.EMAIL_GATEWAY_BOT != "", 'email_gateway_example': settings.EMAIL_GATEWAY_EXAMPLE, 'open_realm_creation': settings.OPEN_REALM_CREATION, 'password_auth_enabled': password_auth_enabled(realm), 'dev_auth_enabled': dev_auth_enabled(realm), 'google_auth_enabled': google_auth_enabled(realm), 'github_auth_enabled': github_auth_enabled(realm), 'development_environment': settings.DEVELOPMENT, 'support_email': settings.ZULIP_ADMINISTRATOR, }
def handle(self, *args, **options): # type: (*Any, **Any) -> None if not options["tos"]: raise CommandError("""You must confirm that this user has accepted the Terms of Service by passing --this-user-has-accepted-the-tos.""") if not options["string_id"]: raise CommandError("""Please specify a realm by passing --realm.""") try: realm = get_realm_by_string_id(options["string_id"]) except Realm.DoesNotExist: raise CommandError("Realm does not exist.") try: email = options['email'] full_name = options['full_name'] try: validators.validate_email(email) except ValidationError: raise CommandError("Invalid email address.") except KeyError: if 'email' in options or 'full_name' in options: raise CommandError("""Either specify an email and full name as two parameters, or specify no parameters for interactive user creation.""") else: while True: email = input("Email: ") try: validators.validate_email(email) break except ValidationError: print("Invalid email address.", file=sys.stderr) full_name = input("Full name: ") try: notify_new_user(do_create_user(email, initial_password(email), realm, full_name, email_to_username(email)), internal=True) except IntegrityError: raise CommandError("User already exists.")
def handle(self, *args, **options): # type: (*Any, **str) -> None realm_name = options['realm'] try: realm = get_realm_by_string_id(realm_name) except Realm.DoesNotExist: print('There is no realm called %s.' % (realm_name, )) sys.exit(1) users = realm.get_admin_users() if users: print('Admins:\n') for user in users: print(' %s (%s)' % (user.email, user.full_name)) else: print('There are no admins for this realm!') print( '\nYou can use the "knight" management command to knight admins.')
def handle(self, *args, **options): # type: (*Any, **str) -> None realm = get_realm_by_string_id(options["string_id"]) if options["op"] == "show": print("Aliases for %s:" % (realm.domain,)) for alias in realm_aliases(realm): print(alias) sys.exit(0) alias = options['alias'].lower() if options["op"] == "add": if not can_add_alias(alias): print("A Realm already exists for this domain, cannot add it as an alias for another realm!") sys.exit(1) RealmAlias.objects.create(realm=realm, domain=alias) sys.exit(0) elif options["op"] == "remove": RealmAlias.objects.get(realm=realm, domain=alias).delete() sys.exit(0) else: self.print_help("./manage.py", "realm_alias") sys.exit(1)
def clean_realm_subdomain(self): # type: () -> str if settings.REALMS_HAVE_SUBDOMAINS: error_strings = { 'too short': _("Subdomain needs to have length 3 or greater."), 'extremal dash': _("Subdomain cannot start or end with a '-'."), 'bad character': _("Subdomain can only have lowercase letters, numbers, and '-'s." ), 'unavailable': _("Subdomain unavailable. Please choose a different one.") } else: error_strings = { 'too short': _("Short name needs at least 3 characters."), 'extremal dash': _("Short name cannot start or end with a '-'."), 'bad character': _("Short name can only have lowercase letters, numbers, and '-'s." ), 'unavailable': _("Short name unavailable. Please choose a different one.") } subdomain = self.cleaned_data['realm_subdomain'] if not subdomain: return '' if len(subdomain) < 3: raise ValidationError(error_strings['too short']) if subdomain[0] == '-' or subdomain[-1] == '-': raise ValidationError(error_strings['extremal dash']) if not re.match('^[a-z0-9-]*$', subdomain): raise ValidationError(error_strings['bad character']) if is_reserved_subdomain(subdomain) or \ get_realm_by_string_id(subdomain) is not None: raise ValidationError(error_strings['unavailable']) return subdomain
def handle(self, *args, **options): # type: (*Any, **Any) -> None duplicates = False for email in options['emails']: try: get_user_profile_by_email(email) print(email + ": There is already a user registered with that address.") duplicates = True continue except UserProfile.DoesNotExist: pass if duplicates: return realm = None string_id = options["string_id"] if string_id: realm = get_realm_by_string_id(string_id) if not realm: print("The realm %s doesn't exist yet, please create it first." % (string_id,)) print("Don't forget default streams!") exit(1) for email in options['emails']: if realm: if not email_allowed_for_realm(email, realm) and not options["force"]: print("You've asked to add an external user (%s) to a closed realm (%s)." % ( email, string_id)) print("Are you sure? To do this, pass --force.") exit(1) else: prereg_user = PreregistrationUser(email=email, realm=realm) else: prereg_user = PreregistrationUser(email=email) prereg_user.save() print(email + ": " + Confirmation.objects.get_link_for_object(prereg_user, host=realm.host))
def handle(self, *args, **options): # type: (*Any, **str) -> None realm = get_realm_by_string_id(options["string_id"]) if options["op"] == "show": print("Aliases for %s:" % (realm.domain, )) for alias in realm_aliases(realm): print(alias) sys.exit(0) alias = options['alias'].lower() if options["op"] == "add": if not can_add_alias(alias): print( "A Realm already exists for this domain, cannot add it as an alias for another realm!" ) sys.exit(1) RealmAlias.objects.create(realm=realm, domain=alias) sys.exit(0) elif options["op"] == "remove": RealmAlias.objects.get(realm=realm, domain=alias).delete() sys.exit(0) else: self.print_help("./manage.py", "realm_alias") sys.exit(1)
def clean_email(self): # type: () -> str """Returns the email if and only if the user's email address is allowed to join the realm they are trying to join.""" data = self.cleaned_data['email'] # If the server has a unique open realm, pass if get_unique_open_realm(): return data # If a realm is specified and that realm is open, pass if completely_open(self.domain): return data # If the subdomain encodes a complete open realm, pass subdomain_realm = get_realm_by_string_id(self.subdomain) if (subdomain_realm is not None and completely_open(subdomain_realm.domain)): return data # If no realm is specified, fail realm = get_valid_realm(data) if realm is None: raise ValidationError(mark_safe(SIGNUP_STRING)) # If it's a clear realm not used for Zephyr mirroring, pass if not realm.is_zephyr_mirror_realm: return data # At this point, the user is trying to join a Zephyr mirroring # realm. We confirm that they are a real account (not a # mailing list), and if so, let them in. if not_mit_mailing_list(data): return data # Otherwise, the user is an MIT mailing list, and we return failure raise ValidationError(mark_safe(SIGNUP_STRING))
def handle(self, **options): # type: (**str) -> None if options["string_id"] is None and options["users"] is None: self.print_help("./manage.py", "turn_off_digests") exit(1) if options["string_id"]: realm = get_realm_by_string_id(options["string_id"]) user_profiles = UserProfile.objects.filter(realm=realm) else: emails = set([email.strip() for email in options["users"].split(",")]) user_profiles = [] for email in emails: user_profiles.append(get_user_profile_by_email(email)) print("Turned off digest emails for:") for user_profile in user_profiles: already_disabled_prefix = "" if user_profile.enable_digest_emails: do_change_enable_digest_emails(user_profile, False) else: already_disabled_prefix = "(already off) " print("%s%s <%s>" % (already_disabled_prefix, user_profile.full_name, user_profile.email))
def accounts_register(request): # type: (HttpRequest) -> HttpResponse key = request.POST['key'] confirmation = Confirmation.objects.get(confirmation_key=key) prereg_user = confirmation.content_object email = prereg_user.email realm_creation = prereg_user.realm_creation try: existing_user_profile = get_user_profile_by_email(email) except UserProfile.DoesNotExist: existing_user_profile = None validators.validate_email(email) # If OPEN_REALM_CREATION is enabled all user sign ups should go through the # special URL with domain name so that REALM can be identified if multiple realms exist unique_open_realm = get_unique_open_realm() if unique_open_realm is not None: realm = unique_open_realm elif prereg_user.referred_by: # If someone invited you, you are joining their realm regardless # of your e-mail address. realm = prereg_user.referred_by.realm elif prereg_user.realm: # You have a realm set, even though nobody referred you. This # happens if you sign up through a special URL for an open realm. realm = prereg_user.realm elif realm_creation: # For creating a new realm, there is no existing realm or domain realm = None elif settings.REALMS_HAVE_SUBDOMAINS: realm = get_realm_by_string_id(get_subdomain(request)) else: realm = get_realm_by_email_domain(email) if realm and not email_allowed_for_realm(email, realm): return render_to_response("zerver/closed_realm.html", {"closed_domain_name": realm.name}) if realm and realm.deactivated: # The user is trying to register for a deactivated realm. Advise them to # contact support. return render_to_response( "zerver/deactivated.html", { "deactivated_domain_name": realm.name, "zulip_administrator": settings.ZULIP_ADMINISTRATOR }) try: if existing_user_profile is not None and existing_user_profile.is_mirror_dummy: # Mirror dummy users to be activated must be inactive is_inactive(email) else: # Other users should not already exist at all. user_email_is_unique(email) except ValidationError: return HttpResponseRedirect( reverse('django.contrib.auth.views.login') + '?email=' + urllib.parse.quote_plus(email)) name_validated = False full_name = None if request.POST.get('from_confirmation'): try: del request.session['authenticated_full_name'] except KeyError: pass if realm is not None and realm.is_zephyr_mirror_realm: # For MIT users, we can get an authoritative name from Hesiod. # Technically we should check that this is actually an MIT # realm, but we can cross that bridge if we ever get a non-MIT # zephyr mirroring realm. hesiod_name = compute_mit_user_fullname(email) form = RegistrationForm( initial={ 'full_name': hesiod_name if "@" not in hesiod_name else "" }) name_validated = True elif settings.POPULATE_PROFILE_VIA_LDAP: for backend in get_backends(): if isinstance(backend, LDAPBackend): ldap_attrs = _LDAPUser( backend, backend.django_to_ldap_username(email)).attrs try: ldap_full_name = ldap_attrs[ settings.AUTH_LDAP_USER_ATTR_MAP['full_name']][0] request.session[ 'authenticated_full_name'] = ldap_full_name name_validated = True # We don't use initial= here, because if the form is # complete (that is, no additional fields need to be # filled out by the user) we want the form to validate, # so they can be directly registered without having to # go through this interstitial. form = RegistrationForm({'full_name': ldap_full_name}) # FIXME: This will result in the user getting # validation errors if they have to enter a password. # Not relevant for ONLY_SSO, though. break except TypeError: # Let the user fill out a name and/or try another backend form = RegistrationForm() elif 'full_name' in request.POST: form = RegistrationForm( initial={'full_name': request.POST.get('full_name')}) else: form = RegistrationForm() else: postdata = request.POST.copy() if name_changes_disabled(realm): # If we populate profile information via LDAP and we have a # verified name from you on file, use that. Otherwise, fall # back to the full name in the request. try: postdata.update( {'full_name': request.session['authenticated_full_name']}) name_validated = True except KeyError: pass form = RegistrationForm(postdata) if not password_auth_enabled(realm): form['password'].field.required = False if form.is_valid(): if password_auth_enabled(realm): password = form.cleaned_data['password'] else: # SSO users don't need no passwords password = None if realm_creation: string_id = form.cleaned_data['realm_subdomain'] realm_name = form.cleaned_data['realm_name'] org_type = int(form.cleaned_data['realm_org_type']) realm = do_create_realm(string_id, realm_name, org_type=org_type)[0] set_default_streams(realm, settings.DEFAULT_NEW_REALM_STREAMS) full_name = form.cleaned_data['full_name'] short_name = email_to_username(email) first_in_realm = len( UserProfile.objects.filter(realm=realm, is_bot=False)) == 0 # FIXME: sanitize email addresses and fullname if existing_user_profile is not None and existing_user_profile.is_mirror_dummy: try: user_profile = existing_user_profile do_activate_user(user_profile) do_change_password(user_profile, password) do_change_full_name(user_profile, full_name) except UserProfile.DoesNotExist: user_profile = do_create_user( email, password, realm, full_name, short_name, prereg_user=prereg_user, tos_version=settings.TOS_VERSION, newsletter_data={"IP": request.META['REMOTE_ADDR']}) else: user_profile = do_create_user( email, password, realm, full_name, short_name, prereg_user=prereg_user, tos_version=settings.TOS_VERSION, newsletter_data={"IP": request.META['REMOTE_ADDR']}) if first_in_realm: do_change_is_admin(user_profile, True) if realm_creation and settings.REALMS_HAVE_SUBDOMAINS: # Because for realm creation, registration happens on the # root domain, we need to log them into the subdomain for # their new realm. return redirect_and_log_into_subdomain(realm, full_name, email) # This dummy_backend check below confirms the user is # authenticating to the correct subdomain. return_data = {} # type: Dict[str, bool] auth_result = authenticate(username=user_profile.email, realm_subdomain=realm.subdomain, return_data=return_data, use_dummy_backend=True) if return_data.get('invalid_subdomain'): # By construction, this should never happen. logging.error("Subdomain mismatch in registration %s: %s" % ( realm.subdomain, user_profile.email, )) return redirect('/') login(request, auth_result) return HttpResponseRedirect(realm.uri + reverse('zerver.views.home')) return render_to_response( 'zerver/register.html', { 'form': form, 'email': email, 'key': key, 'full_name': request.session.get('authenticated_full_name', None), 'lock_name': name_validated and name_changes_disabled(realm), # password_auth_enabled is normally set via our context processor, # but for the registration form, there is no logged in user yet, so # we have to set it here. 'creating_new_team': realm_creation, 'realms_have_subdomains': settings.REALMS_HAVE_SUBDOMAINS, 'password_auth_enabled': password_auth_enabled(realm), }, request=request)
def accounts_register(request): # type: (HttpRequest) -> HttpResponse key = request.POST['key'] confirmation = Confirmation.objects.get(confirmation_key=key) prereg_user = confirmation.content_object email = prereg_user.email realm_creation = prereg_user.realm_creation try: existing_user_profile = get_user_profile_by_email(email) except UserProfile.DoesNotExist: existing_user_profile = None validators.validate_email(email) # If OPEN_REALM_CREATION is enabled all user sign ups should go through the # special URL with domain name so that REALM can be identified if multiple realms exist unique_open_realm = get_unique_open_realm() if unique_open_realm is not None: realm = unique_open_realm elif prereg_user.referred_by: # If someone invited you, you are joining their realm regardless # of your e-mail address. realm = prereg_user.referred_by.realm elif prereg_user.realm: # You have a realm set, even though nobody referred you. This # happens if you sign up through a special URL for an open realm. realm = prereg_user.realm elif realm_creation: # For creating a new realm, there is no existing realm or domain realm = None elif settings.REALMS_HAVE_SUBDOMAINS: realm = get_realm_by_string_id(get_subdomain(request)) else: realm = get_realm_by_email_domain(email) if realm and not email_allowed_for_realm(email, realm): return render_to_response("zerver/closed_realm.html", {"closed_domain_name": realm.name}) if realm and realm.deactivated: # The user is trying to register for a deactivated realm. Advise them to # contact support. return render_to_response("zerver/deactivated.html", {"deactivated_domain_name": realm.name, "zulip_administrator": settings.ZULIP_ADMINISTRATOR}) try: if existing_user_profile is not None and existing_user_profile.is_mirror_dummy: # Mirror dummy users to be activated must be inactive is_inactive(email) else: # Other users should not already exist at all. user_email_is_unique(email) except ValidationError: return HttpResponseRedirect(reverse('django.contrib.auth.views.login') + '?email=' + urllib.parse.quote_plus(email)) name_validated = False full_name = None if request.POST.get('from_confirmation'): try: del request.session['authenticated_full_name'] except KeyError: pass if realm is not None and realm.is_zephyr_mirror_realm: # For MIT users, we can get an authoritative name from Hesiod. # Technically we should check that this is actually an MIT # realm, but we can cross that bridge if we ever get a non-MIT # zephyr mirroring realm. hesiod_name = compute_mit_user_fullname(email) form = RegistrationForm( initial={'full_name': hesiod_name if "@" not in hesiod_name else ""}) name_validated = True elif settings.POPULATE_PROFILE_VIA_LDAP: for backend in get_backends(): if isinstance(backend, LDAPBackend): ldap_attrs = _LDAPUser(backend, backend.django_to_ldap_username(email)).attrs try: ldap_full_name = ldap_attrs[settings.AUTH_LDAP_USER_ATTR_MAP['full_name']][0] request.session['authenticated_full_name'] = ldap_full_name name_validated = True # We don't use initial= here, because if the form is # complete (that is, no additional fields need to be # filled out by the user) we want the form to validate, # so they can be directly registered without having to # go through this interstitial. form = RegistrationForm({'full_name': ldap_full_name}) # FIXME: This will result in the user getting # validation errors if they have to enter a password. # Not relevant for ONLY_SSO, though. break except TypeError: # Let the user fill out a name and/or try another backend form = RegistrationForm() elif 'full_name' in request.POST: form = RegistrationForm( initial={'full_name': request.POST.get('full_name')} ) else: form = RegistrationForm() else: postdata = request.POST.copy() if name_changes_disabled(realm): # If we populate profile information via LDAP and we have a # verified name from you on file, use that. Otherwise, fall # back to the full name in the request. try: postdata.update({'full_name': request.session['authenticated_full_name']}) name_validated = True except KeyError: pass form = RegistrationForm(postdata) if not password_auth_enabled(realm): form['password'].field.required = False if form.is_valid(): if password_auth_enabled(realm): password = form.cleaned_data['password'] else: # SSO users don't need no passwords password = None if realm_creation: string_id = form.cleaned_data['realm_subdomain'] realm_name = form.cleaned_data['realm_name'] org_type = int(form.cleaned_data['realm_org_type']) realm = do_create_realm(string_id, realm_name, org_type=org_type)[0] set_default_streams(realm, settings.DEFAULT_NEW_REALM_STREAMS) full_name = form.cleaned_data['full_name'] short_name = email_to_username(email) first_in_realm = len(UserProfile.objects.filter(realm=realm, is_bot=False)) == 0 # FIXME: sanitize email addresses and fullname if existing_user_profile is not None and existing_user_profile.is_mirror_dummy: try: user_profile = existing_user_profile do_activate_user(user_profile) do_change_password(user_profile, password) do_change_full_name(user_profile, full_name) except UserProfile.DoesNotExist: user_profile = do_create_user(email, password, realm, full_name, short_name, prereg_user=prereg_user, tos_version=settings.TOS_VERSION, newsletter_data={"IP": request.META['REMOTE_ADDR']}) else: user_profile = do_create_user(email, password, realm, full_name, short_name, prereg_user=prereg_user, tos_version=settings.TOS_VERSION, newsletter_data={"IP": request.META['REMOTE_ADDR']}) if first_in_realm: do_change_is_admin(user_profile, True) if realm_creation and settings.REALMS_HAVE_SUBDOMAINS: # Because for realm creation, registration happens on the # root domain, we need to log them into the subdomain for # their new realm. return redirect_and_log_into_subdomain(realm, full_name, email) # This dummy_backend check below confirms the user is # authenticating to the correct subdomain. return_data = {} # type: Dict[str, bool] auth_result = authenticate(username=user_profile.email, realm_subdomain=realm.subdomain, return_data=return_data, use_dummy_backend=True) if return_data.get('invalid_subdomain'): # By construction, this should never happen. logging.error("Subdomain mismatch in registration %s: %s" % ( realm.subdomain, user_profile.email,)) return redirect('/') login(request, auth_result) return HttpResponseRedirect(realm.uri + reverse('zerver.views.home')) return render_to_response('zerver/register.html', {'form': form, 'email': email, 'key': key, 'full_name': request.session.get('authenticated_full_name', None), 'lock_name': name_validated and name_changes_disabled(realm), # password_auth_enabled is normally set via our context processor, # but for the registration form, there is no logged in user yet, so # we have to set it here. 'creating_new_team': realm_creation, 'realms_have_subdomains': settings.REALMS_HAVE_SUBDOMAINS, 'password_auth_enabled': password_auth_enabled(realm), }, request=request)