snapshot of https://github.com/zulip/zulip.git @ 48c69911c7dd4e03b20552eb3bd77ad8151c1357 (2026-09-15)
Some checks failed
Code scanning / CodeQL (push) Failing after 15s
Zulip production suite / Ubuntu 22.04 production build (push) Failing after 26s
Zulip production suite / Debian 12 production install with custom db name and user (push) Has been skipped
Zulip production suite / Ubuntu 22.04 production install and PostgreSQL upgrade with pgroonga (push) Has been skipped
Zulip production suite / Ubuntu 24.04 production install (push) Has been skipped
Zulip production suite / Ubuntu 26.04 production install (push) Has been skipped
Zulip production suite / Debian 13 production install (push) Has been skipped
Zulip production suite / 7.0 Version Upgrade (push) Has been skipped
Zulip production suite / 8.0 Version Upgrade (push) Has been skipped
Zulip production suite / 6.0 Version Upgrade (push) Has been skipped
Zulip production suite / 10.0 Version Upgrade (push) Has been skipped
Zulip production suite / 9.0 Version Upgrade (push) Has been skipped
Zulip production suite / 12.0 Version Upgrade (push) Has been skipped
Zulip production suite / 11.0 Version Upgrade (push) Has been skipped
GitHub Actions Security Analysis with zizmor / zizmor (push) Failing after 3s
Zulip CI / Debian 12 (Python 3.11, backend + documentation) (push) Failing after 26s
Zulip CI / Ubuntu 22.04 (Python 3.10, backend + frontend) (push) Failing after 3s
Zulip CI / Ubuntu 24.04 (Python 3.12, backend) (push) Failing after 25s
Zulip CI / Ubuntu 26.04 (Python 3.14, backend) (push) Failing after 25s
Zulip CI / Debian 13 (Python 3.13, backend) (push) Failing after 28s
Zulip production suite / Required jobs (push) Has been cancelled
Zulip CI / Required jobs (push) Has been cancelled
API Documentation Update Check / check-feature-level-updated (push) Has been cancelled
API Documentation Update Check / notify-if-api-docs-changed (push) Has been cancelled

This commit is contained in:
upstream-mirror
2026-09-15 15:05:30 +05:00
commit 64898b2c79
8999 changed files with 1757358 additions and 0 deletions

View File

