Commit Graph

6949 Commits

Author SHA1 Message Date
Steve Howell f5fc348786 mypy: Add explicit types for dbdata references.
When our handlers specifically reference self.md.zulip_db_data,
we now use an explicit type.

We probably want a more robust solution here, such as a semgrep
rule.
2021-12-30 11:28:15 -08:00
Steve Howell df84892aad markdown: Convert DbData to a dataclass. 2021-12-30 11:28:15 -08:00
Steve Howell 4e551f8279 refactor: Introduce get_stream_name_map.
We only need a name -> id map, and the FullNameInfo
type was a lie.
2021-12-30 11:28:15 -08:00
Steve Howell c04a8097f3 mypy: Add EmojiInfo type.
We now serialize still_url as None for non-animated emojis,
instead of omitting the field. The webapp does proper checks
for falsiness here.  The mobile app does not yet use the field
(to my knowledge).

We bump the API version here. More discussion here:

https://chat.zulip.org/#narrow/stream/378-api-design/topic/still_url/near/1302573
2021-12-30 11:28:14 -08:00
Lauryn Menard a16fcd3172 tests: Improve testing helper event schema for `update_message`.
Further clarifies the fields returned by `update_message` event
for the type of change (content, topic and/or stream).

Follow-up task from #20587.
2021-12-30 08:35:35 -08:00
BIKI DAS ad61d06cea
python: Remove unnecessary list comprehension.
`all` can take a generator, not just a list.  

Using a generator expression here is simpler and faster.
2021-12-30 06:51:50 -08:00
Anders Kaseorg b0b8f84949 test_console_output: Avoid appending to bytes in a loop.
Appending to bytes in a loop leads to a quadratic slowdown since
Python doesn’t optimize this for bytes like it does for str.

Signed-off-by: Anders Kaseorg <anders@zulip.com>
2021-12-29 16:50:08 -08:00
parth 4edf029ad5 invitations: Don't notify now-deactivated users.
While accepting an invitation from a user, there was no condition in
place to check if the user sending the invitation was now
now-deactivated.

Skip sending notifications about newly-joined users to users who are
now disabled.

Fixes #18569.
2021-12-29 16:21:19 -08:00
Steve Howell 1e4593b2ae performance: Avoid Recipient lookup.
We don't have to go to the database to get the Recipient
fields for `user_profile.recipient`.

See also 85ed6f332a from a little
over a year ago--it's very similar.
2021-12-28 12:15:02 -08:00
Steve Howell 01ebb2c85f refactor: Pass realm to bulk_remove_subscriptions.
We made a very similar change to bulk_add_subscriptions
earlier in the year.
2021-12-28 12:15:02 -08:00
Steve Howell ebbd5f168b refactor: Pass realm to notify_subscriptions_removed. 2021-12-28 12:15:02 -08:00
Steve Howell 966d88a78a stream colors: Fix stream color assignment.
The bug here probably didn't come up too much in
practice, but if we were adding a user to multiple
streams when they already had used all N available
colors, all the new streams would be assigned the same
color, since the size of used_colors would stay at N,
thwarting our little modulo-len hackery.

It's not a terrible bug, since users can obviously
customize their stream colors as they see fit.

Usually when we are adding a user to multiple streams,
the users are fairly new, and thus don't have many
existing streams, so I have never heard this bug
reported in the field.

Anyway, assigning the colors in bulk seems to make more
sense, and I added some tests.

For the situations where all the colors have already
been used, I didn't put a ton of thought into exactly
which repeated colors we want to choose; instead, I
just ensure they're different modulo 24. It's possible
that we should just have more than 24 canned colors, or
we should just assign the same default color every time
and let users change it themselves (once they've gone
beyond the 24, to be clear). Or maybe we can just do
something smarter here. I don't have enough time for a
deep dive on this issue.
2021-12-28 12:15:02 -08:00
Steve Howell fe3295d395 performance: Avoid monster query for existing subs.
Part of our codepath for subscribing users involves
fetching the users' existing subscriptions to make sure
we can do things like properly report to the clients
that the users were already subscribed.  This codepath
used to be coupled to code that helped users maintain
unique stream colors.

Suppose you are creating a new stream, and you are
importing users from an older stream with 15k
subscribers, and each of your users is subscribed to
about 20 streams.

The prior code, instead of filtering on recipient_id,
would literally look at every subscription for every
user, which was kind of crazy if you didn't understand
the pick-stream-color complications.

Before this commit, we would fetch 300k rows with 15
columns each (granted, all but one of the columns are
bool/int). That's a total of 4.5 million tiny objects
that we had to glom into Django ORM objects and slice
and dice.

After this commit, we would fetch exactly zero rows
for the are-they-already-subscribed logic.

Yes, ZERO.

If we were to mistakenly try to re-add the same 15k
subscribers to the new stream (under the new code), we
will now fetch 15k Sub rows instead of 300k.

It is worth looking at the prior commit. We go through
great pains to ensure that users get new stream colors
when we invite them to a stream, and we still fetch a
bunch of data for that. Instead of 4.5 million cells,
it's more like 600k cells (2 columns per row), and it's
less than that insofar as some users may only
have 24 distinct colors among their many streams.
It's a lot of work.
2021-12-28 12:15:02 -08:00
Steve Howell f638fd6f72 performance: Get used stream colors in separate trip.
This commit sets us up for the next commit, which will
save us a very expensive query.

If you are adding 15k users to a stream, and each user
has about 20 existing streams, then we need to retrieve
300k rows from the database to figure out which stream
colors they already have.  We don't need all the extra
fields from Subscription, so now we get just the two
values we need for making a color map.

In the next commit we'll eliminate the other use case
for the big query, and I will explain in greater
depth how splitting out the color-picking code can
be a huge win. It is possible that some product decisions
could make this codepath easier. We could also do some
engineering specific to stream colors, such as caching
which colors users have already used.

This does cost us an extra round trip to the database.
2021-12-28 12:15:02 -08:00
Steve Howell 56da570422 code cleanup: Remove unused parameter in pick_color. 2021-12-28 12:15:02 -08:00
Abhijeet Prasad Bodas acdce4df47 actions: Fix misleading comment about wildcard mentions.
Having the `wildcard_mentions_notify` setting turned on does
not necessarily mean that the user will receive notification
for that message. There is more nuance to this, as explained
in the updated comment.
2021-12-28 10:58:54 -08:00
Eeshan Garg 2393342e03 webhooks/jira: Handle anomalous payloads properly.
We recently ran into a payload in production that didn't contain
an event type at all. A payload where we can't figure out the event
type is quite rare. Instead of letting these payloads run amok, we
should raise a more informative exception for such unusual payloads.
If we encounter too many of these, then we can choose to conduct a
deeper investigation on a case-by-case basis.

With some changes by Tim Abbott.
2021-12-28 10:56:25 -08:00
Steve Howell d62b39450e performance: Optimize send_subscription_add_events.
We avoid repeating the same calculations over and
over again for the same stream.

This helps, but the real bottleneck in this function
is that send_event usually takes at least a millisecond,
and that adds up quickly if you're doing something
like subscribing 5k users to a new stream.
2021-12-28 09:33:16 -08:00
Anders Kaseorg bc69f213a0 requirements: Upgrade Python requirements.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2021-12-28 09:31:55 -08:00
Anders Kaseorg 60eed65832 scim: Placate mypy 0.930.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2021-12-28 09:31:55 -08:00
Anders Kaseorg c8dd90f32b bot_config: Placate mypy 0.930.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2021-12-28 09:31:55 -08:00
Anders Kaseorg 575932f4e0 actions: Placate mypy 0.930.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2021-12-28 09:31:55 -08:00
Anders Kaseorg d40f3d54f1 test_console_output: Implement the entire TextIO contract.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2021-12-28 09:31:55 -08:00
Anders Kaseorg 702ce071f4 python: Accept Optional[FrameType] in signal handlers.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2021-12-28 09:31:55 -08:00
Anders Kaseorg 591bd3f4a1 webhooks: Rename Yo App to Yo.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2021-12-22 14:05:17 -08:00
Anders Kaseorg 1d3520db12 webhooks: Remove space from UptimeRobot.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2021-12-22 14:05:17 -08:00
Anders Kaseorg 65868b09eb webhooks: Add missing space in Review Board.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2021-12-22 14:05:17 -08:00
Anders Kaseorg c02c053ec3 webhooks: Fix Mailchimp capitalization.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2021-12-22 14:05:17 -08:00
Anders Kaseorg dc72f79a83 webhooks: Fix Canarytokens pluralization.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2021-12-22 14:05:17 -08:00
Shlok Patel b1436aed9c production: Create stream in an atomic transaction.
To avoid the window between stream creation and creation of the
Recipient object, we create the stream in an atomic transaction.

Fixes #20127
2021-12-21 15:45:45 -08:00
Anders Kaseorg dc18aadeb2 test_classes: Type kwargs for client_get and friends.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2021-12-17 08:03:52 -08:00
Anders Kaseorg 27977eddeb export: Use tar -C to switch directories.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2021-12-17 08:01:53 -08:00
Tim Abbott 22b5e105e6 upload: Remove incorrect animated GIF asserts.
GIF files can be `.GIF`, and also we determine the file format by
inspecting the image data, so there's no reason to have this
assertion.

