Example #1
0
    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
Example #2
0
    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)
Example #3
0
    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)
                )
Example #4
0
    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
Example #5
0
    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, ))
Example #6
0
    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)
Example #7
0
 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
Example #8
0
    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
Example #9
0
    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)
Example #10
0
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)
Example #11
0
    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))
Example #12
0
    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)
Example #13
0
    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))
Example #14
0
    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, ))
Example #15
0
    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,))
Example #16
0
 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()
Example #17
0
 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!")
Example #18
0
 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!")
Example #19
0
    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
Example #20
0
    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.")
Example #21
0
    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))
Example #22
0
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)
Example #23
0
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'))
Example #24
0
    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))
Example #25
0
    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))
Example #26
0
    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)
Example #27
0
    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))
Example #28
0
 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)
Example #29
0
    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.")
Example #30
0
    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)
Example #31
0
    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))
Example #32
0
    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.')
Example #33
0
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,
    }
Example #34
0
    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
Example #35
0
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,
    }
Example #36
0
    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.")
Example #37
0
    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.')
Example #38
0
    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)
Example #39
0
 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
Example #40
0
    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))
Example #41
0
    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)
Example #42
0
    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))
Example #43
0
    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))
Example #44
0
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)
Example #45
0
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)