@@ -0,0 +1,802 @@
# Generated by Django 5.0.7 on 2024-08-13 21:48
import logging
import bitfield.models
import django.contrib.auth.models
import django.contrib.postgres.indexes
import django.contrib.postgres.search
import django.core.validators
import django.db.models.deletion
import django.db.models.functions.text
import django.utils.timezone
from django.conf import settings
from django.db import connection, migrations, models, transaction
from django.db.backends.base.schema import BaseDatabaseSchemaEditor
from django.db.migrations.state import StateApps
from django.db.utils import InternalError
from zerver.models.streams import generate_email_token_for_stream
def set_up_fts_indexes(apps: StateApps, schema_editor: BaseDatabaseSchemaEditor) -> None:
# Duplicated in 0001_squashed_0569.py
with connection.cursor() as cursor:
try:
with transaction.atomic(savepoint=True):
cursor.execute(
"""
CREATE TEXT SEARCH DICTIONARY english_us_hunspell
(template = ispell, DictFile = en_us, AffFile = en_us, StopWords = zulip_english);
CREATE TEXT SEARCH CONFIGURATION zulip.english_us_search (COPY=pg_catalog.english);
ALTER TEXT SEARCH CONFIGURATION zulip.english_us_search
ALTER MAPPING FOR asciiword, asciihword, hword_asciipart, word, hword, hword_part
WITH english_us_hunspell, english_stem;
"""
)
except InternalError as e:
# If we have a remote PostgreSQL server, and we get an
# error about the tsearch_data paths, assume that we're
# running with a hosted PostgreSQL which we can't install
# our stemming/stopword dictionaries in; warn and carry
# on. For local PostgreSQL hosts, this is unexpected and
# we raise the error.
if (
settings.REMOTE_POSTGRES_HOST != ""
and e.__cause__
and "/tsearch_data/" in str(e.__cause__)
):
logging.warning(
"Remote PostgreSQL server %s is not configured with Zulip's improved stemming dictionaries; search quality will be degraded.",
settings.REMOTE_POSTGRES_HOST,
)
cursor.execute(
"""
CREATE TEXT SEARCH CONFIGURATION zulip.english_us_search (COPY=pg_catalog.english);
"""
)
else:
raise
cursor.execute(
"""
CREATE FUNCTION escape_html(text) RETURNS text IMMUTABLE LANGUAGE 'sql' AS $$
SELECT replace(replace(replace(replace(replace($1, '&', '&amp;'), '<', '&lt;'),
'>', '&gt;'), '"', '&quot;'), '''', '&#39;');
$$ ;
CREATE TABLE fts_update_log (id SERIAL PRIMARY KEY, message_id INTEGER NOT NULL);
CREATE FUNCTION do_notify_fts_update_log() RETURNS trigger LANGUAGE plpgsql AS
$$ BEGIN NOTIFY fts_update_log; RETURN NEW; END $$;
CREATE TRIGGER fts_update_log_notify AFTER INSERT ON fts_update_log
FOR EACH STATEMENT EXECUTE PROCEDURE do_notify_fts_update_log();
CREATE FUNCTION append_to_fts_update_log() RETURNS trigger LANGUAGE plpgsql AS
$$ BEGIN INSERT INTO fts_update_log (message_id) VALUES (NEW.id); RETURN NEW; END $$;
CREATE TRIGGER zerver_message_update_search_tsvector_async
BEFORE INSERT OR UPDATE OF subject, rendered_content ON zerver_message
FOR EACH ROW EXECUTE PROCEDURE append_to_fts_update_log();
"""
)
class Migration(migrations.Migration):
initial = True
dependencies = [
("auth", "0001_initial"),
]
operations = [
migrations.RunSQL(sql="ALTER ROLE CURRENT_USER SET search_path TO zulip,public"),
migrations.CreateModel(
name="Recipient",
fields=[
(
"id",
models.AutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
),
),
("type_id", models.IntegerField(db_index=True)),
("type", models.PositiveSmallIntegerField(db_index=True)),
],
options={
"unique_together": {("type", "type_id")},
},
),
migrations.CreateModel(
name="Huddle",
fields=[
(
"id",
models.AutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
),
),
("huddle_hash", models.CharField(db_index=True, max_length=40, unique=True)),
],
),
migrations.CreateModel(
name="Realm",
fields=[
(
"id",
models.AutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
),
),
("domain", models.CharField(db_index=True, max_length=40, unique=True)),
("name", models.CharField(max_length=40, null=True)),
("restricted_to_domain", models.BooleanField(default=True)),
("invite_required", models.BooleanField(default=False)),
("invite_by_admins_only", models.BooleanField(default=False)),
("mandatory_topics", models.BooleanField(default=False)),
("show_digest_email", models.BooleanField(default=True)),
("name_changes_disabled", models.BooleanField(default=False)),
("date_created", models.DateTimeField(default=django.utils.timezone.now)),
("deactivated", models.BooleanField(default=False)),
("create_stream_by_admins_only", models.BooleanField(default=False)),
("allow_message_editing", models.BooleanField(default=True)),
("message_content_edit_limit_seconds", models.IntegerField(default=600)),
("default_language", models.CharField(default="en", max_length=50)),
],
options={
"permissions": (
("administer", "Administer a realm"),
("api_super_user", "Can send messages as other users for mirroring"),
),
},
),
migrations.CreateModel(
name="RealmAlias",
fields=[
(
"id",
models.AutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
),
),
("domain", models.CharField(db_index=True, max_length=80, unique=True)),
(
"realm",
models.ForeignKey(
null=True, on_delete=django.db.models.deletion.CASCADE, to="zerver.realm"
),
),
],
),
migrations.CreateModel(
name="ScheduledJob",
fields=[
(
"id",
models.AutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
),
),
("scheduled_timestamp", models.DateTimeField()),
("type", models.PositiveSmallIntegerField()),
("data", models.TextField()),
("filter_id", models.IntegerField(null=True)),
("filter_string", models.CharField(max_length=100)),
],
),
migrations.CreateModel(
name="Client",
fields=[
(
"id",
models.AutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
),
),
("name", models.CharField(db_index=True, max_length=30, unique=True)),
],
),
migrations.CreateModel(
name="UserProfile",
fields=[
(
"id",
models.AutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
),
),
("password", models.CharField(max_length=128, verbose_name="password")),
(
"last_login",
models.DateTimeField(blank=True, null=True, verbose_name="last login"),
),
(
"is_superuser",
models.BooleanField(
default=False,
help_text="Designates that this user has all permissions without explicitly assigning them.",
verbose_name="superuser status",
),
),
("email", models.EmailField(db_index=True, max_length=254, unique=True)),
("is_staff", models.BooleanField(default=False)),
("is_active", models.BooleanField(db_index=True, default=True)),
("is_bot", models.BooleanField(db_index=True, default=False)),
("date_joined", models.DateTimeField(default=django.utils.timezone.now)),
("is_mirror_dummy", models.BooleanField(default=False)),
("full_name", models.CharField(max_length=100)),
("short_name", models.CharField(max_length=100)),
("pointer", models.IntegerField()),
("last_pointer_updater", models.CharField(max_length=64)),
("api_key", models.CharField(max_length=32)),
("enable_stream_desktop_notifications", models.BooleanField(default=False)),
("enable_stream_sounds", models.BooleanField(default=False)),
("enable_desktop_notifications", models.BooleanField(default=True)),
("enable_sounds", models.BooleanField(default=True)),
("enable_offline_email_notifications", models.BooleanField(default=True)),
("enable_offline_push_notifications", models.BooleanField(default=True)),
("enable_digest_emails", models.BooleanField(default=True)),
("default_desktop_notifications", models.BooleanField(default=True)),
(
"last_reminder",
models.DateTimeField(default=django.utils.timezone.now, null=True),
),
("rate_limits", models.CharField(default="", max_length=100)),
("default_all_public_streams", models.BooleanField(default=False)),
("enter_sends", models.BooleanField(default=True, null=True)),
("autoscroll_forever", models.BooleanField(default=False)),
("twenty_four_hour_time", models.BooleanField(default=False)),
(
"avatar_source",
models.CharField(
choices=[
("G", "Hosted by Gravatar"),
("U", "Uploaded by user"),
("S", "System generated"),
],
default="G",
max_length=1,
),
),
(
"tutorial_status",
models.CharField(
choices=[("W", "Waiting"), ("S", "Started"), ("F", "Finished")],
default="W",
max_length=1,
),
),
("onboarding_steps", models.TextField(default="[]")),
("invites_granted", models.IntegerField(default=0)),
("invites_used", models.IntegerField(default=0)),
("alert_words", models.TextField(default="[]")),
("muted_topics", models.TextField(default="[]")),
(
"bot_owner",
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.SET_NULL,
to=settings.AUTH_USER_MODEL,
),
),
(
"groups",
models.ManyToManyField(
blank=True,
help_text="The groups this user belongs to. A user will get all permissions granted to each of their groups.",
related_name="user_set",
related_query_name="user",
to="auth.group",
verbose_name="groups",
),
),
(
"realm",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE, to="zerver.realm"
),
),
(
"user_permissions",
models.ManyToManyField(
blank=True,
help_text="Specific permissions for this user.",
related_name="user_set",
related_query_name="user",
to="auth.permission",
verbose_name="user permissions",
),
),
("left_side_userlist", models.BooleanField(default=False)),
("is_api_super_user", models.BooleanField(db_index=True, default=False)),
("is_realm_admin", models.BooleanField(db_index=True, default=False)),
("bot_type", models.PositiveSmallIntegerField(db_index=True, null=True)),
("default_language", models.CharField(default="en", max_length=50)),
("tos_version", models.CharField(max_length=10, null=True)),
],
options={
"abstract": False,
},
),
migrations.CreateModel(
name="Message",
fields=[
(
"id",
models.AutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
),
),
("subject", models.CharField(db_index=True, max_length=60)),
("content", models.TextField()),
("rendered_content", models.TextField(null=True)),
("rendered_content_version", models.IntegerField(null=True)),
("pub_date", models.DateTimeField(db_index=True, verbose_name="date published")),
("last_edit_time", models.DateTimeField(null=True)),
("edit_history", models.TextField(null=True)),
("has_attachment", models.BooleanField(db_index=True, default=False)),
("has_image", models.BooleanField(db_index=True, default=False)),
("has_link", models.BooleanField(db_index=True, default=False)),
(
"recipient",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE, to="zerver.recipient"
),
),
(
"sender",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL
),
),
(
"sending_client",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE, to="zerver.client"
),
),
("search_tsvector", django.contrib.postgres.search.SearchVectorField(null=True)),
],
),
migrations.CreateModel(
name="UserActivityInterval",
fields=[
(
"id",
models.AutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
),
),
("start", models.DateTimeField(db_index=True, verbose_name="start time")),
("end", models.DateTimeField(db_index=True, verbose_name="end time")),
(
"user_profile",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL
),
),
],
),
migrations.CreateModel(
name="UserPresence",
fields=[
(
"id",
models.AutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
),
),
("timestamp", models.DateTimeField(verbose_name="presence changed")),
("status", models.PositiveSmallIntegerField(default=1)),
(
"client",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE, to="zerver.client"
),
),
(
"user_profile",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL
),
),
],
options={
"unique_together": {("user_profile", "client")},
},
),
migrations.CreateModel(
name="UserMessage",
fields=[
(
"id",
models.AutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
),
),
(
"flags",
bitfield.models.BitField(
[
"read",
"starred",
"collapsed",
"mentioned",
"wildcard_mentioned",
"summarize_in_home",
"summarize_in_stream",
"force_expand",
"force_collapse",
"has_alert_word",
"historical",
"is_me_message",
],
default=0,
),
),
(
"message",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE, to="zerver.message"
),
),
(
"user_profile",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL
),
),
],
options={
"unique_together": {("user_profile", "message")},
},
),
migrations.CreateModel(
name="UserActivity",
fields=[
(
"id",
models.AutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
),
),
("query", models.CharField(db_index=True, max_length=50)),
("count", models.IntegerField()),
("last_visit", models.DateTimeField(verbose_name="last visit")),
(
"client",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE, to="zerver.client"
),
),
(
"user_profile",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL
),
),
],
options={
"unique_together": {("user_profile", "client", "query")},
},
),
migrations.CreateModel(
name="Stream",
fields=[
(
"id",
models.AutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
),
),
("name", models.CharField(db_index=True, max_length=60)),
("invite_only", models.BooleanField(default=False, null=True)),
(
"email_token",
models.CharField(default=generate_email_token_for_stream, max_length=32),
),
("description", models.CharField(default="", max_length=1024)),
("date_created", models.DateTimeField(default=django.utils.timezone.now)),
("deactivated", models.BooleanField(default=False)),
(
"realm",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE, to="zerver.realm"
),
),
],
options={
"unique_together": {("name", "realm")},
},
),
migrations.CreateModel(
name="RealmFilter",
fields=[
(
"id",
models.AutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
),
),
("pattern", models.TextField()),
("url_format_string", models.TextField()),
(
"realm",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE, to="zerver.realm"
),
),
],
options={
"unique_together": {("realm", "pattern")},
},
),
migrations.CreateModel(
name="DefaultStream",
fields=[
(
"id",
models.AutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
),
),
(
"realm",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE, to="zerver.realm"
),
),
(
"stream",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE, to="zerver.stream"
),
),
],
options={
"unique_together": {("realm", "stream")},
},
),
migrations.CreateModel(
name="PushDeviceToken",
fields=[
(
"id",
models.AutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
),
),
("kind", models.PositiveSmallIntegerField(choices=[(1, "apns"), (2, "gcm")])),
("token", models.CharField(max_length=4096, unique=True)),
("last_updated", models.DateTimeField(auto_now=True)),
("ios_app_id", models.TextField(null=True)),
(
"user",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL
),
),
],
),
migrations.CreateModel(
name="Referral",
fields=[
(
"id",
models.AutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
),
),
("email", models.EmailField(max_length=254)),
("timestamp", models.DateTimeField(auto_now_add=True)),
(
"user_profile",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL
),
),
],
),
migrations.CreateModel(
name="RealmEmoji",
fields=[
(
"id",
models.AutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
),
),
(
"name",
models.TextField(
validators=[
django.core.validators.MinLengthValidator(1),
django.core.validators.RegexValidator(
message="Invalid characters in emoji name",
regex="^[0-9a-zA-Z.\\-_]+(?<![.\\-_])$",
),
]
),
),
("img_url", models.URLField(max_length=1000)),
(
"realm",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE, to="zerver.realm"
),
),
],
options={
"unique_together": {("realm", "name")},
},
),
migrations.CreateModel(
name="PreregistrationUser",
fields=[
(
"id",
models.AutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
),
),
("email", models.EmailField(max_length=254)),
("invited_at", models.DateTimeField(auto_now=True)),
("status", models.IntegerField(default=0)),
(
"realm",
models.ForeignKey(
null=True, on_delete=django.db.models.deletion.CASCADE, to="zerver.realm"
),
),
(
"referred_by",
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.CASCADE,
to=settings.AUTH_USER_MODEL,
),
),
("realm_creation", models.BooleanField(default=False)),
],
),
migrations.CreateModel(
name="Attachment",
fields=[
(
"id",
models.AutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
),
),
("file_name", models.CharField(db_index=True, max_length=100)),
("path_id", models.TextField(db_index=True)),
(
"create_time",
models.DateTimeField(db_index=True, default=django.utils.timezone.now),
),
("messages", models.ManyToManyField(to="zerver.message")),
(
"owner",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL
),
),
("is_realm_public", models.BooleanField(default=False)),
(
"realm",
models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.CASCADE,
to="zerver.realm",
),
),
],
),
migrations.CreateModel(
name="Subscription",
fields=[
(
"id",
models.AutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
),
),
("active", models.BooleanField(default=True)),
("in_home_view", models.BooleanField(default=True, null=True)),
("color", models.CharField(default="#c2c2c2", max_length=10)),
("desktop_notifications", models.BooleanField(default=True)),
("audible_notifications", models.BooleanField(default=True)),
("notifications", models.BooleanField(default=False)),
(
"recipient",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE, to="zerver.recipient"
),
),
(
"user_profile",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL
),
),
("pin_to_top", models.BooleanField(default=False)),
],
options={
"unique_together": {("user_profile", "recipient")},
},
),
# These indexes seem to not squash properly.
migrations.AddIndex(
model_name="userprofile",
index=models.Index(
django.db.models.functions.text.Upper("email"), name="upper_userprofile_email_idx"
),
),
migrations.AddIndex(
model_name="preregistrationuser",
index=models.Index(
django.db.models.functions.text.Upper("email"),
name="upper_preregistration_email_idx",
),
),
migrations.AddIndex(
model_name="message",
index=django.contrib.postgres.indexes.GinIndex(
models.F("search_tsvector"), fastupdate=False, name="zerver_message_search_tsvector"
),
),
migrations.AddIndex(
model_name="message",
index=models.Index(
django.db.models.functions.text.Upper("subject"), name="upper_subject_idx"
),
),
migrations.AddIndex(
model_name="stream",
index=models.Index(
django.db.models.functions.text.Upper("name"), name="upper_stream_name_idx"
),
),
migrations.AlterModelManagers(
name="userprofile",
managers=[
("objects", django.contrib.auth.models.UserManager()),
],
),
migrations.AddField(
model_name="preregistrationuser",
name="streams",
field=models.ManyToManyField(to="zerver.stream"),
),
# AddField operations that create import cycles should happen
# after those that can be squashed.
migrations.AddField(
model_name="realm",
name="notifications_stream",
field=models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.CASCADE,
related_name="+",
to="zerver.stream",
),
),
migrations.AddField(
model_name="userprofile",
name="default_events_register_stream",
field=models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.CASCADE,
related_name="+",
to="zerver.stream",
),
),
migrations.AddField(
model_name="userprofile",
name="default_sending_stream",
field=models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.CASCADE,
related_name="+",
to="zerver.stream",
),
),
migrations.RunPython(set_up_fts_indexes),
]

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,35 @@
from django.conf import settings
from django.core.exceptions import ObjectDoesNotExist
from django.db import migrations, models
from django.db.backends.base.schema import BaseDatabaseSchemaEditor
from django.db.migrations.state import StateApps
def set_subdomain_of_default_realm(
apps: StateApps, schema_editor: BaseDatabaseSchemaEditor
) -> None:
if settings.DEVELOPMENT:
Realm = apps.get_model("zerver", "Realm")
try:
default_realm = Realm.objects.get(domain="zulip.com")
except ObjectDoesNotExist:
default_realm = None
if default_realm is not None:
default_realm.subdomain = "zulip"
default_realm.save()
class Migration(migrations.Migration):
dependencies = [
("zerver", "0001_initial"),
]
operations = [
migrations.AddField(
model_name="realm",
name="subdomain",
field=models.CharField(max_length=40, unique=True, null=True),
),
migrations.RunPython(set_subdomain_of_default_realm, elidable=True),
]