(The code for serving still images does not rely on the file being a
GIF.)
2021-12-16 16:13:00 -08:00
Sahil Batra 1b23cbdf3e do_change_user_role: Use transaction.atomic. 2021-12-16 14:24:30 -08:00
Sahil Batra 168f241ff0 do_create_user: Use transaction.atomic.
Have kept process_new_human_user out of
the atomic block because it involves many
different operations and also sends events.
Tried enclosing event in on_commit but that
would need many changes in the tests, so have
skipped it for now.
2021-12-16 14:24:30 -08:00
Lauryn Menard 9321095406 tests: Update event tests for `do_update_message` action.
Updates testing helpers in `event_schema.py` for `do_update_message` so
that all stream message fields are present in any edits / updates to
stream messages. Adds verfication tests of events returned from private
message edits and from stream message content-only and topic-only edits.
2021-12-16 11:01:31 -08:00
Lauryn Menard 3b72da8a7c api: Include `stream_id` field for all edits to stream messages.
Updates the `update_message` event type to always include a `stream_id`
field when the message being edited is a stream message. This change
aligns with the current definition of the `\get-events` endpoint
in the OpenAPI documentation.
2021-12-16 11:01:31 -08:00
Tim Abbott af27675857 send_custom_email: Add support for emailing remote server contacts.
This isn't a fully reusable tool, since it has copy about terms of
service, but it's at least readily modified and has tests.
2021-12-14 18:11:23 -08:00
Tim Abbott f287606198 send_custom_email: Make options a mandatory kwarg. 2021-12-14 18:11:23 -08:00
Alex Vandiver 4b1fd209be send_email: Don't abort on an EmailNotDeliveredException.
It is better to press on, than stop halfway through due to a user
whose email no longer works.  The exception is already logged, which
is sufficient here, as this is generally run interactively.
2021-12-14 17:07:34 -08:00
Alex Vandiver 45736aea3c email: Don't send overly-long "To" addresses.
This parallels b7fa41601d, but with "To"
addresses, not "From" addresses.
2021-12-14 15:37:12 -08:00
Steve Howell 53ffb8152f tests: Use read_test_image_file helper. 2021-12-13 12:25:19 -08:00
Mateusz Mandera 74f4e3e914 do_change_realm_subdomain: Use transaction.atomic. 2021-12-11 10:39:07 -08:00
Mateusz Mandera 1692b2e81b do_reactivate_realm: Use transaction.atomic. 2021-12-11 10:39:07 -08:00
Mateusz Mandera 466e0bcdb3 do_set_realm_signup_notifications_stream: Use transaction.atomic. 2021-12-11 10:39:07 -08:00
Mateusz Mandera cddfd2cc92 do_set_realm_notifications_stream: Use transaction.atomic. 2021-12-11 10:39:07 -08:00
Mateusz Mandera 4999f68ba9 do_set_realm_message_editing: Use transaction.atomic. 2021-12-11 10:39:07 -08:00
Mateusz Mandera dc9aac9253 do_set_realm_authentication_methods: Use transaction.atomic. 2021-12-11 10:38:14 -08:00
Tim Abbott 31842e1377 export: Fix empty realm_icons directory in single-user exports. 2021-12-10 12:05:34 -08:00
Steve Howell 2902f8b931 tests: Ensure stream senders get a UserMessage row.
We now complain if a test author sends a stream message
that does not result in the sender getting a
UserMessage row for the message.

This is basically 100% equivalent to complaining that
the author failed to subscribe the sender to the stream
as part of the test setup, as far as I can tell, so the
AssertionError instructs the author to subscribe the
sender to the stream.

We exempt bots from this check, although it is
plausible we should only exempt the system bots like
the notification bot.

I considered auto-subscribing the sender to the stream,
but that can be a little more expensive than the
current check, and we generally want test setup to be
explicit.

If there is some legitimate way than a subscribed human
sender can't get a UserMessage, then we probably want
an explicit test for that, or we may want to change the
backend to just write a UserMessage row in that
hypothetical situation.

For most tests, including almost all the ones fixed
here, the author just wants their test setup to
realistically reflect normal operation, and often devs
may not realize that Cordelia is not subscribed to
Denmark or not realize that Hamlet is not subscribed to
Scotland.

Some of us don't remember our Shakespeare from high
school, and our stream subscriptions don't even
necessarily reflect which countries the Bard placed his
characters in.

There may also be some legitimate use case where an
author wants to simulate sending a message to an
unsubscribed stream, but for those edge cases, they can
always set allow_unsubscribed_sender to True.
2021-12-10 09:40:04 -08:00
Tim Abbott 4cb189fc63 settings: Rename TOS_VERSION to TERMS_OF_SERVICE_VERSION.
The previous version was appropriate in a setting where it was only
used for Zulip Cloud, but it's definitely clearer to spell it out.
2021-12-09 17:51:16 -08:00
odunybrad 90aa45a316 emoji: Add database-level uniqueness constraint for RealmEmoji.
While races here are unlikely, it is most correct to enforce this
invariant at the database layer, and having a database-level
constraint makes the models file a bit more readable.
2021-12-09 17:48:53 -08:00
Steve Howell 9a39ca217f user export: Show less info for recipients.
For PM and huddles, show full names but no
emails or other crufty fields.
2021-12-09 17:20:01 -08:00
Steve Howell 6a5c407b05 user export: Be more selective about exported messages. 2021-12-09 17:20:01 -08:00
Steve Howell fa654fd7a0 user export: Ignore realm icon and logo.
These are not considered to be "personal"
info, even if you upload them, so we
don't export them.

Generally the only folks who upload
these are admins, who can easily get
them in other ways. In fact, anybody
can get these via the app.
2021-12-09 17:20:01 -08:00
Steve Howell 8f991f8eb1 export: Make sure messages are sorted **across** files.
We now ensure that all message ids are sorted BEFORE
we split them into batches.

We now do a few extra "slim" queries to get message
ids up front.

But, now, when we divide them into batches, we no
longer run 2 or 3 different complicated queries in
a loop. We just basically hydrate our message ids,
so `write_message_partials` should be easy to reason
about.

This change also means that for tiny realms with
< 1000 messages you will always have just one
json file, since we aggregate the ids from the
queries before batching.
2021-12-09 12:22:34 -08:00
Steve Howell cef0e11816 export: Add get_id_list_gently_from_database.
This is slightly overkill for the single-user use
case, but for small queries it's barely any overhead,
and it's a nice abstraction.
2021-12-09 12:22:34 -08:00
Steve Howell 8ea320812f user exports: Chunkify messages in sorted order.
This accomplishes a few things:

    * It extracts `chunkify` rather than having us
      clumsily track chunking-related stuff in a
      big loop that is doing other stuff.

    * It makes it so that all message ids
      in message-000001.json < message-000002.json.

    * It makes it easier for us to customize
      the messages we send to a single user
      (coming soon).

BTW we probably have a slicker version of chunkify
somewhere in our codebase, but I couldn't remember
where.
2021-12-09 12:22:34 -08:00
Steve Howell 2a73964e16 user export: Add reactions.
We may eventually try to attach these to the messages
in the message-NNNNNN.json files, but for now they're
fine in user.json.
2021-12-09 12:22:34 -08:00
Steve Howell f810833df5 export: Improve export_usermessages_batch.
We no longer jankily read our input file into
an "output" variable.  Instead, we do things
in a type-safe way.
2021-12-09 08:36:40 -08:00
Steve Howell 5c1e8cb8dc mypy: Add MessagePartial TypedDict. 2021-12-09 08:36:40 -08:00
Steve Howell 09c57a3f9f export: Log more consistently and sort ids.
Now all file writes go through our three
helper functions, and we consistently
write a single log message after the file
gets written.

I killed off write_message_exports, since
all but one of its callers can call
write_table_data, which automatically
sorts data.  In particular, our Message
and UserMessage data will now be sorted
by ids.
2021-12-09 08:36:40 -08:00
Steve Howell 6ec49951c6 minor: Avoid creating intermediate list for message_ids.
This probably just postpones the list creation until
Django builds the "IN" query, but semantically it's
good to work in sets where we don't have any
meaningful ordering of the list that gets used.
2021-12-08 16:12:54 -08:00
Steve Howell f8ed099d3c export: Sort table data for most tables.
This affects most of our tables, but it excludes
table(s) like Message that go through kind of
unique codepaths.
2021-12-08 16:12:54 -08:00
Steve Howell a1d3f12e53 refactor: Extract write_table_data().
The immediate benefit of this is stronger mypy
checks (avoiding the ugly union caused by message
files).

The subsequent commit will add sorting.

We have test coverage on all these lines insofar
as if you comment out the lines, tests will
explode (i.e. more than superficial line
coverage).
2021-12-08 16:12:54 -08:00
Steve Howell c76ca2d0df export: Sort records.json files by path. 2021-12-08 16:12:54 -08:00
Steve Howell 2ef38e3d48 refactor: Extract write_records_json_file. 2021-12-08 16:12:54 -08:00
Steve Howell b79cfc19ab user export: Broaden query for RealmAuditLog.
We now check acting_user as well as modified_user
to see if a row pertains to our exported user.
2021-12-08 16:01:38 -08:00
Steve Howell 927b04368e minor: Use virtual_parent for custom fetchers.
The distinction here wasn't super meaningful
due to the way we order our "elif" statements,
but we want to reserver "normal_parent" for the
majority of use cases, where you simply tell
the Config what the "foreign_key" is.
2021-12-08 15:58:07 -08:00
Steve Howell 50120a9387 export: Remove config parameter for custom fetchers. 2021-12-08 15:58:07 -08:00
Steve Howell 54a3a423e5 mypy: Fix CustomFetch=Any hack. 2021-12-08 15:58:07 -08:00
Steve Howell 4128b52ac5 export: Rename custom fetchers. 2021-12-08 15:58:07 -08:00
Steve Howell a2c4931316 exports: Use realm for RealmAuditLog in realm exports.
For realm-wide exports, there is no reason to query
inefficiently against a list of modified users.

We move the Config out of the common child configs.
2021-12-08 15:58:07 -08:00
Steve Howell 8dd3c1038f exports: Rename parent_key to include_rows.
Even though Django usually treats foo__in
and foo_id__in identically for filters where
foo is a ForeignKey type, we want to insist
on somewhat more consistent syntax, because
we have the odd combo of type and type_id
in Recipient, where type_id is kinda like a
foreign key, but not a ForeignKey.

So we assert for now that all our include_rows
values end in "_id__in".
2021-12-08 15:58:07 -08:00
Steve Howell 02207f47d5 minor: Move code blocks to be alphabetical. 2021-12-08 15:58:07 -08:00
Steve Howell aae9f1b6f5 export: Make Config errors more clear. 2021-12-08 15:58:07 -08:00
Nikhil Maske 091772b534 hotspots: Remove intro_reply hotspot.
Zulip shows two guides on How to reply, first one by
the welcome bot and second one is intro_reply hotspot.
To simply and avoid redundancy, intro_reply hotspot is
removed.

Fixes #20482.
2021-12-07 21:55:59 -08:00
Eeshan Garg 3714a30e63 stream notifications: Add helper for silent user mention syntax.
In many of our stream notification messages, we make use of the
same silent user mention syntax, the template for which was always
hardcoded. This commit adds a helper function that all relevant
callers can call to get the right syntax when mentioning users.

Thanks to Tim Abbott for this suggestion!
2021-12-07 14:53:50 -08:00
Eeshan Garg 8ebe05f644 streams: Add RealmAuditLog entry for message retention updates. 2021-12-07 14:53:50 -08:00
Eeshan Garg d2901892e2 streams: Add notifications for message retention policy updates.
This is a part of #20289.
2021-12-07 14:53:50 -08:00
Steve Howell 6d09eab285 export: Export file images for single users.
We don't have automated test coverage on this yet,
but below are the results from manual testing.

Note that we include the realm icon and logo even
though they were not created by Cordelia.

    ./manage.py export_single_user cordelia@zulip.com

    $ (cd /tmp/zulip-export-4v3mo802/ && find .)
    .
    ./emoji
    ./emoji/2
    ./emoji/2/emoji
    ./emoji/2/emoji/images
    ./emoji/2/emoji/images/3.jpg
    ./emoji/records.json
    ./messages-000001.json
    ./realm_icons
    ./realm_icons/2
    ./realm_icons/2/night_logo.original
    ./realm_icons/2/night_logo.png
    ./realm_icons/2/icon.png
    ./realm_icons/2/icon.original
    ./realm_icons/records.json
    ./avatars
    ./avatars/2
    ./avatars/2/c5125af0447f4d66ce34c1b32eac75ac27ebe0e7.original
    ./avatars/2/c5125af0447f4d66ce34c1b32eac75ac27ebe0e7.png
    ./avatars/records.json
    ./uploads
    ./uploads/2
    ./uploads/2/68
    ./uploads/2/68/xyEkC5dTIp8m42_6HJ3kBfdt
    ./uploads/2/68/xyEkC5dTIp8m42_6HJ3kBfdt/denver.jpg
    ./uploads/2/96
    ./uploads/2/96/ol5WE6RTUntvuPDSpJUrYTim
    ./uploads/2/96/ol5WE6RTUntvuPDSpJUrYTim/denver.jpg
    ./uploads/records.json
    ./user.json
2021-12-07 11:16:52 -08:00
Steve Howell b8d9143318 export: Validate emoji paths.
(We lift the RealmEmoji query to be used by
both local and S3 storage helpers.)
2021-12-07 11:16:52 -08:00
Steve Howell ef6d9b10d2 refactor: Extract get_emoji_path. 2021-12-07 11:16:52 -08:00
Steve Howell 5a41904201 export: Add handle_system_bots flag.
We will set this to False for single-user exports.
2021-12-07 11:16:52 -08:00
Steve Howell 0e19deb558 exports: Limit s3 upload exports with path_id checks. 2021-12-07 11:16:52 -08:00
Steve Howell f6cbf931ae refactor: Pass attachments to export_uploads_from_local.
The next commit will use attachments in the s3 path.
2021-12-07 11:16:52 -08:00
Steve Howell 03f40a64d4 refactor: Pass valid_hashes to export_files_from_s3. 2021-12-07 11:16:52 -08:00
Steve Howell 15bc677f35 export: Pass users to export_avatars_from_local. 2021-12-07 11:16:52 -08:00
Eeshan Garg 2cdaae681d actions: Rename do_change_plan_type -> do change_realm_plan_type.
We will soon be adding an equivalent function for RemoteZulipServer,
so it makes sense to rename this function to be more descriptive.
2021-12-06 16:18:53 -08:00
Steve Howell 42ecabe967 export: Add check_metadata flag. 2021-12-06 15:09:37 -08:00
Steve Howell 0166f13d83 s3 exports: Validate user metadata for all assets.
This preps us to download assets for just a single
user.
2021-12-06 15:09:37 -08:00
Steve Howell 946ab22bba refactor: Lift users query to caller.
This preps us to reuse this code for single users
(after a few more subsequent changes).
2021-12-06 15:09:37 -08:00
Steve Howell b0e5c1d3b9 export: Remove paranoid assertion.
There are tactical reasons to remove this assertion.

Basically, the reason it's safe to remove is that it's
been around a long time and we would have seen this
operationally. Also, the check to make sure that the
S3 filename thingy matches the avatar hash is a much
stronger check.

We will soon restore a stronger version of this check
that applies to all of our asset types (emojis/avatars/etc.).
2021-12-06 15:09:37 -08:00
Steve Howell 59951ae52b refactor: Move metadata checks for s3 export.
This technically broadens the check for user_profile_id,
but we write that metadata on every record.
2021-12-06 15:09:37 -08:00
Steve Howell a27a6a4548 refactor: Inline _check_key_metadata.
This was only called in one place.
2021-12-06 15:09:37 -08:00
Steve Howell db39948be5 refactor: Pass in flavor to export_files_from_s3. 2021-12-06 15:09:37 -08:00
Steve Howell f4354c896b refactor: Pass object_key into export_files_from_s3.
This makes it easier to read the calling code and see
the big picture of how the four asset types are
organized.

I also handle uploads first, to be similar to the local
code.

This code is well tested--you can modify any of the callers
to pass in a wrong value of `object_key` and get a failing
test.
2021-12-06 15:09:37 -08:00
Tim Abbott fee05339a2 actions: Extract ONBOARDING_RECENT_TIMEDELTA. 2021-12-06 14:07:54 -08:00
Steve Howell 4088be6017 import/export: Add UserStatus table.
(We support both realm and single-user exports.)
2021-12-06 13:27:25 -08:00
Steve Howell 45addcd506 cosmetic: Sort DATE_FIELDS in export.py source. 2021-12-06 13:27:25 -08:00
Steve Howell f83907d3bb export: Add MutedUser table.
Note that the import was already implemented, but
its test was flawed.
2021-12-06 13:27:25 -08:00
Steve Howell 624260dd70 import: Extract re_map_realm_emoji_codes. 2021-12-06 13:27:24 -08:00
Steve Howell 6ec5a5193a tests: Verify emoji codes. 2021-12-06 13:22:47 -08:00
Palash e1796b0c8f onboarding: Manage occurrence of 'help' command.
"help" command occurs in the command list in
initial pms or when bot doesn't understand the message. It doesn't
occur when the bot is respoding to the "help" command itself.
2021-12-06 11:32:00 -08:00
Sahil Batra b68ebf5a22 message: Check wildcard mention restrictions while editing message.
This commit adds code to check whether a user is allowed to use
wildcard mention in a large stream or not while editing a message
based on the realm settings.

Previously this was only checked while sending message, thus user
was easily able to use wildcard mention by first sending a normal
message and then using a wildcard mention by editing it.
2021-12-06 10:22:29 -08:00
Aman Agrawal d2d6e1577f events: Explicitly send empty drafts to spectators.
This is purely for readability reasons, we still send empty
drafts without this change since UserProfile is None.

Fixes #20297
2021-12-03 14:34:21 -08:00
Palash a444560684 onboarding: Replace 'edit profile' with 'profile' in bot command list.
And change the tests accordingly.
2021-12-02 08:12:51 -08:00
Palash 6404b7bf61 onboarding: Make Welcome Bot more interactive.
1. The initial welcome message now contains less detail.
2. The bot now responds to these commands: "apps", "edit profile",
"dark mode", "light mode", "streams", "topics", "message formatting",
"keyboard shortcuts" and "help" - the bot still responds if there are
slight variations in these commands.
3. Tests have been made to check if bot responds to the advertised
commands (with variations) and gives a negative message if it doesn't
understand the message.