View File

@@ -0,0 +1,17 @@
from django.db import migrations, models
CORPORATE = 1
class Migration(migrations.Migration):
dependencies = [
("zerver", "0029_realm_subdomain"),
]
operations = [
migrations.AddField(
model_name="realm",
name="org_type",
field=models.PositiveSmallIntegerField(default=CORPORATE),
),
]

View File

@@ -0,0 +1,23 @@
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("zerver", "0030_realm_org_type"),
]
operations = [
migrations.AlterField(
model_name="userprofile",
name="avatar_source",
field=models.CharField(
choices=[
("G", "Hosted by Gravatar"),
("J", "Generated using Jdenticon"),
("U", "Uploaded by user"),
],
max_length=1,
default="J",
),
),
]

View File

@@ -0,0 +1,39 @@
import hashlib
from unittest.mock import patch
from django.conf import settings
from django.db import migrations
from django.db.backends.base.schema import BaseDatabaseSchemaEditor
from django.db.migrations.state import StateApps
from zerver.lib.upload import ensure_avatar_image
from zerver.models import UserProfile
# We hackishly patch this function in order to revert it to the state
# it had when this migration was first written. This is a balance
# between copying in a historical version of hundreds of lines of code
# from zerver.lib.upload (which would pretty annoying, but would be a
# pain) and just using the current version, which doesn't work
# since we rearranged the avatars in Zulip 1.6.
def patched_user_avatar_path(user_profile: UserProfile) -> str:
email = user_profile.email
user_key = email.lower() + settings.AVATAR_SALT
return hashlib.sha1(user_key.encode()).hexdigest()
@patch("zerver.lib.upload.user_avatar_path", patched_user_avatar_path)
def verify_medium_avatar_image(apps: StateApps, schema_editor: BaseDatabaseSchemaEditor) -> None:
user_profile_model = apps.get_model("zerver", "UserProfile")
for user_profile in user_profile_model.objects.filter(avatar_source="U"):
ensure_avatar_image(user_profile, medium=True)
class Migration(migrations.Migration):
dependencies = [
("zerver", "0031_remove_system_avatar_source"),
]
operations = [
migrations.RunPython(verify_medium_avatar_image, elidable=True),
]

View File

@@ -0,0 +1,25 @@
from django.db import migrations
from django.db.backends.base.schema import BaseDatabaseSchemaEditor
from django.db.migrations.state import StateApps
def add_domain_to_realm_alias_if_needed(
apps: StateApps, schema_editor: BaseDatabaseSchemaEditor
) -> None:
Realm = apps.get_model("zerver", "Realm")
RealmAlias = apps.get_model("zerver", "RealmAlias")
for realm in Realm.objects.all().iterator():
# if realm.domain already exists in RealmAlias, assume it is correct
if not RealmAlias.objects.filter(domain=realm.domain).exists():
RealmAlias.objects.create(realm=realm, domain=realm.domain)
class Migration(migrations.Migration):
dependencies = [
("zerver", "0032_verify_all_medium_avatar_images"),
]
operations = [
migrations.RunPython(add_domain_to_realm_alias_if_needed, elidable=True),
]

View File

@@ -0,0 +1,15 @@
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("zerver", "0033_migrate_domain_to_realmalias"),
]
operations = [
migrations.AddField(
model_name="userprofile",
name="enable_online_push_notifications",
field=models.BooleanField(default=False),
),
]

View File

@@ -0,0 +1,15 @@
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("zerver", "0034_userprofile_enable_online_push_notifications"),
]
operations = [
migrations.AddField(
model_name="realm",
name="message_retention_days",
field=models.IntegerField(null=True),
),
]

View File

@@ -0,0 +1,15 @@
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
("zerver", "0035_realm_message_retention_period_days"),
]
operations = [
migrations.RenameField(
model_name="realm",
old_name="subdomain",
new_name="string_id",
),
]

View File

@@ -0,0 +1,41 @@
from django.db import migrations, models
from django.db.backends.base.schema import BaseDatabaseSchemaEditor
from django.db.migrations.state import StateApps
from django.db.utils import IntegrityError
def set_string_id_using_domain(apps: StateApps, schema_editor: BaseDatabaseSchemaEditor) -> None:
Realm = apps.get_model("zerver", "Realm")
for realm in Realm.objects.all().iterator():
if not realm.string_id:
prefix = realm.domain.split(".")[0]
try:
realm.string_id = prefix
realm.save(update_fields=["string_id"])
continue
except IntegrityError:
pass
for i in range(1, 100):
try:
realm.string_id = prefix + str(i)
realm.save(update_fields=["string_id"])
break
except IntegrityError:
pass
else:
raise RuntimeError(f"Unable to find a good string_id for realm {realm}")
class Migration(migrations.Migration):
dependencies = [
("zerver", "0036_rename_subdomain_to_string_id"),
]
operations = [
migrations.RunPython(set_string_id_using_domain, elidable=True),
migrations.AlterField(
model_name="realm",
name="string_id",
field=models.CharField(unique=True, max_length=40),
),
]

View File

@@ -0,0 +1,27 @@
from django.db import migrations, models
COMMUNITY = 2
class Migration(migrations.Migration):
dependencies = [
("zerver", "0037_disallow_null_string_id"),
]
operations = [
migrations.AlterField(
model_name="realm",
name="invite_required",
field=models.BooleanField(default=True),
),
migrations.AlterField(
model_name="realm",
name="org_type",
field=models.PositiveSmallIntegerField(default=COMMUNITY),
),
migrations.AlterField(
model_name="realm",
name="restricted_to_domain",
field=models.BooleanField(default=False),
),
]

View File

@@ -0,0 +1,15 @@
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("zerver", "0038_realm_change_to_community_defaults"),
]
operations = [
migrations.AlterField(
model_name="realmalias",
name="domain",
field=models.CharField(max_length=80, db_index=True),
),
]

View File

@@ -0,0 +1,18 @@
import bitfield.models
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
("zerver", "0039_realmalias_drop_uniqueness"),
]
operations = [
migrations.AddField(
model_name="realm",
name="authentication_methods",
field=bitfield.models.BitField(
["Google", "Email", "GitHub", "LDAP", "Dev", "RemoteUser"], default=2147483647
),
),
]

View File

@@ -0,0 +1,60 @@
import os
import re
from django.db import migrations, models
from django.db.backends.base.schema import BaseDatabaseSchemaEditor
from django.db.migrations.state import StateApps
attachment_url_re = re.compile(r"[/\-]user[\-_]uploads[/\.-].*?(?=[ )]|\Z)")
def attachment_url_to_path_id(attachment_url: str) -> str:
path_id_raw = re.sub(r"[/\-]user[\-_]uploads[/\.-]", "", attachment_url)
# Remove any extra '.' after file extension. These are probably added by the user
return re.sub(r"[.]+$", "", path_id_raw, flags=re.MULTILINE)
def check_and_create_attachments(apps: StateApps, schema_editor: BaseDatabaseSchemaEditor) -> None:
STREAM = 2
Message = apps.get_model("zerver", "Message")
Attachment = apps.get_model("zerver", "Attachment")
Stream = apps.get_model("zerver", "Stream")
for message in Message.objects.filter(has_attachment=True, attachment=None):
attachment_url_list = attachment_url_re.findall(message.content)
for url in attachment_url_list:
path_id = attachment_url_to_path_id(url)
user_profile = message.sender
is_message_realm_public = False
if message.recipient.type == STREAM:
stream = Stream.objects.get(id=message.recipient.type_id)
is_message_realm_public = (
not stream.invite_only and stream.realm.domain != "mit.edu"
)
if path_id is not None:
attachment = Attachment.objects.create(
file_name=os.path.basename(path_id),
path_id=path_id,
owner=user_profile,
realm=user_profile.realm,
is_realm_public=is_message_realm_public,
)
attachment.messages.add(message)
class Migration(migrations.Migration):
dependencies = [
("zerver", "0040_realm_authentication_methods"),
]
operations = [
# The TextField change was originally in the next migration,
# but because it fixes a problem that causes the RunPython
# part of this migration to crash, we've copied it here.
migrations.AlterField(
model_name="attachment",
name="file_name",
field=models.TextField(db_index=True),
),
migrations.RunPython(check_and_create_attachments, elidable=True),
]

View File

@@ -0,0 +1,15 @@
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("zerver", "0041_create_attachments_for_old_messages"),
]
operations = [
migrations.AlterField(
model_name="attachment",
name="file_name",
field=models.TextField(db_index=True),
),
]

View File

@@ -0,0 +1,9 @@
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
("zerver", "0042_attachment_file_name_length"),
]
operations = []

View File