With substantial tweaks by tabbott.

Fixes #19900.
2021-12-01 16:30:48 -08:00
Mateusz Mandera 994ab8115e scim: Order Users by id when queried using filter syntax.
django-scim2 doesn't order the rows when fetching them in reponse to a
query using the filter syntax. We ensure that ORDER BY id is always
appended to the SQL queries.
2021-11-26 16:06:16 -08:00
Steve Howell 946e8064a3 user exports: Add several tables to the tarball.
We add the following tables to the user export:

    AlertWord
    CustomProfileFieldValue
    RealmAuditLog
    Service
    UserActivity
    UserActivityInterval
    UserCount
    UserGroup
    UserHotspot
    UserPresence
    UserTopic

Except for UserCount, we achieve this by sharing
code with the realm export via
add_user_profile_child_configs.

UserCount is handled slightly differently than realm
exports due to which key we trigger off.

It's possible that RealmAuditLog is incomplete for
single users, since we may also want rows where they
are the acting_user. This commit finds rows where
they are the modified_user. For non-admins I believe
it's rarely the case that they are the actor, and
they will tend to be the modified user if the two
fields are different at all.  For admins it's
arguable we want to see both changes they enacted
as well as changes that affected them.
2021-11-25 08:36:43 -08:00
Sahil Batra 2c1a87166c register: Pass settings.WEB_PUBLIC_STREAMS_ENABLED to clients.
This commit adds 'server_web_public_streams_enabled' field to
the register response to pass settings.WEB_PUBLIC_STREAMS_ENABLED
to clients.
2021-11-23 10:48:20 -08:00
Shlok Patel b3c58f454f api: Prevent special characters in topics.
Special characters, including `\r`, `\n`, and more esoteric codepoints
like non-characters, can negatively affect rendering and UI behaviour.

Check for, and prevent making new messages with, characters in the
Unicode categories of `Cc` (control characters), `Cs`, (surrogates),
and `Cn` (unassigned, non-characters).

Fixes #20128.
2021-11-22 22:09:06 -08:00
Sahil Batra eef9dd963b zcommand: Replace "mode" with "theme" in the returned message.
This commit replaces "dark mode" and "light mode" with "dark theme"
and "light theme" in the message returned and shown in a little
popup in the UI, when color scheme settings are changed through
slash commands.
2021-11-22 14:59:16 -08:00
Aman Agrawal 2c4af0e111 integration: Fix overflowing display name on open collective page.
Removed extra text to stop display name from flowing out of logo
container.
2021-11-21 21:05:06 -08:00
Aman Agrawal 334f046842 events: Don't send data related to custom profile field to spectator.
Since spectators can't access personal profile settings and
can't view profile for other users. Hence, we don't send realm
custom profile field data and user's profile data to spectators.

Fixes #20301.
2021-11-20 21:01:38 -08:00
Sahil Batra b72035abfe misc: Replace "Light mode" with "Light theme". 2021-11-19 11:49:59 -08:00
Sahil Batra 5024ba98cd misc: Rename "dark mode" to "dark theme".
Fixes part of #20228.
2021-11-18 16:57:11 -08:00
Sahil Batra 08404f2824 help: Rename night-mode.md to dark-theme.md.
Fixes part of #20228.
2021-11-18 16:55:35 -08:00
Aman Agrawal 00d3b88257 realm: Enable spectator access by default in development.
Enable spectator access for test `zulip` realm in developement
setup.

Add option in `do_create_realm` to configure
`enable_spectator_access` field of `Realm`.
2021-11-18 12:55:12 -08:00
Lauryn Menard 5300ad8ca0 api_documentation: Display `null` data type if potential value.
If null is a potential value of data type for a return value or
parameter in the API endpoint, then it is rendered as an option.

This currently relies on the 'nullable' setting in the OpenAPI spec
that was removed in the 3.1.0 release. If/when the OpenAPI version
is updated, then how the `data_type` for parameters and return values
is rendered will need to be reworked.

Fixes #20264.
2021-11-17 13:20:24 -08:00
Alex Vandiver faeffa2466 queue_processors: Set a bounded prefetch size on rabbitmq queues.
RabbitMQ clients have a setting called prefetch[1], which controls how
many un-acknowledged events the server forwards to the local queue in
the client.  The default is 0; this means that when clients first
connect, the server must send them every message in the queue.

This itself may cause unbounded memory usage in the client, but also
has other detrimental effects.  While the client is attempting to
process the head of the queue, it may be unable to read from the TCP
socket at the rate that the server is sending to it -- filling the TCP
buffers, and causing the server's writes to block.  If the server
blocks for more than 30 seconds, it times out the send, and closes the
connection with:

```
closing AMQP connection <0.30902.126> (127.0.0.1:53870 -> 127.0.0.1:5672):
{writer,send_failed,{error,timeout}}
```

This is https://github.com/pika/pika/issues/753#issuecomment-318119222.

Set a prefetch limit of 100 messages, or the batch size, to better
handle queues which start with large numbers of outstanding events.

Setting prefetch=1 causes significant performance degradation in the
no-op queue worker, to 30% of the prefetch=0 performance.  Setting
prefetch=100 achieves 90% of the prefetch=0 performance, and higher
values offer only minor gains above that.  For batch workers, their
performance is not notably degraded by prefetch equal to their batch
size, and they cannot function on smaller prefetches than their batch
size.

We also set a 100-count prefetch on Tornado workers, as they are
potentially susceptible to the same effect.

[1] https://www.rabbitmq.com/confirms.html#channel-qos-prefetch
2021-11-16 11:48:50 -08:00
Alex Vandiver 7c3507feef queue: Allow passing down a prefetch count to pika. 2021-11-16 11:48:50 -08:00
Alex Vandiver d1822b5630 tests: Move simulated_queue_client to the only test it is used in. 2021-11-16 11:48:50 -08:00
Alex Vandiver 6b6dcf6ce1 soft_deactivate: Handle multiple SUBSCRIPTION_DEACTIVATEDs.
Race conditions in stream unsubscription may lead to multiple
back-to-back SUBSCRIPTION_DEACTIVATED RealmAuditLog entries for the
same stream.  The current logic constructs duplicate UserMessage
entries for such, which then later fail to insert.

Keep a set of message-ids that have been prep'd to be inserted, so
that we don't duplicate them if there is a duplicated
SUBSCRIPTION_DEACTIVATED row.  This also renames the `message` local
variable, which otherwise overrode the `message` argument of a
different type.
2021-11-10 12:19:25 -08:00
YashRE42 778b7c0bdb links: Replace all references to Django docs to link to /3.2/ version.
Previously, our codebase contained links to various versions of the
Django docs, eg https://docs.djangoproject.com/en/1.8/ref/
request-response/#django.http.HttpRequest and https://
docs.djangoproject.com/en/2.2/ref/settings/#std:setting-SERVER_EMAIL
opening a link to a doc with an outdated Django version would show a
warning "This document is for an insecure version of Django that is no
longer supported. Please upgrade to a newer release!".

Most of these links are inside comments.

Following the replacement of these links in our docs, this commit uses
a search with the regex "docs.djangoproject.com/en/([0-9].[0-9]*)/"
and replaces all matches with "docs.djangoproject.com/en/3.2/".

All the new links in this commit have been generated by the above
replace and each link has then been manually checked to ensure that
(1) the page still exists and has not been moved to a new location
(and it has been found that no page has been moved like this), (2)
that the anchor that we're linking to has not been changed (and it has
been found that no anchor has been changed like this).

One comment where we mentioned a Django version in text before linking
to a page for that version has also been changed, the comment
mentioned the specific version when a change happened, and the history
is no longer relevant to us.
2021-11-08 18:06:16 -08:00
Alex Vandiver e3ec2e398c rate_limit: Pass seconds to freedom to all RateLimited exceptions. 2021-11-04 20:34:39 -07:00
Shlok Patel 893c9bc896 export: Remove `--delete-after-upload` flag in realm export.
For export realm following changes have been made:
- `./manage.py export --upload` would delete `.tar.gz` and unpacked dir
- `./manage.py export` would only delete `unpacked dir`

Besides, we have removed `--delete-after-upload` as we have set it as
the default.

Fixes #20081
2021-11-03 11:14:02 -07:00
Tim Abbott 4d055a6695 push_notifications: Truncate overly large remove events.
Fixes #19224.
2021-11-02 21:24:14 -07:00
Aman Agrawal 3e689ebae9 users: Allow spectators to view user avatars.
If realm is web_public, spectators can now view avatar of other
users.

There is a special exception we had to introduce in rest model to
allow `/avatar` type of urls for `anonymous` access, because they
don't have the /api/v1 prefix.

Fixes #19838.
2021-11-02 11:26:19 -07:00
Sahil Batra e6106cb334 invites: Update error message when max limit for the day is reached.
This commit updates the error message returned when the maximum
invite limit for the day. We update the error returned by API to
only mention that the limit is reached and add the suggestion
to use multi-use link or contact support in the message shown
in webapp.
2021-11-01 16:36:26 -07:00
Sahil Batra 84cd68a5aa realm: Create RealmUserDefault object for internal realm.
We create RealmUserDefault object for internal realm just
for consistency. The code in migration does so but it
was missed to add the code when creating new internal realm.
2021-10-29 16:19:55 -07:00
Mateusz Mandera 4105ccdb17 saml: Implement IdP-initated logout for Keycloak.
Fixes #13948.
2021-10-27 13:13:55 -07:00
Alex Vandiver 6a40c17ccf markdown: CSS-escape preview links.
This adds `soupsieve` as an explicit dependency, but intentionally
does not adjust the provision version, as it was already an indirect
dependency.
2021-10-26 18:17:23 -07:00
Alex Vandiver 52f74bbd9b markdown: Run URL preview links through camo.
Not proxying these requests through camo is a security concern.
Furthermore, on the desktop client, any embed image which is hosted on
a server with an expired or otherwise invalid certificate will trigger
a blocking modal window with no clear source and a confusing error
message; see zulip/zulip-desktop#1119.