@@ -0,0 +1,41 @@
import django.db.models.deletion
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("zerver", "0043_realm_filter_validators"),
]
operations = [
migrations.CreateModel(
name="Reaction",
fields=[
(
"id",
models.AutoField(
verbose_name="ID", serialize=False, auto_created=True, primary_key=True
),
),
(
"user_profile",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL
),
),
(
"message",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE, to="zerver.Message"
),
),
("emoji_name", models.TextField()),
],
bases=(models.Model,),
),
migrations.AlterUniqueTogether(
name="reaction",
unique_together={("user_profile", "message", "emoji_name")},
),
]

View File

@@ -0,0 +1,15 @@
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("zerver", "0044_reaction"),
]
operations = [
migrations.AddField(
model_name="realm",
name="waiting_period_threshold",
field=models.PositiveIntegerField(default=0),
),
]

View File

@@ -0,0 +1,23 @@
# Generated by Django 1.10.4 on 2016-12-20 07:02
import django.db.models.deletion
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("zerver", "0045_realm_waiting_period_threshold"),
]
operations = [
migrations.AddField(
model_name="realmemoji",
name="author",
field=models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.CASCADE,
to=settings.AUTH_USER_MODEL,
),
),
]

View File

@@ -0,0 +1,16 @@
# Generated by Django 1.10.4 on 2016-12-20 13:45
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("zerver", "0046_realmemoji_author"),
]
operations = [
migrations.AddField(
model_name="realm",
name="add_emoji_by_admins_only",
field=models.BooleanField(default=False),
),
]

View File

@@ -0,0 +1,16 @@
# Generated by Django 1.10.4 on 2016-12-29 02:18
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("zerver", "0047_realm_add_emoji_by_admins_only"),
]
operations = [
migrations.AlterField(
model_name="userprofile",
name="enter_sends",
field=models.BooleanField(null=True, default=False),
),
]

View File

@@ -0,0 +1,15 @@
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("zerver", "0048_enter_sends_default_to_false"),
]
operations = [
migrations.AddField(
model_name="userprofile",
name="pm_content_in_desktop_notifications",
field=models.BooleanField(default=True),
),
]

View File

@@ -0,0 +1,16 @@
# Generated by Django 1.10.5 on 2017-01-23 17:44
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("zerver", "0049_userprofile_pm_content_in_desktop_notifications"),
]
operations = [
migrations.AddField(
model_name="userprofile",
name="avatar_version",
field=models.PositiveSmallIntegerField(default=1),
),
]

View File

@@ -0,0 +1,20 @@
# Generated by Django 1.10.5 on 2017-01-25 20:55
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("zerver", "0050_userprofile_avatar_version"),
]
operations = [
migrations.AddField(
model_name="realmalias",
name="allow_subdomains",
field=models.BooleanField(default=False),
),
migrations.AlterUniqueTogether(
name="realmalias",
unique_together={("realm", "domain")},
),
]

View File

@@ -0,0 +1,17 @@
# Generated by Django 1.10.5 on 2017-02-11 03:07
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("zerver", "0051_realmalias_add_allow_subdomains"),
]
operations = [
migrations.AlterField(
model_name="realmalias",
name="realm",
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to="zerver.Realm"),
),
]

View File

@@ -0,0 +1,40 @@
# Generated by Django 1.10.5 on 2017-02-23 05:37
import django.db.models.deletion
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("zerver", "0052_auto_fix_realmalias_realm_nullable"),
]
operations = [
migrations.CreateModel(
name="EmailChangeStatus",
fields=[
(
"id",
models.AutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
),
),
("new_email", models.EmailField(max_length=254)),
("old_email", models.EmailField(max_length=254)),
("updated_at", models.DateTimeField(auto_now=True)),
("status", models.IntegerField(default=0)),
(
"realm",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE, to="zerver.Realm"
),
),
(
"user_profile",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL
),
),
],
),
]

View File

@@ -0,0 +1,25 @@
# Generated by Django 1.10.5 on 2017-02-15 06:18
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("zerver", "0053_emailchangestatus"),
]
operations = [
migrations.AddField(
model_name="realm",
name="icon_source",
field=models.CharField(
choices=[("G", "Hosted by Gravatar"), ("U", "Uploaded by administrator")],
default="G",
max_length=1,
),
),
migrations.AddField(
model_name="realm",
name="icon_version",
field=models.PositiveSmallIntegerField(default=1),
),
]

View File

@@ -0,0 +1,16 @@
# Generated by Django 1.10.5 on 2017-03-01 06:28
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("zerver", "0054_realm_icon"),
]
operations = [
migrations.AddField(
model_name="attachment",
name="size",
field=models.IntegerField(null=True),
),
]

View File

@@ -0,0 +1,16 @@
# Generated by Django 1.10.5 on 2017-03-02 07:28
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("zerver", "0055_attachment_size"),
]
operations = [
migrations.AddField(
model_name="userprofile",
name="emoji_alt_code",
field=models.BooleanField(default=False),
),
]

View File

@@ -0,0 +1,95 @@
# Generated by Django 1.10.5 on 2017-03-04 07:33
import django.db.models.deletion
from django.conf import settings
from django.db import migrations, models
from django.db.backends.base.schema import BaseDatabaseSchemaEditor
from django.db.migrations.state import StateApps
from django.utils.timezone import now as timezone_now
def backfill_user_activations_and_deactivations(
apps: StateApps, schema_editor: BaseDatabaseSchemaEditor
) -> None:
migration_time = timezone_now()
RealmAuditLog = apps.get_model("zerver", "RealmAuditLog")
UserProfile = apps.get_model("zerver", "UserProfile")
for user in UserProfile.objects.all().iterator():
RealmAuditLog.objects.create(
realm=user.realm,
modified_user=user,
event_type="user_created",
event_time=user.date_joined,
backfilled=False,
)
for user in UserProfile.objects.filter(is_active=False):
RealmAuditLog.objects.create(
realm=user.realm,
modified_user=user,
event_type="user_deactivated",
event_time=migration_time,
backfilled=True,
)
def reverse_code(apps: StateApps, schema_editor: BaseDatabaseSchemaEditor) -> None:
RealmAuditLog = apps.get_model("zerver", "RealmAuditLog")
RealmAuditLog.objects.filter(event_type="user_created").delete()
RealmAuditLog.objects.filter(event_type="user_deactivated").delete()
class Migration(migrations.Migration):
dependencies = [
("zerver", "0056_userprofile_emoji_alt_code"),
]
operations = [
migrations.CreateModel(
name="RealmAuditLog",
fields=[
(
"id",
models.AutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
),
),
("event_type", models.CharField(max_length=40)),
("backfilled", models.BooleanField(default=False)),
("event_time", models.DateTimeField()),
(
"acting_user",
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.CASCADE,
related_name="+",
to=settings.AUTH_USER_MODEL,
),
),
(
"modified_stream",
models.ForeignKey(
null=True, on_delete=django.db.models.deletion.CASCADE, to="zerver.Stream"
),
),
(
"modified_user",
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.CASCADE,
related_name="+",
to=settings.AUTH_USER_MODEL,
),
),
(
"realm",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE, to="zerver.Realm"
),
),
],
),
migrations.RunPython(
backfill_user_activations_and_deactivations, reverse_code=reverse_code, elidable=True
),
]

View File

@@ -0,0 +1,16 @@
# Generated by Django 1.10.5 on 2017-02-27 14:34
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("zerver", "0057_realmauditlog"),
]
operations = [
migrations.AddField(
model_name="realm",
name="email_changes_disabled",
field=models.BooleanField(default=False),
),
]

View File

@@ -0,0 +1,16 @@
# Generated by Django 1.10.5 on 2017-03-04 07:40
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("zerver", "0058_realm_email_changes_disabled"),
]
operations = [
migrations.AddField(
model_name="userprofile",
name="quota",
field=models.IntegerField(default=1073741824),
),
]

View File

@@ -0,0 +1,8 @@
# Generated by Django 1.10.5 on 2017-02-27 17:03
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
("zerver", "0059_userprofile_quota"),
]

View File

@@ -0,0 +1,16 @@
# Generated by Django 1.10.5 on 2017-03-15 11:43
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("zerver", "0060_move_avatars_to_be_uid_based"),
]
operations = [
migrations.AddField(
model_name="userprofile",
name="timezone",
field=models.CharField(default="UTC", max_length=40),
),
]

View File

@@ -0,0 +1,16 @@
# Generated by Django 1.10.5 on 2017-03-16 12:22
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("zerver", "0061_userprofile_timezone"),
]
operations = [
migrations.AlterField(
model_name="userprofile",
name="timezone",
field=models.CharField(default="", max_length=40),
),
]

View File

@@ -0,0 +1,16 @@
# Generated by Django 1.10.5 on 2017-03-19 19:06
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("zerver", "0062_default_timezone"),
]
operations = [
migrations.AddField(
model_name="realm",
name="description",
field=models.TextField(max_length=100, null=True),
),
]

View File

@@ -0,0 +1,8 @@
# Generated by Django 1.10.5 on 2017-03-18 12:38
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
("zerver", "0063_realm_description"),
]

View File

@@ -0,0 +1,16 @@
# Generated by Django 1.10.5 on 2017-03-21 15:56
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("zerver", "0064_sync_uploads_filesize_with_db"),
]
operations = [
migrations.AddField(
model_name="realm",
name="inline_image_preview",
field=models.BooleanField(default=True),
),
]

View File

@@ -0,0 +1,16 @@
# Generated by Django 1.10.5 on 2017-03-21 15:58
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("zerver", "0065_realm_inline_image_preview"),
]
operations = [
migrations.AddField(
model_name="realm",
name="inline_url_embed_preview",
field=models.BooleanField(default=True),
),
]

View File

@@ -0,0 +1,166 @@
# Generated by Django 1.10.5 on 2017-03-26 01:10
import bitfield.models
import django.db.models.deletion
import django.utils.timezone
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("zerver", "0066_realm_inline_url_embed_preview"),
]
operations = [
migrations.CreateModel(
name="ArchivedAttachment",
fields=[
(
"id",
models.AutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
),
),
("file_name", models.TextField(db_index=True)),
("path_id", models.TextField(db_index=True)),
("is_realm_public", models.BooleanField(default=False)),
(
"create_time",
models.DateTimeField(db_index=True, default=django.utils.timezone.now),
),
("size", models.IntegerField(null=True)),
(
"archive_timestamp",
models.DateTimeField(db_index=True, default=django.utils.timezone.now),
),
],
options={
"abstract": False,
},
bases=(models.Model,),
),
migrations.CreateModel(
name="ArchivedMessage",
fields=[
(
"id",
models.AutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
),
),
("subject", models.CharField(db_index=True, max_length=60)),
("content", models.TextField()),
("rendered_content", models.TextField(null=True)),
("rendered_content_version", models.IntegerField(null=True)),
("pub_date", models.DateTimeField(db_index=True, verbose_name="date published")),
("last_edit_time", models.DateTimeField(null=True)),
("edit_history", models.TextField(null=True)),
("has_attachment", models.BooleanField(db_index=True, default=False)),
("has_image", models.BooleanField(db_index=True, default=False)),
("has_link", models.BooleanField(db_index=True, default=False)),
(
"archive_timestamp",
models.DateTimeField(db_index=True, default=django.utils.timezone.now),
),
(
"recipient",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE, to="zerver.Recipient"
),
),
(
"sender",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL
),
),
(
"sending_client",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE, to="zerver.Client"
),
),
],
options={
"abstract": False,
},
bases=(models.Model,),
),
migrations.CreateModel(
name="ArchivedUserMessage",
fields=[
(
"id",
models.AutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
),
),
(
"flags",
bitfield.models.BitField(
[
"read",
"starred",
"collapsed",
"mentioned",
"wildcard_mentioned",
"summarize_in_home",
"summarize_in_stream",
"force_expand",
"force_collapse",
"has_alert_word",
"historical",
"is_me_message",
],
default=0,
),
),
(
"archive_timestamp",
models.DateTimeField(db_index=True, default=django.utils.timezone.now),
),
(
"message",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE, to="zerver.ArchivedMessage"
),
),
(
"user_profile",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL
),
),
],
options={
"abstract": False,
},
bases=(models.Model,),
),
migrations.AddField(
model_name="archivedattachment",
name="messages",
field=models.ManyToManyField(to="zerver.ArchivedMessage"),
),
migrations.AddField(
model_name="archivedattachment",
name="owner",
field=models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL
),
),
migrations.AddField(
model_name="archivedattachment",
name="realm",
field=models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.CASCADE,
to="zerver.Realm",
),
),
migrations.AlterUniqueTogether(
name="archivedusermessage",
unique_together={("user_profile", "message")},
),
]

View File

@@ -0,0 +1,15 @@
# Generated by Django 1.10.5 on 2017-03-13 23:32
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
("zerver", "0067_archived_models"),
]
operations = [
migrations.RemoveField(
model_name="realm",
name="domain",
),
]

View File

@@ -0,0 +1,16 @@
# Generated by Django 1.10.5 on 2017-03-27 20:00
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("zerver", "0068_remove_realm_domain"),
]
operations = [
migrations.AddField(
model_name="realmauditlog",
name="extra_data",
field=models.TextField(null=True),
),
]

View File

@@ -0,0 +1,37 @@
# Generated by Django 1.10.5 on 2017-03-28 00:22
import django.db.models.deletion
import django.utils.timezone
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("zerver", "0069_realmauditlog_extra_data"),
]
operations = [
migrations.CreateModel(
name="UserHotspot",
fields=[
(
"id",
models.AutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
),
),
("hotspot", models.CharField(max_length=30)),
("timestamp", models.DateTimeField(default=django.utils.timezone.now)),
(
"user",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL
),
),
],
),
migrations.AlterUniqueTogether(
name="userhotspot",
unique_together={("user", "hotspot")},
),
]

View File

@@ -0,0 +1,15 @@
# Generated by Django 1.10.5 on 2017-03-31 14:21
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
("zerver", "0070_userhotspot"),
]
operations = [
migrations.RenameModel(
old_name="RealmAlias",
new_name="RealmDomain",
),
]

View File

@@ -0,0 +1,16 @@
# Generated by Django 1.10.5 on 2017-03-31 05:51
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("zerver", "0071_rename_realmalias_to_realmdomain"),
]
operations = [
migrations.AlterField(
model_name="realmauditlog",
name="event_time",
field=models.DateTimeField(db_index=True),
),
]

View File

@@ -0,0 +1,70 @@
# Generated by Django 1.10.5 on 2017-04-17 06:49
import django.db.models.deletion
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("zerver", "0072_realmauditlog_add_index_event_time"),
]
operations = [
migrations.CreateModel(
name="CustomProfileField",
fields=[
(
"id",
models.AutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
),
),
("name", models.CharField(max_length=100)),
(
"field_type",
models.PositiveSmallIntegerField(
choices=[(1, "Integer"), (2, "Float"), (3, "Short text"), (4, "Long text")],
default=3,
),
),
(
"realm",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE, to="zerver.Realm"
),
),
],
),
migrations.CreateModel(
name="CustomProfileFieldValue",
fields=[
(
"id",
models.AutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
),
),
("value", models.TextField()),
(
"field",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE, to="zerver.CustomProfileField"
),
),
(
"user_profile",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL
),
),
],
),
migrations.AlterUniqueTogether(
name="customprofilefieldvalue",
unique_together={("user_profile", "field")},
),
migrations.AlterUniqueTogether(
name="customprofilefield",
unique_together={("realm", "name")},
),
]

View File

@@ -0,0 +1,52 @@
# Generated by Django 1.10.5 on 2017-04-13 22:12
from django.db import migrations
from django.db.backends.base.schema import BaseDatabaseSchemaEditor
from django.db.migrations.state import StateApps
from django.db.models import Count
def fix_duplicate_attachments(apps: StateApps, schema_editor: BaseDatabaseSchemaEditor) -> None:
"""Migration 0041 had a bug, where if multiple messages referenced the
same attachment, rather than creating a single attachment object
for all of them, we would incorrectly create one for each message.
This results in exceptions looking up the Attachment object
corresponding to a file that was used in multiple messages that
predate migration 0041.
This migration fixes this by removing the duplicates, moving their
messages onto a single canonical Attachment object (per path_id).
"""
Attachment = apps.get_model("zerver", "Attachment")
# Loop through all groups of Attachment objects with the same `path_id`
for group in (
Attachment.objects.values("path_id")
.annotate(Count("id"))
.order_by()
.filter(id__count__gt=1)
):
# Sort by the minimum message ID, to find the first attachment
attachments = sorted(
Attachment.objects.filter(path_id=group["path_id"]).order_by("id"),
key=lambda x: min(x.messages.all().values_list("id")[0]),
)
surviving = attachments[0]
to_cleanup = attachments[1:]
for a in to_cleanup:
# For each duplicate attachment, we transfer its messages
# to the canonical attachment object for that path, and
# then delete the original attachment.
for msg in a.messages.all():
surviving.messages.add(msg)
surviving.is_realm_public = surviving.is_realm_public or a.is_realm_public
surviving.save()
a.delete()
class Migration(migrations.Migration):
dependencies = [
("zerver", "0073_custom_profile_fields"),
]
operations = [
migrations.RunPython(fix_duplicate_attachments, elidable=True),
]

View File

@@ -0,0 +1,21 @@
# Generated by Django 1.10.5 on 2017-04-13 22:29
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("zerver", "0074_fix_duplicate_attachments"),
]
operations = [
migrations.AlterField(
model_name="archivedattachment",
name="path_id",
field=models.TextField(db_index=True, unique=True),
),
migrations.AlterField(
model_name="attachment",
name="path_id",
field=models.TextField(db_index=True, unique=True),
),
]

View File

@@ -0,0 +1,25 @@
# Generated by Django 1.10.5 on 2017-04-23 19:51
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("zerver", "0075_attachment_path_id_unique"),
]
operations = [
migrations.AddField(
model_name="userprofile",
name="emojiset",
field=models.CharField(
choices=[
("apple", "Apple"),
("emojione", "Emoji One"),
("google", "Google"),
("twitter", "Twitter"),
],
default="google",
max_length=20,
),
),
]

View File

@@ -0,0 +1,20 @@
# Generated by Django 1.10.5 on 2017-03-09 05:23
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("zerver", "0076_userprofile_emojiset"),
]
operations = [
migrations.AddField(
model_name="realmemoji",
name="file_name",
field=models.TextField(db_index=True, null=True),
),
migrations.RemoveField(
model_name="realmemoji",
name="img_url",
),
]

View File

@@ -0,0 +1,34 @@
# Generated by Django 1.10.5 on 2017-04-27 16:55
import django.db.models.deletion
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("zerver", "0077_add_file_name_field_to_realm_emoji"),
]
operations = [
migrations.CreateModel(
name="Service",
fields=[
(
"id",
models.AutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
),
),
("name", models.CharField(max_length=100)),
("base_url", models.TextField()),
("token", models.TextField()),
("interface", models.PositiveSmallIntegerField(default=1)),
(
"user_profile",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL
),
),
],
),
]

View File

@@ -0,0 +1,24 @@
# Generated by Django 1.10.5 on 2017-05-10 05:59
from django.db import migrations
from django.db.backends.base.schema import BaseDatabaseSchemaEditor
from django.db.migrations.state import StateApps
def delete_old_scheduled_jobs(apps: StateApps, schema_editor: BaseDatabaseSchemaEditor) -> None:
"""Delete any old scheduled jobs, to handle changes in the format of
that table. Ideally, we'd translate the jobs, but it's not really
worth the development effort to save a few invitation reminders
and day2 followup emails.
"""
ScheduledJob = apps.get_model("zerver", "ScheduledJob")
ScheduledJob.objects.all().delete()
class Migration(migrations.Migration):
dependencies = [
("zerver", "0078_service"),
]
operations = [
migrations.RunPython(delete_old_scheduled_jobs, elidable=True),
]