Rewrite all `message_embed_image` URLs through camo, if it is enabled.
2021-10-26 18:17:23 -07:00
Anders Kaseorg 58920affd4 python: Remove re.UNICODE flag (redundant in Python 3).
https://docs.python.org/3/library/re.html#re.A

Signed-off-by: Anders Kaseorg <anders@zulip.com>
2021-10-22 13:42:29 -07:00
Alex Vandiver 9381a3bd45 linkifiers: Support URL percent-encoded bytes.
Supporting URL percent-encoded bytes is possible using `%%20`, but this
is not necessarily very understandable to end-users, even those that
understand percent encoding.

Allow `%20` in linkifier URL format strings, and transform them into
`%%20` in the pattern just before they are applied in markdown
translation.  Care must be taken here, such that already-escaped `%`s
are not escaped an extra time.

We do this before rendering, and not before storage, as
a simplification; the JS-side linkifier at present only understands
`%(foo)s` and thus needs no changes, and to avoid an un-escaping pass
before showing in the admin UI.
2021-10-22 13:00:20 -07:00
Anders Kaseorg 4839b7ed27 url_preview: Interpret og:image relative to full page URL.
og:image is supposed to be an absolute URL, but some sites incorrectly
provide a relative URL.  In this case, it makes more sense to
interpret it relative to the full page URL after redirects, rather
than relative to just the domain part of the page URL before
redirects.

Signed-off-by: Anders Kaseorg <anders@zulip.com>
2021-10-21 12:20:37 -07:00
Jonny Tran ddf4053a73 composebox_typeahead: Remove redundant options from the `/` typeahead.
Removes the `/day` and `/night` options from the typeahead menu while
still allowing the commands to be used. Typing `/day` and `/night`
will now suggest `/light` and `/dark`, respectively. Also changes the
`Dark mode` and `Light mode` popups that appear after using the
corresponding command.

Fixes #18318.
2021-10-21 10:50:27 -07:00
Anders Kaseorg d1c05467ec push_notifications: Fix RemoteZulipServer annotation to work at runtime.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2021-10-20 00:48:55 -07:00
Alex Vandiver c0b557fb2e push_notifications: Move zilencer import inside ZILENCER_ENABLED check. 2021-10-20 06:16:10 +00:00
Alex Vandiver 111ee64e36 push_notifications: Pass down the remote server and user-id for logs.
This makes logging more consistent between FCM and APNs codepaths, and
makes clear which user-ids are for local users, and which are opaque
integers namespaced from some remote zulip server.
2021-10-19 22:04:24 -07:00
Alex Vandiver 5bcd3c01cb push_notifications: Add log line with user-id, UUID, and devices.
Being able to determine how many distinct users are getting push
notifications per remote host is useful, as is the distribution of
device counts.  This parallels the log line in
handle_push_notification for push notifications from local realms,
handled via the event queue.
2021-10-19 22:04:24 -07:00
rht bb8504d925 lint: Fix typos found by codespell. 2021-10-19 16:51:13 -07:00
Eeshan Garg b325a4f1be realm: Rename plan type constants to be more descriptive.
It is confusing to have the plan type constants not be namespaced
by the thing they represent. We already have a namespacing
convention in place for constants, so we should use it for
Realm.plan_type as well.
2021-10-19 12:20:39 -07:00
Alex Vandiver b02754adec html_diff: Handle empty differences between empty strings.
`rendered_content` in historical messages may be empty; examining the
history of them may thus require diff'ing two empty strings, which
itself produces an empty string.

Use `lxml.html.fragment_fromstring` to be able to successfully parse
these, rather than 500.

Part of #19559.
2021-10-18 18:27:40 -07:00
Mateusz Mandera f5a65846a8 scim: Override django-scim2 logic of exception handling in views.
As detailed in the comments, the default behavior is undesirable for us
because we can't really predict all possibilities of exceptions that may
be raised - and thus putting str(e) in the http response is potentially
insecure as it may leak some unexpected sensitive information that was
in the exception.

As a hypothetical example - KeyError resulting from some buggy
some_dict[secret_string] call would leak information. Though of course
we aim to never write code like that.
2021-10-17 21:33:03 -07:00
Vishnu KS aff52722a7 billing: Add PLUS as a plan_type to Realm. 2021-10-15 17:27:50 -07:00
Alya Abbott 60535adfc7 onboarding: Update Welcome Bot.
The most important thing is linking to the new user guide.
2021-10-15 12:59:20 -07:00
Anders Kaseorg 3bd3173b1f avatar: Remove ?x=x kludge.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2021-10-14 12:47:43 -07:00
Anders Kaseorg 58771d6e66 avatar: Use append_url_query_string.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2021-10-14 12:47:43 -07:00
Anders Kaseorg f42e191776 url_encoding: Use proper parsing for query string appending.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2021-10-14 12:47:43 -07:00
Mateusz Mandera 73a6f2a1a7 auth: Add support for using SCIM for account management. 2021-10-14 12:29:10 -07:00
Mateusz Mandera 7c0995b14b actions: Support acting_user=None in check_change_full_name.
do_change_full_name supports it already, so this is a trivial change.
2021-10-14 12:28:35 -07:00
Anders Kaseorg 1e5157b66c user_groups: Add a recursive group membership model.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2021-10-13 10:08:06 -07:00
Sahil Batra 6ac9386a29 models: Add related_name to UserGroup and UserGroupMembership fields.
This commit adds related_name parameter to UserGroup.direct_members
such that we can use direct_groups instead of the default
usergroupmembership_set for getting all the groups of which the
user is direct member.

This commit also sets related_name of UserGroupMembership.user_group
and UserGroupMembership.user_profile to "+" which means that we will
not be having backward relations for these. This change is correct
since we would need to use the recursive queries to get all the
groups of a user and all the members of a group after we add the
subgroups concept in next commit. This leads to us using direct_members
field of UserGroup instead of usergroupmembership_set in mention code,
but this will soon be replaced with the recursive query function to
include subgroup's members as well.

Extracted this commit from #19866.

Authored-by : Anders Kaseorg <anders@zulip.com>
2021-10-13 10:08:06 -07:00
Sahil Batra 6f31b959ac user_groups: Fix return type of get_user_group_direct_members.
This commit fixes return type of get_user_group_direct_members
function which returns a list of user profile ids and not UserProfile
objects.
2021-10-13 16:57:04 +05:30
Sahil Batra b65aadae4b user_groups: Make get_user_group_direct_members query efficient.
This commit makes the query in get_user_group_direct_members
efficient by directly fetching user-profile ids instead of
first fetching user profile object and then id.
2021-10-13 16:56:44 +05:30
Sahil Batra 2d39b14a38 user_groups: Rename members field of UserGroup to direct_members.
This commit renames members field of UserGroup to direct_members
for better readability because in the new permissions model, a
user group can be a sub-group of another group and thus technically
members of sub-group will also be members of that group.
This is a prep commit for new permissions model.

Extracted this commit from #19866.

Co-authored-by: Anders Kaseorg <anders@zulip.com>
2021-10-12 13:57:53 -07:00
Sahil Batra e47662aa19 user_groups: Rename get_memberships_of_users.
This is a prep commit for new permissions model in
which a user group would be able to have a subgroup.

This commit renames get_memberships_of_users to
get_direct_memberships_of_users to specify that
the function is used only to fetch the direct
memberships and not memberships of subgroups of
the direct group.

Extracted this commit from #19866.

Co-authored-by: Anders Kaseorg <anders@zulip.com>
2021-10-12 13:57:47 -07:00
Sahil Batra 07e2ecf221 user_groups: Rename get_user_groups to get_direct_user_groups.
This is a prep commit for new permissions model in which a user
group would be able to have a subgroup.

This commit renames get_user_groups to get_direct_user_groups
to specify that the function is used only to fetch the direct
groups that user is part of and not subgroups of the direct
group.

Extracted this commit from #19866.

Co-authored-by: Anders Kaseorg <anders@zulip.com>
2021-10-12 13:57:32 -07:00
Sahil Batra 82af2d3db5 user_groups: Rename get_user_group_members to get_user_group_direct_members.
This is a prep commit for new permissions model in which a user group would
be able to have a subgroup.

This commit renames get_user_group_members to get_user_group_direct_members
to specify that the function is used only to fetch direct members of group
and excludes the subgroup's members.

Extracted this commit from #19866.

Co-authored-by: Anders Kaseorg <anders@zulip.com>
2021-10-12 13:57:26 -07:00
Dinesh 0b68f264c6 apply_event: Do not include new user settings in the top level.
From 430c5cb, in `fetch_initial_state_data`,
we only include legacy settings in the top level of
`state` and the newer ones are stored in `state['user_settings']`.
That should've had a corresponding change in apply_event().