View File

@@ -0,0 +1,16 @@
# Generated by Django 1.10.5 on 2017-05-11 20:27
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("zerver", "0079_remove_old_scheduled_jobs"),
]
operations = [
migrations.AlterField(
model_name="realm",
name="description",
field=models.TextField(null=True),
),
]

View File

@@ -0,0 +1,40 @@
# Generated by Django 1.10.5 on 2017-05-02 21:44
import django.core.validators
from django.db import migrations, models
from django.db.backends.base.schema import BaseDatabaseSchemaEditor
from django.db.migrations.state import StateApps
def emoji_to_lowercase(apps: StateApps, schema_editor: BaseDatabaseSchemaEditor) -> None:
RealmEmoji = apps.get_model("zerver", "RealmEmoji")
emoji = RealmEmoji.objects.all()
for e in emoji:
# Technically, this could create a conflict, but it's
# exceedingly unlikely. If that happens, the sysadmin can
# manually rename the conflicts with the manage.py shell
# and then rerun the migration/upgrade.
e.name = e.name.lower()
e.save()
class Migration(migrations.Migration):
dependencies = [
("zerver", "0080_realm_description_length"),
]
operations = [
migrations.RunPython(emoji_to_lowercase, elidable=True),
migrations.AlterField(
model_name="realmemoji",
name="name",
field=models.TextField(
validators=[
django.core.validators.MinLengthValidator(1),
django.core.validators.RegexValidator(
message="Invalid characters in emoji name",
regex="^[0-9a-z.\\-_]+(?<![.\\-_])$",
),
]
),
),
]

View File

@@ -0,0 +1,20 @@
from django.db import migrations, models
from django.db.models import Q
class Migration(migrations.Migration):
dependencies = [
("zerver", "0081_make_emoji_lowercase"),
]
operations = [
migrations.AddIndex(
model_name="usermessage",
index=models.Index(
"user_profile",
"message",
condition=Q(flags__andnz=2),
name="zerver_usermessage_starred_message_id",
),
),
]

View File

@@ -0,0 +1,20 @@
from django.db import migrations, models
from django.db.models import Q
class Migration(migrations.Migration):
dependencies = [
("zerver", "0082_index_starred_user_messages"),
]
operations = [
migrations.AddIndex(
model_name="usermessage",
index=models.Index(
"user_profile",
"message",
condition=Q(flags__andnz=8),
name="zerver_usermessage_mentioned_message_id",
),
),
]

View File

@@ -0,0 +1,16 @@
# Generated by Django 1.10.5 on 2017-05-22 14:49
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("zerver", "0083_index_mentioned_user_messages"),
]
operations = [
migrations.AddField(
model_name="realmemoji",
name="deactivated",
field=models.BooleanField(default=False),
),
]

View File

@@ -0,0 +1,22 @@
# Generated by Django 1.11.2 on 2017-06-20 10:31
from django.db import migrations
from django.db.backends.base.schema import BaseDatabaseSchemaEditor
from django.db.migrations.state import StateApps
def fix_bot_type(apps: StateApps, schema_editor: BaseDatabaseSchemaEditor) -> None:
UserProfile = apps.get_model("zerver", "UserProfile")
bots = UserProfile.objects.filter(is_bot=True, bot_type=None)
for bot in bots:
bot.bot_type = 1
bot.save()
class Migration(migrations.Migration):
dependencies = [
("zerver", "0084_realmemoji_deactivated"),
]
operations = [
migrations.RunPython(fix_bot_type, elidable=True),
]

View File

@@ -0,0 +1,18 @@
# Generated by Django 1.11.2 on 2017-06-26 21:56
from django.db import migrations, models
CORPORATE = 1
class Migration(migrations.Migration):
dependencies = [
("zerver", "0085_fix_bots_with_none_bot_type"),
]
operations = [
migrations.AlterField(
model_name="realm",
name="org_type",
field=models.PositiveSmallIntegerField(default=CORPORATE),
),
]

View File

@@ -0,0 +1,24 @@
# Generated by Django 1.10.5 on 2017-05-10 05:59
from django.db import migrations
from django.db.backends.base.schema import BaseDatabaseSchemaEditor
from django.db.migrations.state import StateApps
def delete_old_scheduled_jobs(apps: StateApps, schema_editor: BaseDatabaseSchemaEditor) -> None:
"""Delete any old scheduled jobs, to handle changes in the format of
send_email. Ideally, we'd translate the jobs, but it's not really
worth the development effort to save a few invitation reminders
and day2 followup emails.
"""
ScheduledJob = apps.get_model("zerver", "ScheduledJob")
ScheduledJob.objects.all().delete()
class Migration(migrations.Migration):
dependencies = [
("zerver", "0086_realm_alter_default_org_type"),
]
operations = [
migrations.RunPython(delete_old_scheduled_jobs, elidable=True),
]

View File

@@ -0,0 +1,26 @@
# Generated by Django 1.11.2 on 2017-07-07 08:34
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
("zerver", "0087_remove_old_scheduled_jobs"),
]
operations = [
migrations.RemoveField(
model_name="referral",
name="user_profile",
),
migrations.RemoveField(
model_name="userprofile",
name="invites_granted",
),
migrations.RemoveField(
model_name="userprofile",
name="invites_used",
),
migrations.DeleteModel(
name="Referral",
),
]

View File

@@ -0,0 +1,21 @@
# Generated by Django 1.11.2 on 2017-07-10 13:53
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("zerver", "0088_remove_referral_and_invites"),
]
operations = [
migrations.AddField(
model_name="userprofile",
name="last_active_message_id",
field=models.IntegerField(null=True),
),
migrations.AddField(
model_name="userprofile",
name="long_term_idle",
field=models.BooleanField(db_index=True, default=False),
),
]

View File

@@ -0,0 +1,16 @@
# Generated by Django 1.11.2 on 2017-07-07 15:58
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("zerver", "0089_auto_20170710_1353"),
]
operations = [
migrations.AddField(
model_name="userprofile",
name="high_contrast_mode",
field=models.BooleanField(default=False),
),
]

View File

@@ -0,0 +1,16 @@
# Generated by Django 1.11.2 on 2017-07-16 08:57
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("zerver", "0090_userprofile_high_contrast_mode"),
]
operations = [
migrations.AddField(
model_name="realm",
name="allow_edit_history",
field=models.BooleanField(default=True),
),
]

View File

@@ -0,0 +1,42 @@
# Generated by Django 1.11.2 on 2017-07-11 23:41
import django.db.models.deletion
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("zerver", "0091_realm_allow_edit_history"),
]
operations = [
migrations.CreateModel(
name="ScheduledEmail",
fields=[
(
"id",
models.AutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
),
),
("scheduled_timestamp", models.DateTimeField(db_index=True)),
("data", models.TextField()),
("address", models.EmailField(db_index=True, max_length=254, null=True)),
("type", models.PositiveSmallIntegerField()),
(
"user",
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.CASCADE,
to=settings.AUTH_USER_MODEL,
),
),
],
options={
"abstract": False,
},
),
migrations.DeleteModel(
name="ScheduledJob",
),
]

View File

@@ -0,0 +1,71 @@
from django.db import migrations, models
from django.db.backends.base.schema import BaseDatabaseSchemaEditor
from django.db.migrations.state import StateApps
from django.db.models import Max
from django.utils.timezone import now as timezone_now
def backfill_subscription_log_events(
apps: StateApps, schema_editor: BaseDatabaseSchemaEditor
) -> None:
migration_time = timezone_now()
RealmAuditLog = apps.get_model("zerver", "RealmAuditLog")
Subscription = apps.get_model("zerver", "Subscription")
Message = apps.get_model("zerver", "Message")
objects_to_create = []
subs_query = Subscription.objects.select_related(
"user_profile", "user_profile__realm", "recipient"
).filter(recipient__type=2)
for sub in subs_query:
entry = RealmAuditLog(
realm=sub.user_profile.realm,
modified_user=sub.user_profile,
modified_stream_id=sub.recipient.type_id,
event_last_message_id=0,
event_type="subscription_created",
event_time=migration_time,
backfilled=True,
)
objects_to_create.append(entry)
RealmAuditLog.objects.bulk_create(objects_to_create)
objects_to_create = []
event_last_message_id = Message.objects.aggregate(Max("id"))["id__max"]
migration_time_for_deactivation = timezone_now()
for sub in subs_query.filter(active=False):
entry = RealmAuditLog(
realm=sub.user_profile.realm,
modified_user=sub.user_profile,
modified_stream_id=sub.recipient.type_id,
event_last_message_id=event_last_message_id,
event_type="subscription_deactivated",
event_time=migration_time_for_deactivation,
backfilled=True,
)
objects_to_create.append(entry)
RealmAuditLog.objects.bulk_create(objects_to_create)
objects_to_create = []
def reverse_code(apps: StateApps, schema_editor: BaseDatabaseSchemaEditor) -> None:
RealmAuditLog = apps.get_model("zerver", "RealmAuditLog")
RealmAuditLog.objects.filter(event_type="subscription_created").delete()
RealmAuditLog.objects.filter(event_type="subscription_deactivated").delete()
class Migration(migrations.Migration):
dependencies = [
("zerver", "0092_create_scheduledemail"),
]
operations = [
migrations.AddField(
model_name="realmauditlog",
name="event_last_message_id",
field=models.IntegerField(null=True),
),
migrations.RunPython(
backfill_subscription_log_events, reverse_code=reverse_code, elidable=True
),
]

View File

@@ -0,0 +1,12 @@
# Generated by Django 1.11.2 on 2017-07-22 13:44
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
("zerver", "0093_subscription_event_log_backfill"),
]
operations = []

View File

@@ -0,0 +1,20 @@
from django.db import migrations, models
from django.db.models import Q
class Migration(migrations.Migration):
dependencies = [
("zerver", "0094_realm_filter_url_validator"),
]
operations = [
migrations.AddIndex(
model_name="usermessage",
index=models.Index(
"user_profile",
"message",
condition=Q(flags__andz=1),
name="zerver_usermessage_unread_message_id",
),
),
]

View File

@@ -0,0 +1,16 @@
# Generated by Django 1.11.2 on 2017-08-09 04:21
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("zerver", "0095_index_unread_user_messages"),
]
operations = [
migrations.AddField(
model_name="preregistrationuser",
name="password_required",
field=models.BooleanField(default=True),
),
]

View File

@@ -0,0 +1,61 @@
# Generated by Django 1.11.2 on 2017-06-18 21:26
import os
import orjson
from django.db import migrations, models
from django.db.backends.base.schema import BaseDatabaseSchemaEditor
from django.db.migrations.state import StateApps
def populate_new_fields(apps: StateApps, schema_editor: BaseDatabaseSchemaEditor) -> None:
# Open the JSON file which contains the data to be used for migration.
MIGRATION_DATA_PATH = os.path.join(
os.path.dirname(os.path.dirname(__file__)), "management", "data"
)
path_to_unified_reactions = os.path.join(MIGRATION_DATA_PATH, "unified_reactions.json")
with open(path_to_unified_reactions, "rb") as f:
unified_reactions = orjson.loads(f.read())
Reaction = apps.get_model("zerver", "Reaction")
for reaction in Reaction.objects.all().iterator():
reaction.emoji_code = unified_reactions.get(reaction.emoji_name)
if reaction.emoji_code is None:
# If it's not present in the unified_reactions map, it's a realm emoji.
reaction.emoji_code = reaction.emoji_name
if reaction.emoji_name == "zulip":
# `:zulip:` emoji is a zulip special custom emoji.
reaction.reaction_type = "zulip_extra_emoji"
else:
reaction.reaction_type = "realm_emoji"
reaction.save()
class Migration(migrations.Migration):
dependencies = [
("zerver", "0096_add_password_required"),
]
operations = [
migrations.AddField(
model_name="reaction",
name="emoji_code",
field=models.TextField(default="unset"),
preserve_default=False,
),
migrations.AddField(
model_name="reaction",
name="reaction_type",
field=models.CharField(
choices=[
("unicode_emoji", "Unicode emoji"),
("realm_emoji", "Custom emoji"),
("zulip_extra_emoji", "Zulip extra emoji"),
],
default="unicode_emoji",
max_length=30,
),
),
migrations.RunPython(
populate_new_fields, reverse_code=migrations.RunPython.noop, elidable=True
),
]

View File

@@ -0,0 +1,20 @@
from django.db import migrations, models
from django.db.models import Q
class Migration(migrations.Migration):
dependencies = [
("zerver", "0097_reactions_emoji_code"),
]
operations = [
migrations.AddIndex(
model_name="usermessage",
index=models.Index(
"user_profile",
"message",
condition=Q(flags__andnz=512),
name="zerver_usermessage_has_alert_word_message_id",
),
),
]

View File

@@ -0,0 +1,20 @@
from django.db import migrations, models
from django.db.models import Q
class Migration(migrations.Migration):
dependencies = [
("zerver", "0098_index_has_alert_word_user_messages"),
]
operations = [
migrations.AddIndex(
model_name="usermessage",
index=models.Index(
"user_profile",
"message",
condition=Q(flags__andnz=8) | Q(flags__andnz=16),
name="zerver_usermessage_wildcard_mentioned_message_id",
),
),
]

View File

@@ -0,0 +1,52 @@
# Generated by Django 1.11.4 on 2017-08-27 17:08
import bitfield.models
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
("zerver", "0099_index_wildcard_mentioned_user_messages"),
]
operations = [
migrations.AlterField(
model_name="archivedusermessage",
name="flags",
field=bitfield.models.BitField(
[
"read",
"starred",
"collapsed",
"mentioned",
"wildcard_mentioned",
"summarize_in_home",
"summarize_in_stream",
"force_expand",
"force_collapse",
"has_alert_word",
"historical",
],
default=0,
),
),
migrations.AlterField(
model_name="usermessage",
name="flags",
field=bitfield.models.BitField(
[
"read",
"starred",
"collapsed",
"mentioned",
"wildcard_mentioned",
"summarize_in_home",
"summarize_in_stream",
"force_expand",
"force_collapse",
"has_alert_word",
"historical",
],
default=0,
),
),
]

View File

@@ -0,0 +1,48 @@
# Generated by Django 1.11.4 on 2017-08-30 00:26
import django.db.models.deletion
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("zerver", "0100_usermessage_remove_is_me_message"),
]
operations = [
migrations.CreateModel(
name="MutedTopic",
fields=[
(
"id",
models.AutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
),
),
("topic_name", models.CharField(max_length=60)),
(
"recipient",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE, to="zerver.Recipient"
),
),
(
"stream",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE, to="zerver.Stream"
),
),
(
"user_profile",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL
),
),
],
bases=(models.Model,),
),
migrations.AlterUniqueTogether(
name="mutedtopic",
unique_together={("user_profile", "stream", "topic_name")},
),
]

View File

@@ -0,0 +1,78 @@
# Generated by Django 1.11.4 on 2017-08-30 00:26
import orjson
from django.db import connection, migrations
from django.db.backends.base.schema import BaseDatabaseSchemaEditor
from django.db.migrations.state import StateApps
from psycopg2.sql import SQL
def convert_muted_topics(apps: StateApps, schema_editor: BaseDatabaseSchemaEditor) -> None:
stream_query = SQL(
"""
SELECT
zerver_stream.name,
zerver_stream.realm_id,
zerver_stream.id,
zerver_recipient.id
FROM
zerver_stream
INNER JOIN zerver_recipient ON (
zerver_recipient.type_id = zerver_stream.id AND
zerver_recipient.type = 2
)
"""
)
stream_dict = {}
with connection.cursor() as cursor:
cursor.execute(stream_query)
rows = cursor.fetchall()
for stream_name, realm_id, stream_id, recipient_id in rows:
stream_name = stream_name.lower()
stream_dict[(stream_name, realm_id)] = (stream_id, recipient_id)
UserProfile = apps.get_model("zerver", "UserProfile")
MutedTopic = apps.get_model("zerver", "MutedTopic")
new_objs = []
user_query = UserProfile.objects.values(
"id",
"realm_id",
"muted_topics",
)
for row in user_query:
user_profile_id = row["id"]
realm_id = row["realm_id"]
muted_topics = row["muted_topics"]
tups = orjson.loads(muted_topics)
for stream_name, topic_name in tups:
stream_name = stream_name.lower()
val = stream_dict.get((stream_name, realm_id))
if val is not None:
stream_id, recipient_id = val
muted_topic = MutedTopic(
user_profile_id=user_profile_id,
stream_id=stream_id,
recipient_id=recipient_id,
topic_name=topic_name,
)
new_objs.append(muted_topic)
with connection.cursor() as cursor:
cursor.execute("DELETE from zerver_mutedtopic")
MutedTopic.objects.bulk_create(new_objs)
class Migration(migrations.Migration):
dependencies = [
("zerver", "0101_muted_topic"),
]
operations = [
migrations.RunPython(convert_muted_topics, elidable=True),
]

View File

@@ -0,0 +1,15 @@
# Generated by Django 1.11.4 on 2017-08-31 00:13
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
("zerver", "0102_convert_muted_topic"),
]
operations = [
migrations.RemoveField(
model_name="userprofile",
name="muted_topics",
),
]

View File

@@ -0,0 +1,23 @@
# Generated by Django 1.11.4 on 2017-08-30 00:26
from django.db import migrations
from django.db.backends.base.schema import BaseDatabaseSchemaEditor
from django.db.migrations.state import StateApps
from zerver.lib.fix_unreads import fix
def fix_unreads(apps: StateApps, schema_editor: BaseDatabaseSchemaEditor) -> None:
UserProfile = apps.get_model("zerver", "UserProfile")
user_profiles = list(UserProfile.objects.filter(is_bot=False))
for user_profile in user_profiles:
fix(user_profile)
class Migration(migrations.Migration):
dependencies = [
("zerver", "0103_remove_userprofile_muted_topics"),
]
operations = [
migrations.RunPython(fix_unreads, elidable=True),
]

View File

@@ -0,0 +1,16 @@
# Generated by Django 1.11.4 on 2017-09-08 17:52
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("zerver", "0104_fix_unreads"),
]
operations = [
migrations.AddField(
model_name="userprofile",
name="enable_stream_push_notifications",
field=models.BooleanField(default=False),
),
]

View File

@@ -0,0 +1,16 @@
# Generated by Django 1.11.4 on 2017-09-08 17:52
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("zerver", "0105_userprofile_enable_stream_push_notifications"),
]
operations = [
migrations.AddField(
model_name="subscription",
name="push_notifications",
field=models.BooleanField(default=False),
),
]

View File

@@ -0,0 +1,37 @@
# Generated by Django 1.11.4 on 2017-09-04 22:48
import django.db.models.deletion
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("zerver", "0106_subscription_push_notifications"),
]
operations = [
migrations.CreateModel(
name="MultiuseInvite",
fields=[
(
"id",
models.AutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
),
),
(
"realm",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE, to="zerver.Realm"
),
),
(
"referred_by",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL
),
),
("streams", models.ManyToManyField(to="zerver.Stream")),
],
),
]

View File

@@ -0,0 +1,31 @@
# Generated by Django 1.11.4 on 2017-08-24 02:39
from django.db import migrations
from django.db.backends.base.schema import BaseDatabaseSchemaEditor
from django.db.migrations.state import StateApps
def fix_realm_string_ids(apps: StateApps, schema_editor: BaseDatabaseSchemaEditor) -> None:
Realm = apps.get_model("zerver", "Realm")
if Realm.objects.filter(deactivated=False).count() != 2:
return
zulip_realm = Realm.objects.get(string_id="zulip")
try:
user_realm = Realm.objects.filter(deactivated=False).exclude(id=zulip_realm.id)[0]
except Realm.DoesNotExist:
return
user_realm.string_id = ""
user_realm.save()
class Migration(migrations.Migration):
dependencies = [
("zerver", "0107_multiuseinvite"),
]
operations = [
migrations.RunPython(
fix_realm_string_ids, reverse_code=migrations.RunPython.noop, elidable=True
),
]