Also, fixed a test related to this logic.
2021-10-07 16:39:51 -07:00
Eeshan Garg 29b354346b update_realm: Allow demo orgs to be converted to regular orgs.
This commit adds support to the `PATCH /realm` endpoint for
converting a demo organization to a regular organization.

This is a part of #19523.
2021-10-07 14:43:03 -07:00
Eeshan Garg f25230c7d4 analytics/support: Add ability to edit realm org type. 2021-10-07 14:08:11 -07:00
Alya Abbott 8045355eee user docs: Document public vs. private stream creation permissions. 2021-10-06 17:33:19 -07:00
Aman Agrawal 3b29c61409 auth: Add login buttons for web public access.
For users who are not logged in and for those who don't have
'prefers_web_public_view' set in session, we redirect them
to the default login page where they can choose to login
as spectator or authenticated user.
2021-10-05 16:30:40 -07:00
Sahil Batra ab0d852fd5 register: Add can_create_web_public_streams to register response. 2021-10-05 10:10:32 -07:00
Sahil Batra 2c2c19c4d4 streams: Restrict creating web public streams based on new setting.
This commit restricts creating web public streams based on the
recently added create_web_public_stream_policy setting.
2021-10-05 09:56:00 -07:00
Sahil Batra 3916181770 models: Add can_create_web_public_streams helper.
This commit adds can_create_web_public_streams helper
in models.py which will be used to validate whether
user is allowed to create a web-public stream or not.

This commit also adds the checks for Realm.POLICY_OWNERS_ONLY
in check_has_permission_policies.
2021-10-05 09:48:50 -07:00
Sahil Batra a63385f47f tests: Check all cases in check_has_permission_policies.
This commit adds tests for POLICY_EVERYONE and POLICY_NOBODY
in check_has_permission_policies test. The original code
used these values but these were not covered in test.
2021-10-05 09:12:56 -07:00
Sahil Batra c07b8e9b44 tests: Validate owner users also in check_has_permission_policies.
We should validate owner user also for all policy values. This is
important when we will add tests for POLICY_NOBODY in next commit.
2021-10-05 09:12:56 -07:00
Sahil Batra eedd832ca9 events: Fix updating user email on changing email_address_visibility.
When email_address_visibility is changed and either the old value
or the updated value is EMAIL_ADDRESS_VISIBILITY_EVERYONE then
email field of all users is updated and we also send the corresponding
event to clients. But apply_event code did not update the data on
receiving the event, so this commit fixes the code to correctly
handle the event in apply_event.

(We also use this event when just changing a user's email address).

This commit also adds the tests and openapi schema for the event.
2021-10-04 17:24:31 -07:00
Eeshan Garg c4aeb159c4 topics: Fix translation issue with moved topic notifications.
Since the calls to the translation function `_()` are made outside
of the `send_message_moved_breadcrumbs` function, these strings are
translated outside of the `with override_language` block, leading to
translated strings even when we don't intend them to be translated.

We now use gettext_lazy with appropriate testing to avoid this.
2021-10-04 16:20:16 -07:00
Alex Vandiver db934be064 CVE-2021-41115: Use re2 for user-supplied linkifier patterns.
Zulip attempts to validate that the regular expressions that admins
enter for linkifiers are well-formatted, and only contain a specific
subset of regex grammar.  The process of checking these
properties (via a regex!) can cause denial-of-service via
backtracking.

Furthermore, this validation itself does not prevent the creation of
linkifiers which themselves cause denial-of-service when they are
executed.  As the validator accepts literally anything inside of a
`(?P<word>...)` block, any quadratic backtracking expression can be
hidden therein.

Switch user-provided linkifier patterns to be matched in the Markdown
processor by the `re2` library, which is guaranteed constant-time.
This somewhat limits the possible features of the regular
expression (notably, look-head and -behind, and back-references);
however, these features had never been advertised as working in the
context of linkifiers.

A migration removes any existing linkifiers which would not function
under re2, after printing them for posterity during the upgrade; they
are unlikely to be common, and are impossible to fix automatically.

The denial-of-service in the linkifier validator was discovered by
@erik-krogh and @yoff, as GHSL-2021-118.
2021-10-04 21:26:24 +00:00
Pradyumna Sinha 18b36e5b8c markdown/tabbed_sections: Raise exception for missing tab name.
This fixes the issue  where 'None' would appear in the rendered
html in case of a missing tab display_name. Now,
'test-help-documentation' will fail in case of any tab display_name
being missing.

In case of a tab_section with no tabs, currently a single tab with
the name 'null_tab' gets added. Added the display name 'None' for
'null_tab', to keep in line with the existing behaviour.

Fixes #19822
2021-10-01 16:25:17 -07:00
Pradyumna Sinha 78692e9c14 markdown/tabbed_sections: Don't set tab label as 'None' in case of no tabs. 2021-10-01 16:22:11 -07:00
Pradyumna Sinha fe5de4a128 markdown/tabbed_sections: Rename TAB_DISPLAY_NAMES to TAB_SECTION_LABELS. 2021-10-01 16:22:11 -07:00
Shlok Patel 1e18d36328 realm: Change default permissions for education organizations.
This makes our onboarding guide for education organizations much
simpler, since new organizations will start with these settings
correctly configured.

Fixes #19682
2021-10-01 15:33:33 -07:00
Ganesh Pawar fa928d5cd1 streams: Split setting for stream creation policy.
Users wanted a feature where they could specify
which users can create public streams and which users can
create private streams.

This splits stream creation code into two parts,
public and private stream creation.

Fixes #17009.
2021-10-01 10:26:42 -07:00
sahil839 909a3cde76 realm: Replace allow_message_deleting with delete_own_message_policy.
This commit replaces 'allow_message_deleting' boolean setting
with an integer setting 'delete_own_message_policy'. We have a
separate dropdown now for deciding which user-roles can delete
messages sent by themselves and the time-limit setting droddown
is different.

This new setting has two options - everyone and admins only. Other
options including moderators will be added further.

We also remove the "Never" option from the original time-limit
dropdown, as admins are always allowed to delete message. This
never option resembled the case of only admins being allowed to
delete but this state is now resembled by setting the dropdown
to "admins only" and we also disable the time-limit dropdown in
this case as admins are allowed to delete irrespective of limit.

Note, this setting is only for deleting messages sent by the
deleting user themselves, and only admins are allowed to delete
messages sent by others as before.
2021-09-30 14:59:31 -07:00
sahil839 b13bfa09c5 message: Make zero invalid value for message_content_delete_limit_seconds.
We make zero invalid value for message_content_delete_limit_seconds and
for handling the case of "Allow to delete message any time", the API-level
value of message_content_delete_limit_seconds is "anytime" and "None"
as the DB-level value. We also use these values for message retention
setting, so it helps maintain consistency.
2021-09-30 14:45:39 -07:00
Mateusz Mandera 0af7c84c99 push_notifs: Log the number of devices notification was sent to. 2021-09-29 15:50:06 -07:00
Sahil Batra d1732fb9da settings: Remove realm-level default of enable_login_emails setting.
This commit does not remove the 'enable_login_emails' field from
RealmUserDefault table but it is just not used and cannot be
changed from UI or API similar to 'enable_marketing_emails' setting.
2021-09-28 12:41:09 -07:00
Aman Agrawal ef84224eed message_edit: Allow spectators to access raw message content.
We allow spectators to fetch the raw / original content of a
message which is used by the spectator to "View source" of
the message.
2021-09-28 10:07:36 -07:00
Tim Abbott e556481ba0 streams: Remove duplicates of get_web_public_streams_queryset.
This is a somewhat subtle function, that deserves a few comments
explaining subtle details of its logic, and there's no good reason to
have multiple copies of that logic that are slightly inconsistent.

Because the main changes here are just checking for invariant
failures, the behavioral change here should be limited to ensuring
deactivated streams are not considered available even if they were
tagged as web public streams before deactivation.
2021-09-28 10:07:36 -07:00
Tim Abbott 272e81988b tornado: Make process_notification hack avoid import loops.
This fixes a problem where we could not import zerver.lib.streams from
zerver.lib.message, which would otherwise be reasonable, because the
former implicitly imported many modules due to this issue.
2021-09-28 10:07:36 -07:00
Anders Kaseorg 0f7d0a23c9 Revert "validator: Add generic check_or."
This reverts commit cd93d0967f.

This check_or is redundant with check_union; it gives a misleading
error message for the non-matching case; and it has no type safety.

Signed-off-by: Anders Kaseorg <anders@zulip.com>
2021-09-28 09:28:56 -07:00
seiwailai cd93d0967f validator: Add generic check_or.
Added generic check_or function and tests.
Fixes part of #17914.

Co-authored-by: Gaurav Pandey <gauravguitarrocks@gmail.com>
2021-09-27 17:30:26 -07:00
Kevin Scott 09851ff290 markdown: Document built-in preprocessor priorities for convenience.
Fixes #19810
2021-09-27 10:42:09 -07:00
Eeshan Garg bf64cb2d1c topics: Fix translation issue with resolve topic notifications.
In maybe_send_resolve_topic_notifications, since the calls to the
translation function `_()` are made outside of the `override_language`
block, the strings are not translated correctly.

This commit refactors the function to make sure that the translation
happens in the right block of code.

Fixes #19730.
2021-09-23 17:21:33 -07:00
Tim Abbott 417c32629d outgoing webhooks: Fix inconsistencies with Slack's API.
Apparently, our slack compatible outgoing webhook format didn't
exactly match Slack, especially in the types used for values.  Fix
this by using a much more consistent format, where we preserve their
pattern of prefixing IDs with letters.

This fixes a bug where Zulip's team_id could be the empty string,
which tripped up using GitLab's slash commands with Zulip.

Fixes #19588.
2021-09-23 11:19:20 -07:00
Sahil Batra c233ee9935 settings: Migrate twenty_four_hour_time setting to RealmUserDefault.
This commit removes the existing default_twenty_four_hour_time field in
Realm table which was used to set the twenty_four_hour_time setting of
new user on joining and instead we now use the twenty_four_hour_time
field of RealmUserDefault table for the same.

With some tweaks by tabbott to clarify the documentation.
2021-09-23 10:44:42 -07:00
Alya Abbott 0f9d0f5a86 help_docs: Reorganize notification docs under three umbrella pages.
With minor URL migration work by Eeshan Garg.
2021-09-22 16:46:46 -07:00
Mateusz Mandera 491f763f4e models: Improve conversion of CustomProfileField values.
These values are currently either a string already or a List[int]. We
should do the conversion in
do_update_user_custom_profile_data_if_changed properly: if the value is
already a string, it can be used directly - if it's not, orjson.dumps is
a more future-proof way of converting than str(). Using orjson.dumps
here also allows us to change the converter of the USER type
CustomProfileField to orjson.loads, which is nicer to have than
ast.literal_eval.
While orjson.dumps() and str() give the same output when
given the special case of List[int],
ast.literal_eval was previously used due to orjson.loads not being
a good inverse function to str in general. That gets straightened out
now.
2021-09-22 16:22:46 -07:00
Mateusz Mandera cacff28578 types: Fix declared type of custom profile field values.
None of the existing custom profile field types have the value as an
integer like declared in many places - nor is it a string like currently
decalred in types.py. The correct type is Union[str, List[int]]. Rather
than tracking this in so many places throughout the codebase, we add a
new ProfileDataElementValue type and insert it where appropriate.
2021-09-22 16:22:46 -07:00
Mateusz Mandera 91ea21a3fc actions: Fix type-incorrect custom profile field value assignment.
The old assignment is incorrect - field_value.value is a TextField() and
should always be a string. This didn't strictly break anything, because
django converts the value to a string when .save()ing to the db, but
field_value.value persists as a non-string for the rest of this
codepath. After fixing this, the small codeblock in
notify_user_update_custom_profile_data handling conversion of
field_value.value to a string becomes redundant.

We're assured that we're not breaking event format by the test
test_custom_profile_field_data_events in test_events.py.
2021-09-22 16:22:46 -07:00
Alya Abbott c7544d620d user docs: Fix missing tab name on /help/getting-your-organization-started-with-zulip. 2021-09-22 14:29:44 -07:00
Alya Abbott b773048031 user docs: Add documentation for configuring new user defaults.
Also remove a redundant link on customize-settings-for-new-users page.
2021-09-21 16:43:35 -07:00
Aman Agrawal 233d250eff do_make_stream_web_public: Send update to client.
Send update event to client after a stream is made web public.

This has been documented in the API documentation since feature level
73; previously the value was always false.
2021-09-21 12:16:10 -07:00
Aman Agrawal 5138652810 update_stream_backend: Add ability to make streams web public.
We allow clients to make existing streams web public via the API.

This feature is still disabled via settings in production
environments, because we may have additional policy rules or UI
warnings we wish to add to this sort of conversion.
2021-09-21 12:16:09 -07:00
Aman Agrawal 6a78112940 subscribe: Allow web public stream creation via the API.
User can now create web public stream via the /subscribe API.
So, when a web public stream present in the API request does not
exist, it will be created now by specifying the is_web_public
parameter. The parameter would have been ignored without this
commit.
2021-09-21 11:20:36 -07:00
Tim Abbott eb62693d26 list_to_streams: Use simpler if statement flow.
Since each if statement just raises an exception if triggered,
removing the else blocks makes the logic more readable.
2021-09-21 11:06:05 -07:00
Tim Abbott 71b8a1794a streams: Use standard error message when requiring owner.
The new error message is more clear about why, "User cannot create
stream with this settings." was bad English, and in any case removing
an unnecessary string is always an improvement for translators.
2021-09-21 11:05:30 -07:00
Eeshan Garg 5839f16969 markdown: Run settings_tab/relative links extensions after include.
Recently, we discovered that our settings_tab/relative Markdown
directives didn't work when they were in a macro that was included
in another Markdown file. Note that without this commit, the
/help/create-your-organization-profile page is broken. This commit
changes the respective priorities of these two extensions such that
these directives are rendered *after* the macro is included in
another file.

Thanks to Alya Abbott for reporting this bug!
2021-09-20 16:57:43 -07:00
Eeshan Garg bfbd77ca5c markdown: Organize preprocessor priorities in one place.
All of our custom Markdown extensions have priorities that govern
the order in which the preprocessors will be run. It is more
convenient to have these all in one file so that you can easily
discern the order at first glance.

Thanks to Alya Abbott for reporting the bug that led to this
refactoring!
2021-09-20 16:57:43 -07:00
Alya Abbott 2f3ebb5b16 help: Merge "Change who can add custom emoji" into "Custom emoji" page. 2021-09-17 18:08:59 -07:00
Alya Abbott 302aba035a help: Rename add-custom-emoji -> custom-emoji. 2021-09-17 18:08:59 -07:00
Abhijeet Prasad Bodas 743712c267 user_topic: Filter on visibility_policy in muted_topic code.
This is the final step required for it to be possible for us to add
UserTopic rows in the future with a differen visibility_policy.

Fixes #19272.
2021-09-17 12:14:28 -07:00
Abhijeet Prasad Bodas 4455dac424 models: Use default db table name for UserTopic.
Also update the realm import/export code and tests accordingly.
2021-09-17 12:14:28 -07:00
Abhijeet Prasad Bodas 2aea944a7e models: Rename UserTopic.date_muted to last_updated.
This is a follow-up to #19388.

We will in the future allow patch requests to change the visibility
of an existing topic, so `last_updated` is better name for this field.

This commit does not affect the API or events in any way, but only the
database.
2021-09-17 12:14:28 -07:00
Alya Abbott 310b8736af user docs: Add a bunch of "getting started" content. 2021-09-16 11:41:43 -07:00
Mateusz Mandera 05fe62c96c docs: Adjust phrasing of "From your desktop, click on the gear...".
We actually mean the main Zulip UI here, so "from your desktop" sounds
potentially misleading; reodering the phrasing makes the meaning
unambiguous.
2021-09-16 10:47:56 -07:00
Tim Abbott 39c897a2b0 help: Rename about-streams-and-topics to streams-and-topics.
This better matches the title of the page and more generally our
conventions around naming /help/ articles.  We include a redirect
because this is referenced from Welcome Bot messages, and we
definitely don't want those links to break.
2021-09-15 09:48:36 -07:00
Alex Vandiver 8c72959951 push_notifications: Handle empty rendered_messages.
This parallels fe25517295, but for mobile notifications.  It also
adds a test, which verifies that such content does not crash either
mobile or email notifications.
2021-09-15 09:45:38 -07:00
Alex Vandiver 039b869ca5 email_notifications: Fix inline-ing of image-URL-only messages.
fe25517295 adjusted the email_notifications codepath to use
`lxml.html.fragment_fromstring` method when parsing
`rendered_content`, but left the tests using a helper which called
`fromstring`.

Switching the tests to match the code as run reveals a bug -- using
`drop_tree` on all `message_inline_image` classes now _does_ remove
all of a top-level image-URL-only message.  Previously, such messages
were "safe" from the block that calls `drop_tree` only by dint of
`drop_tree` being a silent no-op for the root element.  When parsed
using `fragment_fromstring`, they are no longer the root, and as such
an empty message results.

Reorder relative_to_full_url to check for only one `message_inline_image`
within the top `<div>`, and only run the `drop_tree` path in the
alternate case.  Tests must be adjusted for their output now including
one more layer of `<div>`.
2021-09-15 09:45:38 -07:00
Mateusz Mandera 5d54cd1041 tests: Use a HttpRequest object in assert_login_failure.
Our convention is to always have authenticate() called with a request
object. We need to be consistent with that in tests too, to avoid test
failures resulting from breaking that assumption.
We modify assert_login_failure to call client.login() in the same way as
the other similar helpers - with a properly initialized HttpRequest
instance.
2021-09-14 15:39:41 -07:00
Aman Agrawal dff4ab0daf spectators: Add comments and assertions on security model.
These tweaks help make reasoning about the spectators security model
easier to understand.
2021-09-14 10:33:14 -07:00
Riken Shah 8c31e6f96e emoji: Add backend changes to support still image for animated emojis.
Now, when we add a custom animated emoji to the realm
we also save a still image of it (1st frame of the gif). So
we can avoid showing an animated emoji every time.
2021-09-12 07:13:04 +00:00
Mateusz Mandera ad188130ba do_send_confirmation_email: Make invite_expires_in_days optional.
create_confirmation_link has validity time as an optional argument,
because it has reasonable defaults. Thus it's a better API for
do_send_confirmation_email to make this optional as well, allowing
relying on create_confirmation_link's defaults.
2021-09-10 16:53:03 -07:00
Mateusz Mandera 3205f680c1 do_invite_users: Turn some args into kwargs-only. 2021-09-10 16:53:03 -07:00
shanukun 8c1ea78d7d invite: Extend invite api for handling expiration duration.
This extends the invite api endpoints to handle an extra
argument, expiration duration, which states the number of
days before the invitation link expires.

For prereg users, expiration info is attached to event
object to pass it to invite queue processor in order to
create and send confirmation link.
In case of multiuse invites, confirmation links are
created directly inside do_create_multiuse_invite_link(),

For filtering valid user invites, expiration info stored in
Confirmation object is used, which is accessed by a prereg
user using reverse generic relations.

Fixes #16359.
2021-09-10 16:53:03 -07:00
Eeshan Garg 85b1f1bed9 email: Update follow-up day 1 emails to mention demo orgs.
This is a part of #19523.
2021-09-10 16:31:54 -07:00
Eeshan Garg bf9c35ded4 onboarding: Mention demo orgs in Welcome Bot's PMs.
This is a part of #19523.
2021-09-10 16:31:54 -07:00
Abhijeet Prasad Bodas 17b8d53612 email notifs: Update scheduled timestamps after batching period change.
The API for changing the batching period was added in
5db4fe8652.

This is a follow up to that commit. We also update the timestamps for
existing scheduled email notifications entries so that the effect of
changing the setting is immediate.

Part of #15280
2021-09-10 13:25:47 -07:00
Mateusz Mandera f064e3ebac auth: Ensure a realm can't be created on SOCIAL_AUTH_SUBDOMAIN. 2021-09-10 10:47:15 -07:00
Anders Kaseorg c14549f275 name_restrictions: Reserve ‘mg’ and ‘front-mail’.
These hostnames only have MX records for Mailgun and Front, and will
not work as a Zulip organization.

Signed-off-by: Anders Kaseorg <anders@zulip.com>
2021-09-10 10:25:56 -07:00
Sahil Batra c7cb983ebd settings: Move check_settings_values to user_settings.py.
This commit moves check_settings_values to user_settings.py
from validator.py such that we can import the functions at
the top without any issue of cyclic imports.
2021-09-09 15:03:55 -07:00
Sahil Batra 88346949b5 messages: Do not allow mentioning system user groups.
We do not allow mentioning system user groups for now
because this can lead to circumventing the wildcard
mention restrictions. It will be enabled once we add
a setting to control that.

This is implemented by just ignoring it as one of the
mentioned user group even if the message content
inlcudes the mention syntax for it and the message
is sent normally.

We still keep the for_mention parameter for accessing
user group while sending email and push notifications
as mentioning system user groups will be allowed in
future.
This commit also removes the test for email notifications
for system user groups as we are not allowing mentioning
them.

This commit is only for backend change as we already
exclude the system groups from mention typeaheads and
other UI.
2021-09-09 11:25:33 -07:00
Parth 9ed707c34b authentication: Fix placeholder realms for redirects.
The name of the new realm created as a tombstone after renaming
a realm's subdomain is the constant 'placeholder-realm'.
This would confuse the user when shown the deactivation notice
and asking to join the realm at a new subdomain.
This PR replaces it with the original realm name to avoid confusion.
Fixes: #19677
2021-09-09 11:02:45 -07:00
sahil839 8bab712cb4 create_user: Initialize settings according to realm-level defaults.
This commit modifies the copy_user_settings code such that instead
of source user profile, we can have two types of sources - a user
profile and RealmUserDefault table of realm and then set the
settings from RealmUserDefault only is there is no user profile
as a source.

We also rename copy_user_settings to copy_default_settings for
clarity.
2021-09-09 10:55:19 -07:00
Sahil Batra 693d58265e realm: Add 'PATCH /realm/user_settings_defaults' endpoint.
The realm-level default value of settngs for new users will
be updated using this endpoint.
2021-09-09 10:55:18 -07:00
Sahil Batra 17087cf06f actions: Add do_set_realm_user_default_setting.
This commit adds do_set_realm_user_default_setting which
will be used to change the realm-level defaults of settings
for new users.

We also add a new event type "realm_user_settings_defaults"
for these settings and a "realm_user_settings_default" object
in '/register' response containing all the realm-level default
settings.
2021-09-09 10:38:38 -07:00
sahil839 7d64a9053b models: Ensure every realm has a RealmUserDefault object.
Because we create all realms with do_create_user (including in the
test suite), we just need to change that function, add a migration for
existing realms, and ensure the data import code path correctly
creates these objects.

Note that the import code path will create a RealmUserDefault row with
default values if it is not present in the import data, which is
important for importing data from other tools like Slack.
2021-09-09 10:28:44 -07:00
Sahil Batra 97f41b5abd users: Change type of enable_marketing_emails parameter in create_user.
This commit changes the type of enable_marketing_emails parameter of
create_user to Optional[bool].
The value of this parameter will be None in certain cases when user
registers through SSO and 'TERMS_OF_SERVICE=False' when there will
be no registration form and thus no value of enable_marketing_emails.
2021-09-09 10:15:07 -07:00
Sahil Batra 03a0cfda64 settings: Set enable_marketing_emails after copying user settings.
We set the enable_marketing_emails setting after copying user
settings to override the value selected in registration form.
This change is also necessary because enable_marketing_emails
field is present in RealmUserDefault to avoid copying code
but we do not use this value actually and instead we want
the setting to be set according to the value in registration
form.

We set this setting only for non-bot users since we generally
do not set any settings for bots.
2021-09-09 10:15:07 -07:00
Sahil Batra 2eec0772fb user_settings: Extract setting values checks to a function.
We extract the checks for default_language, notification_sound,
and email_notifications_batching_period_seconds setting values
in json_change_settings to a new function check_settings_values.
2021-09-09 10:15:07 -07:00
Tim Abbott c5261af2dc migrations: Fix system bot realm not having a name.
This prevented migration 0345
(517c2ed39d / #19696) from applying on
systems that were created after the refactoring that resulted in the
system bot realm potentially having null as its name.

(We've already confirmed that normal realms, created via
`do_create_realm`, shouldn't be able to have this unusual state).
2021-09-09 09:50:43 -07:00
Tim Abbott 545911b051 markdown: Remove useless locless_schemes check.
This check was copied from upstream python-markdown's "safe mode"
before they removed that feature.  The upstream history is that they
introduced this check in
2db5d1c8e4,
which was not a complete security check, and then added the
immediately following check (with an allowlist of schemes) in
0b4ffbb60e.

Their first, incomplete check provides no security benefit and makes
the code hard to reason about, so we remove it.
2021-09-09 09:03:40 -07:00
rht c24ab8c4d3 markdown: Expand list of safelisted URL schemes to match HTML spec. 2021-09-09 09:03:40 -07:00
Sahil Batra 9c4eb764e2 create_user: Do not set enter_sends value twice.
enter_sends is already included in property_types
dict, so there is no need to set it again using
setattr in copy_user_settings.
2021-09-09 09:03:06 -07:00
Sahil Batra 8b711695cb event_schema: Use notification_settings_legacy to get type.
The 'update_global_notifications' type event is sent only for
existing settings and will not be sent for new settings, so we
should use notification_settings_legacy dict to check the type
of setting value in check_update_global_notifications instead
of notification_settings_types dict.
2021-09-09 09:03:06 -07:00
Sahil Batra 526de3f7d1 settings: Remove unnecessary loop of notification_setting_types.
We still used notification_setting_types in copy_user_settings
function of create_user.py and in a test in test_event_system.py.
It is not required to do so since we have added all settings in
property_types already and we loop over property_types at both
these places which includes all settings.
2021-09-09 09:03:06 -07:00
Sahil Batra 2f61afea9f settings: Remove do_change_notification_settings function.
This commit removes the do_change_notification_settings
function and we use do_change_user_setting directly to
change all the user settings now.
2021-09-08 11:04:44 -07:00
Sahil Batra 991efaf450 actions: Make acting_user manadatory kwarg for do_change_user_setting. 2021-09-08 11:04:44 -07:00
Sahil Batra 550d97a593 settings: Refactor callers of do_change_user_setting to pass acting_user. 2021-09-08 11:04:44 -07:00
Eeshan Garg f0ea002d94 events: Add demo_organization_scheduled_deletion_date to /register.
This commit adds `demo_organization_scheduled_deletion_date` to
the `realm` section of the `/register` response so that it is
available to clients when enabled.

This is a part of #19523.
2021-09-07 17:40:33 -07:00
Anders Kaseorg 66ad6a4583 docs: Inline code spans are not blocks.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
2021-09-07 16:12:39 -07:00
Tim Abbott dd6cc32ae5 do_change_notification_settings: Merge into do_change_settings.
We preserve the function as a small wrapper until we can resolve the
TODO noted in the comment.
2021-09-07 10:49:56 -07:00
Tim Abbott a5d46e5cab do_change_notification_settings: Add conditional around RealmAuditLog work. 2021-09-07 10:49:56 -07:00
Tim Abbott fecdc234bf models: Rename setting-changed RealmAuditLog entry.
We will likely in the future want to start creating these for all
settings changes, and this new name will make the code more readable
when we do so.
2021-09-07 10:49:56 -07:00