View File

@@ -0,0 +1,20 @@
from django.db import migrations
from django.db.backends.base.schema import BaseDatabaseSchemaEditor
from django.db.migrations.state import StateApps
def set_tutorial_status_to_finished(
apps: StateApps, schema_editor: BaseDatabaseSchemaEditor
) -> None:
UserProfile = apps.get_model("zerver", "UserProfile")
UserProfile.objects.update(tutorial_status="F")
class Migration(migrations.Migration):
dependencies = [
("zerver", "0108_fix_default_string_id"),
]
operations = [
migrations.RunPython(set_tutorial_status_to_finished, elidable=True),
]

View File

@@ -0,0 +1,35 @@
# Generated by Django 1.11.5 on 2017-10-08 18:37
from django.db import migrations, models
from django.db.backends.base.schema import BaseDatabaseSchemaEditor
from django.db.migrations.state import StateApps
def populate_is_zephyr(apps: StateApps, schema_editor: BaseDatabaseSchemaEditor) -> None:
Realm = apps.get_model("zerver", "Realm")
Stream = apps.get_model("zerver", "Stream")
realms = Realm.objects.filter(
string_id="zephyr",
)
for realm in realms:
Stream.objects.filter(realm_id=realm.id).update(
is_in_zephyr_realm=True,
)
class Migration(migrations.Migration):
dependencies = [
("zerver", "0109_mark_tutorial_status_finished"),
]
operations = [
migrations.AddField(
model_name="stream",
name="is_in_zephyr_realm",
field=models.BooleanField(default=False),
),
migrations.RunPython(
populate_is_zephyr, reverse_code=migrations.RunPython.noop, elidable=True
),
]

View File

@@ -0,0 +1,37 @@
# Generated by Django 1.11.5 on 2017-10-18 16:15
import django.db.models.deletion
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("zerver", "0110_stream_is_in_zephyr_realm"),
]
operations = [
migrations.CreateModel(
name="BotUserStateData",
fields=[
(
"id",
models.AutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
),
),
("key", models.TextField(db_index=True)),
("value", models.TextField()),
(
"bot_profile",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL
),
),
],
),
migrations.AlterUniqueTogether(
name="botuserstatedata",
unique_together={("bot_profile", "key")},
),
]

View File

@@ -0,0 +1,17 @@
from django.db import migrations, models
from django.db.models.functions import Upper
class Migration(migrations.Migration):
dependencies = [
("zerver", "0111_botuserstatedata"),
]
operations = [
migrations.AddIndex(
model_name="mutedtopic",
index=models.Index(
"stream", Upper("topic_name"), name="zerver_mutedtopic_stream_topic"
),
),
]

View File

@@ -0,0 +1,36 @@
# Generated by Django 1.11.5 on 2017-10-14 15:12
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("zerver", "0112_index_muted_topics"),
]
operations = [
migrations.CreateModel(
name="DefaultStreamGroup",
fields=[
(
"id",
models.AutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
),
),
("name", models.CharField(db_index=True, max_length=60)),
(
"realm",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE, to="zerver.Realm"
),
),
("streams", models.ManyToManyField(to="zerver.Stream")),
],
),
migrations.AlterUniqueTogether(
name="defaultstreamgroup",
unique_together={("realm", "name")},
),
]

View File

@@ -0,0 +1,17 @@
# Generated by Django 1.11.5 on 2017-10-19 21:42
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("zerver", "0113_default_stream_group"),
]
operations = [
migrations.AddField(
model_name="preregistrationuser",
name="invited_as_admin",
field=models.BooleanField(default=False),
),
]

View File

@@ -0,0 +1,69 @@
# Generated by Django 1.11.6 on 2017-10-30 05:05
import django.db.models.deletion
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("zerver", "0114_preregistrationuser_invited_as_admin"),
]
operations = [
migrations.CreateModel(
name="UserGroup",
fields=[
(
"id",
models.AutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
),
),
("name", models.CharField(max_length=100)),
],
),
migrations.CreateModel(
name="UserGroupMembership",
fields=[
(
"id",
models.AutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
),
),
(
"user_group",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE, to="zerver.UserGroup"
),
),
(
"user_profile",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL
),
),
],
),
migrations.AddField(
model_name="usergroup",
name="members",
field=models.ManyToManyField(
through="zerver.UserGroupMembership", to=settings.AUTH_USER_MODEL
),
),
migrations.AddField(
model_name="usergroup",
name="realm",
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to="zerver.Realm"),
),
migrations.AlterUniqueTogether(
name="usergroupmembership",
unique_together={("user_group", "user_profile")},
),
migrations.AlterUniqueTogether(
name="usergroup",
unique_together={("realm", "name")},
),
]

View File

@@ -0,0 +1,17 @@
# Generated by Django 1.11.5 on 2017-10-28 11:13
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("zerver", "0115_user_groups"),
]
operations = [
migrations.AddField(
model_name="realm",
name="allow_message_deleting",
field=models.BooleanField(default=False),
),
]

View File

@@ -0,0 +1,17 @@
# Generated by Django 1.11.6 on 2017-11-01 08:01
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("zerver", "0116_realm_allow_message_deleting"),
]
operations = [
migrations.AddField(
model_name="usergroup",
name="description",
field=models.CharField(default="", max_length=1024),
),
]

View File

@@ -0,0 +1,17 @@
# Generated by Django 1.11.6 on 2017-11-14 19:52
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("zerver", "0117_add_desc_to_user_group"),
]
operations = [
migrations.AddField(
model_name="defaultstreamgroup",
name="description",
field=models.CharField(default="", max_length=1024),
),
]

View File

@@ -0,0 +1,17 @@
# Generated by Django 1.11.6 on 2017-11-14 19:28
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("zerver", "0118_defaultstreamgroup_description"),
]
operations = [
migrations.AddField(
model_name="userprofile",
name="night_mode",
field=models.BooleanField(default=False),
),
]

View File

@@ -0,0 +1,37 @@
# Generated by Django 1.11.6 on 2017-11-01 19:12
import django.db.models.deletion
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("zerver", "0119_userprofile_night_mode"),
]
operations = [
migrations.CreateModel(
name="BotUserConfigData",
fields=[
(
"id",
models.AutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
),
),
("key", models.TextField(db_index=True)),
("value", models.TextField()),
(
"bot_profile",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL
),
),
],
),
migrations.AlterUniqueTogether(
name="botuserconfigdata",
unique_together={("bot_profile", "key")},
),
]

View File

@@ -0,0 +1,41 @@
# Generated by Django 1.11.5 on 2017-10-19 22:01
import django.db.models.deletion
from django.db import migrations, models
from django.db.backends.base.schema import BaseDatabaseSchemaEditor
from django.db.migrations.state import StateApps
def set_initial_value_for_signup_notifications_stream(
apps: StateApps, schema_editor: BaseDatabaseSchemaEditor
) -> None:
realm_model = apps.get_model("zerver", "Realm")
realms = realm_model.objects.exclude(notifications_stream__isnull=True)
for realm in realms:
realm.signup_notifications_stream = realm.notifications_stream
realm.save(update_fields=["signup_notifications_stream"])
class Migration(migrations.Migration):
dependencies = [
("zerver", "0120_botuserconfigdata"),
]
operations = [
migrations.AddField(
model_name="realm",
name="signup_notifications_stream",
field=models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.CASCADE,
related_name="+",
to="zerver.Stream",
),
),
migrations.RunPython(
set_initial_value_for_signup_notifications_stream,
reverse_code=migrations.RunPython.noop,
elidable=True,
),
]

View File

@@ -0,0 +1,16 @@
# Generated by Django 1.11.6 on 2017-11-24 09:10
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
("zerver", "0121_realm_signup_notifications_stream"),
]
operations = [
migrations.RenameModel(
old_name="BotUserStateData",
new_name="BotStorageData",
),
]

View File

@@ -0,0 +1,21 @@
# Generated by Django 1.11.6 on 2017-11-22 20:45
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("zerver", "0122_rename_botuserstatedata_botstoragedata"),
]
operations = [
migrations.AlterField(
model_name="userprofile",
name="email",
field=models.EmailField(db_index=True, max_length=254),
),
migrations.AlterUniqueTogether(
name="userprofile",
unique_together={("realm", "email")},
),
]

View File

@@ -0,0 +1,22 @@
# Generated by Django 1.11.6 on 2017-11-29 01:38
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("zerver", "0123_userprofile_make_realm_email_pair_unique"),
]
operations = [
migrations.AddField(
model_name="subscription",
name="email_notifications",
field=models.BooleanField(default=False),
),
migrations.AddField(
model_name="userprofile",
name="enable_stream_email_notifications",
field=models.BooleanField(default=False),
),
]

View File

@@ -0,0 +1,17 @@
# Generated by Django 1.11.6 on 2017-11-30 04:58
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("zerver", "0124_stream_enable_notifications"),
]
operations = [
migrations.AddField(
model_name="realm",
name="max_invites",
field=models.IntegerField(default=100),
),
]

View File

@@ -0,0 +1,24 @@
# Generated by Django 1.11.6 on 2017-11-30 04:58
from django.db import migrations
from django.db.backends.base.schema import BaseDatabaseSchemaEditor
from django.db.migrations.state import StateApps
def remove_prereg_users_without_realm(
apps: StateApps, schema_editor: BaseDatabaseSchemaEditor
) -> None:
prereg_model = apps.get_model("zerver", "PreregistrationUser")
prereg_model.objects.filter(realm=None, realm_creation=False).delete()
class Migration(migrations.Migration):
dependencies = [
("zerver", "0125_realm_max_invites"),
]
operations = [
migrations.RunPython(
remove_prereg_users_without_realm, reverse_code=migrations.RunPython.noop, elidable=True
),
]

Some files were not shown because too many files have changed in this diff Show More