Compare commits

...

1111 Commits

Author SHA1 Message Date
Tim Abbott
5fa6260ae8 Add changelog for Zulip 1.3.9 release. 2015-11-16 08:46:48 -08:00
Tim Abbott
7395003e6a Fix buggy #! lines using "/usr/bin/env python2.7 -u".
The #! line processing interpreted the argument to pass to `env` as
"python2.7 -u", which obviously isn't a real program.

We fix this by setting the PYTHONUNBUFFERED environment variable
inside the program, which has the same effect.

Thanks to Dan Fedele for the bug report and suggested solution!
2015-11-16 08:46:48 -08:00
Tim Abbott
ac35d26868 Add changelog for Zulip 1.3.8 release. 2015-11-15 14:58:52 -08:00
Tim Abbott
788b688935 Document upgrade process complications around puppet. 2015-11-15 14:58:52 -08:00
Tim Abbott
bd817fba97 Expand documentation on how to use the development environment.
* Reorganize to cover how to use the VM regardless of install process
  used.
* Document exactly what you need to do in order to see your changes.
* Remove the now-inaccurate documentation about flaky casper tests.
* Point to the testing documentation.
2015-11-15 14:31:40 -08:00
Tim Abbott
abdb148f42 Clarify instructions for setting up the S3 integration.
These instructions still aren't great due to #291, but at least this
is clear about how to get this working.
2015-11-15 13:50:12 -08:00
Tim Abbott
d06cb5d55a Expand documentation on writing and debugging Casper tests. 2015-11-11 21:36:00 -08:00
Tim Abbott
0cbedd6b0c Add casper tests for administration page user/bot (re/de)activation.
This should prevent future regressions like the one fixed in #243.
2015-11-11 21:35:55 -08:00
Tim Abbott
827babdf29 terminate-psql-sessions: Remove dependency on bc.
Fixes #281.
2015-11-11 21:35:16 -08:00
Tim Abbott
9d75fd33d9 Add new test for management commands running with --help.
This test caught a few bugs where refactoring had made management
commands fail (and would have caught a few more recent ones).

Ideally we'd replace this with a more advanced test that actually
tests that the management command do something useful, but it's a
start.
2015-11-11 21:34:39 -08:00
Tim Abbott
16ae985807 profile_request: Fix get_old_messages_backend import. 2015-11-11 21:34:39 -08:00
Tim Abbott
3e794351ab Remove expunge_* management commands.
These management commands never worked and given that we removed the
retention_policy code that they call, it makes sense to remove them as
well.
2015-11-11 21:34:39 -08:00
Tim Abbott
6718c85b13 Add troubleshooting documentation for the remote user SSO setup. 2015-11-11 21:33:52 -08:00
Tim Abbott
b81ecc4064 Add whitespace lint rules checking for missing spaces before {. 2015-11-10 10:06:47 -08:00
Tim Abbott
5f25974737 Fix Javascript whitespace issues with {. 2015-11-10 10:01:34 -08:00
Walter Heck
f145b01d91 Update create_user management command.
notify_new_user was recently moved to zerver.lib.actions from
zerver.views and this wasn't properly updated. This would give an
error when doing a `manage.py create_user` from the command line.
2015-11-08 19:41:00 -08:00
Tim Abbott
9b4c440e0d apps: Fix linking to SSO versions of desktop app.
The SSO build of the desktop app is intended only for those users who
who have settings.SSO_ONLY set, i.e. the only way to login is via the
site's SSO REMOTE_USER authentication.  We were incorrectly linking to
it on all production installations :(.
2015-11-06 09:51:25 -08:00
Tim Abbott
123f21c46b README.prod: Fix old requirements documentation. 2015-11-06 09:47:26 -08:00
Tim Abbott
2d0fbd068f Document how to revert to a previous version in upgrade process. 2015-11-06 09:45:41 -08:00
Tim Abbott
29706275df Document how to find the old realm if you've changed ADMIN_DOMAIN. 2015-11-06 09:45:41 -08:00
Tim Abbott
c3c4062ec7 Fix missing quotes in ADMIN_DOMAIN change docs. 2015-11-06 09:45:41 -08:00
Tim Abbott
61cb2ce883 Document how to clone the Zulip repository on Windows.
Fixes #272.
2015-11-06 09:45:41 -08:00
Tim Abbott
7c1b438ab0 Expand the Vagrant installation documentation significantly.
Thanks to Omar Farooq (o3dwade) for an early version of this!
2015-11-06 09:45:41 -08:00
Tim Abbott
5ffa2186d0 Merge common portions of the Fedora/CentOS development instructions.
There's still some parts of the CentOS 7 instructions that we may be
able to just delete.
2015-11-06 09:45:41 -08:00
Tim Abbott
0b77eb0291 Fix headings in installation instructions. 2015-11-06 09:45:41 -08:00
Tim Abbott
55ddc35b90 Move development installations instructions to a separate file.
This will make the core README.md file cleaner.
2015-11-06 09:45:41 -08:00
Tim Abbott
8181a0423f Fix some small issues with the CentOS/Fedora instructions. 2015-11-06 09:45:41 -08:00
Марко М. Костић (Marko M. Kostić)
7f4b82af18 Added CentOS 7 specific instructions to the manual install guide. 2015-11-06 09:45:41 -08:00
Allie Jones
85809e6140 Add webpack build process. 2015-11-06 09:13:25 -08:00
Allie Jones
e20a1bc73c Remove the committed handlebars package and install it via npm. 2015-11-06 09:09:41 -08:00
Allie Jones
4de0325a9d Install node dependencies using npm.
The node packages 'jQuery' and 'jquery' are different--'jQuery' is the
legacy support package that is needed for Zulip so the require statements
in the tests were updated.

Travis uses node 4.0 by default and we are using 0.10, so the command to
install the correct version had to be added to the .travis.yml file.
2015-11-06 09:08:59 -08:00
Allie Jones
46e267f4dc Add node-legacy package.
Some dependencies aren't configured to find the node binary correctly on
Debian (since it is called nodejs instead of node). The node-legacy package
fixes this.
2015-11-06 09:08:50 -08:00
Tim Abbott
ae04744606 admin: Refactor to remove unnecessary selections of active_user_row. 2015-11-04 08:15:55 -08:00
Tim Abbott
958ada9f44 admin: Fix deactivating bot users.
The previous code was using the same codepath as for real users, which
was unfortunate in two ways:
* It hit the wrong endpoint on the server and thus failed
* It popped up the "remove a user prompt" which described a bunch of
  things not relevant to bots.
2015-11-04 08:03:28 -08:00
Tim Abbott
5161891fbd admin: Fix reactivating bot users.
Because the `owner` field had the class email, we were sending the
concatination of the user and owner email addresses as the email
address in the reactivate requests.

Fixes #243.
2015-11-04 08:03:17 -08:00
Tim Abbott
f6f8f1fe36 Use new-style classes consistently for Python 3 support.
Also add the fixer for this to our list of fixers we check.
2015-11-04 08:01:52 -08:00
Tim Abbott
f52ffa7923 travis: Add Python 3 compatibility test.
This tests whether a new patch introduces any regressions related to
any of the Python 3 compatibility fixers we've run in the past, so
that we can make continuous forward progress on our path towards
Python 3 compatibility.

This produces error output that looks like this:
"""
Testing for additions of Python 2 patterns we've removed as part of moving towards Python 3 compatibility.

Running Python 3 compatibility test lib2to3.fixes.fix_apply
Running Python 3 compatibility test lib2to3.fixes.fix_except
diff --git a/zerver/views/__init__.py b/zerver/views/__init__.py
index b5c0102..2defd46 100644
--- a/zerver/views/__init__.py
+++ b/zerver/views/__init__.py
@@ -296,7 +296,7 @@ def accounts_register(request):
                 do_activate_user(user_profile)
                 do_change_password(user_profile, password)
                 do_change_full_name(user_profile, full_name)
-            except UserProfile.DoesNotExist, e:
+            except UserProfile.DoesNotExist as e:
                 user_profile = do_create_user(email, password, realm, full_name, short_name,
                                               prereg_user=prereg_user,
                                               newsletter_data={"IP": request.META['REMOTE_ADDR']})

Python 3 compatibility error(s) detected!  See diff above for what you need to change.
"""
2015-11-04 08:00:25 -08:00
Shumbashi
123791bfdd Fix 'manage.py makemessages' errors.
Running 'manage.py makemessages' produced two errors previously.

Closes #265.
2015-11-04 07:39:48 -08:00
Ahmed Shibani
4f29cfee9e Mark strings for translation in templates/zerver
In order to enable internationalization support in Zulip, and to use
Django internationalization tools, all strings in Zulip frontend needs
to be marked for translation.
2015-11-03 23:06:31 -08:00
Ahmed Shibani
47d8d784a2 Add 'blocktrans' to tools/check-templates.
Running check-templates test fails when there are 'blocktrans' tags in
django templates. The fix is to add 'blocktrans' to
is_django_block_tag function in check-templates.
2015-11-03 08:06:48 -08:00
Tim Abbott
6eb670097c Expand testing done via Travis CI to cover production pipeline.
With this change, we are now testing the production static asset
pipeline and installation process in a new testing job (and also run
the frontend/backend tests separately).

This means that changes that break the Zulip static asset pipeline or
production installation process are more likely to fail tests.  The
testing is imperfect in that it does not have proper isolation -- we
build a complete Zulip development environment and then install a
Zulip production environment on top of it, so e.g. any apt
dependencies installed for Zulip development will still be available
for the Zulip production environment.  But, it's better than nothing!

A good v2 of this would be to have the production setup process just
install the minimum stuff needed to run `build-release-tarball` and
then uninstall it / clean it up so that we can do a more clear
production installation, but that's more work.
2015-11-01 18:11:39 -08:00
Tim Abbott
421560af21 postgres-init-db: Stop all services before recreating database. 2015-11-01 18:11:39 -08:00
Tim Abbott
3c31f9a2e3 Drop database users prior to DROP/CREATE database.
This fixes an annoying issue where one tries to rebuild the database,
and it fails due to there being existing connections.

The one thing that is potentially scary about this implementation is
that it means it's now a lot easier to accidentally drop your
production database by running the wrong script; might be worth adding
a "--force" flag controlling this behavior or something.

Thanks to Nemanja Stanarevic and Neeraj Wahi for prototypes of this
implementation!  They did most of the work and testing for this.
2015-11-01 18:11:39 -08:00
Tim Abbott
b7cd000af6 install: Check nginx configuration is valid.
It's better to fail here and have the user correct the issue than fail
later.
2015-11-01 18:06:59 -08:00
Tim Abbott
33295180a9 Apply Python 3 futurize transform libmodernize.fixes.fix_unicode_type. 2015-11-01 09:35:06 -08:00
Tim Abbott
607eedfc25 Apply Python 3 futurize transform libmodernize.fixes.fix_zip. 2015-11-01 09:35:06 -08:00
Tim Abbott
f7878a61e1 Apply Python 3 futurize transform libmodernize.fixes.fix_xrange_six. 2015-11-01 09:35:06 -08:00
Tim Abbott
5ffb4deb8d Apply Python 3 futurize transform libmodernize.fixes.fix_raise_six. 2015-11-01 09:35:05 -08:00
Tim Abbott
cd6f8e9191 Apply Python 3 futurize transform libmodernize.fixes.fix_map. 2015-11-01 09:35:05 -08:00
Tim Abbott
ffc900fe6e Apply Python 3 futurize transform libmodernize.fixes.fix_int_long_tuple. 2015-11-01 09:26:17 -08:00
Tim Abbott
3b185ad4de Apply Python 3 futurize transform libmodernize.fixes.fix_input_six. 2015-11-01 09:26:17 -08:00
Tim Abbott
2ea0663a4a Apply Python 3 futurize transform libmodernize.fixes.fix_imports_six. 2015-11-01 09:26:16 -08:00
Tim Abbott
b3ac668779 Apply Python 3 futurize transform libmodernize.fixes.fix_filter. 2015-11-01 09:26:16 -08:00
Tim Abbott
651b011514 Apply Python 3 futurize transform libmodernize.fixes.fix_basestring. 2015-11-01 09:26:16 -08:00
Tim Abbott
7e63842003 Apply Python 3 futurize transform libfuturize.fixes.fix_raise. 2015-11-01 09:26:16 -08:00
Tim Abbott
f3783fb4a1 Apply Python 3 futurize transform libfuturize.fixes.fix_print_with_import. 2015-11-01 09:26:16 -08:00
Tim Abbott
f97649b35c Apply Python 3 futurize transform libfuturize.fixes.fix_next_call. 2015-11-01 09:26:16 -08:00
Tim Abbott
9c66229456 Apply Python 3 futurize transform libfuturize.fixes.fix_absolute_import. 2015-11-01 09:26:16 -08:00
Tim Abbott
43abd83d1c Apply Python 3 futurize transform lib2to3.fixes.fix_ws_comma. 2015-11-01 09:26:14 -08:00
Tim Abbott
2b61c0203d Apply Python 3 futurize transform lib2to3.fixes.fix_repr. 2015-11-01 09:25:49 -08:00
Tim Abbott
daddf7c519 Apply Python 3 futurize transform lib2to3.fixes.fix_numliterals. 2015-11-01 09:25:49 -08:00
Tim Abbott
2398a370e2 Apply Python 3 futurize transform lib2to3.fixes.fix_ne. 2015-11-01 09:25:49 -08:00
Tim Abbott
06f6ee6566 Apply Python 3 futurize transform lib2to3.fixes.fix_idioms. 2015-11-01 09:25:47 -08:00
Tim Abbott
e9243d0f0b Apply Python 3 futurize transform lib2to3.fixes.fix_has_key. 2015-11-01 08:10:01 -08:00
Tim Abbott
5ce6a3c8f9 Apply Python 3 futurize transform lib2to3.fixes.fix_funcattrs. 2015-11-01 08:09:54 -08:00
Tim Abbott
8c34c40924 Apply Python 3 futurize transform lib2to3.fixes.fix_except. 2015-11-01 08:08:33 -08:00
Shane Kearns
6e3426fe10 python api: allow control over the server certificate verification
The --insecure option ("insecure=true" in .zuliprc) disables
verification entirely, similar to other tools like curl.

The --cert_bundle ("cert_bundle=<file>" in .zuliprc) allows
a file to be specified containing the CA certificates to verify
against.
When using self-signed certificates, the server's public key
can be used as the only cerificate in the file.

This change incidentally fixes an issue where the "site" parameter
in .zuliprc was ignored when specifying --user and --api-key on
the command line.

Fixes: #104
2015-10-31 21:20:34 -07:00
Kara McNair
97a2e70d2b Add passing tests for emails replying to missed personal messages
Covers both direct PMs and huddle message recipients.
2015-10-31 17:28:21 -07:00
Kara McNair
a8e5755c7b Add tests for processing emailed-in stream messages (success & fail)
Prior to adding reply-to-missed-message-email functionality, adding
automated tests for simpler case - incoming stream messages. Added
to new file test_email_mirror.py.
Also removed the "if not body" code from process_stream_message that
will never run because of an upstream ZulipEmailForwardError exception.
2015-10-31 17:26:23 -07:00
Tim Abbott
10657c1d53 Move node tests to node_tests/. 2015-10-28 10:11:47 -07:00
Tim Abbott
81f32f4aa1 casper: Rename frontend_tests/run to clarify it uses casper. 2015-10-28 10:11:47 -07:00
Tim Abbott
5aa89fd6af casper: Move common.js and test-credentials.js to casper-lib/. 2015-10-28 10:11:47 -07:00
Tim Abbott
01f0d362d9 Move test_credentials.js into casper_tests/. 2015-10-28 10:11:47 -07:00
Tim Abbott
2294063361 Move casper server.log into casper_tests/. 2015-10-28 10:11:47 -07:00
Tim Abbott
988a9acead Move casper tests to a clearer directory name. 2015-10-28 10:11:47 -07:00
Tim Abbott
f1074aa491 Move frontend tests out of zerver/tests/.
This fixes an unfortunate bug where the backend tests in
zerver/tests.py were not being run automatically, and also makes these
a bit easier to find.
2015-10-28 10:11:47 -07:00
Tim Abbott
a36ac151ef Fix newly invited users receiving private stream history.
Also add a test to avoid this regressing in the future.

Fixes #230.
2015-10-26 23:36:37 -07:00
Tim Abbott
c1686235cd Fix construction of names in LDAP integration.
Previously these users' names were being set to 1-element lists
containing the name, not the names themselves.  This bug caused
existing users to have their people module state (e.g. @-mentions,
etc.) to break whenever a new user joined.

Fixes #222.
2015-10-26 22:49:10 -07:00
Kara McNair
8e429759e2 Replace 'flaky' and 'freaking out' with less personified words.
The tests to recognize a misbehaving/unpredictable worker task use
the words 'flaky' and 'freaking out' in personifying the system
behavior. This terminology isn't inclusive of people with
mental health issues or mood disorders, so this change updates
the wording to have less personification and more objective system
description. (http://www.ncbi.nlm.nih.gov/pmc/articles/PMC1925070/)
2015-10-26 20:14:48 -07:00
Gautam Kotian
fb5192e85b Fix typo in README.md. 2015-10-26 20:04:55 -07:00
Elizabeth Sander
2ba01f4900 Defer permission for notifications until after tutorial.
In the process, remove old mozilla notifications hack since the
notifications_api shim should handle that case correctly.

Fixes #17.
2015-10-26 09:44:15 -07:00
Bernhard Morgenstern
dd2ccff22b Fix indentation for Trac ticket description changes.
Before this fix, the "to" was included in the markdown blocks.
2015-10-22 15:02:35 -07:00
Steven Oud
d5435fad1d Consistently use /usr/bin/env python2.7 in shebangs and commands. 2015-10-21 22:58:21 +00:00
Tim Abbott
136c55e43d Document new zulip-help@ mailing list for installation help. 2015-10-19 21:45:44 -07:00
Tim Abbott
b76e78c4dd Expand documentation on contributing to Zulip. 2015-10-19 21:01:18 -07:00
Tim Abbott
3bb0ce2383 Changelog: Simplify formatting and document 1.3.7 release. 2015-10-19 20:32:47 -07:00
Tim Abbott
54c964a332 Rewrite the email gateway integration instructions. 2015-10-19 10:10:20 -07:00
Tim Abbott
a6ddd28c9e Clarify the steps in the outgoing SMTP setup process. 2015-10-19 10:09:45 -07:00
Tim Abbott
494797ea0a Fix has_valid_realm logic following get_realm refactor. 2015-10-19 09:59:06 -07:00
Tim Abbott
3e1f4e611c Clarify on zulip.com signup form that we're not taking new teams. 2015-10-19 09:37:24 -07:00
Tim Abbott
758baca01a run-dev.py: Report a nice error if you run it as root.
Fixes #172.
2015-10-15 12:45:38 -04:00
Tim Abbott
3167b64d1c Extend changelog with other unreleased improvemenets since 1.3.6. 2015-10-15 12:31:28 -04:00
Nicholas Bergson-Shilcock
89a2765553 Turn off desktop notifications by default for new users.
New users will no longer get desktop and audible notifications for all streams
by default.

This also updates the `day1` follow-up email to let users know they can
customize how and when Zulip notifies them of new messages.

Lastly, this adds a `changelog.md` file, following the conventions from
keepachangelog.com, to track changes for new releases.
2015-10-15 12:25:32 -04:00
Tim Abbott
e75ba630fb initialize-database: Make management command errors fatal again.
We accidentally made this non-fatal when we added the nice error
output telling users to run postgres-init-db.
2015-10-15 12:21:46 -04:00
Tim Abbott
bf694fa832 Flush memcached whenever we drop the databases.
This fixes some issues that we've had where commands will fail is
confusing ways after the database is rebuilt because data from before
the database was dropped is still in the memcached cache.
2015-10-15 12:18:41 -04:00
Tim Abbott
32aea4c9dd Fix get_unique_open_realm always returning None in production.
Fixes #186.
2015-10-15 10:21:04 -04:00
Tim Abbott
5d22f5ee0a Improve LDAP_APPEND_DOMAIN default.
The documentation suggests the default is None; this change makes that
true.  Also make the actual code robust to this being set to "" instead.
2015-10-15 09:16:59 -04:00
Tim Abbott
71a06d58de Convert uses of Realm.objects.get() to get_realm().
get_realm is better in two key ways:
* It uses memcached to fetch the data from the cache and thus is faster.
* It does a case-insensitive query and thus is more safe.
2015-10-15 09:16:58 -04:00
Tim Abbott
51ed5028dc Remove unnecessary get_realm_name function. 2015-10-15 09:16:58 -04:00
Tim Abbott
419d31a007 Expand documentation for the LDAP auth integration.
Fixes #134, #173.
2015-10-15 09:16:58 -04:00
Tim Abbott
784ba7e066 Fix support for LDAP Authentication mechanism.
This addresses a few issues:
* The LDAP authentication integration now creates an account a new
  Zulip account if the user authenticated correctly but didn't have a
  Zulip account.
* The previous code didn't correctly disable the LDAP group
  permissions functionality.  We're not using groups support from the
  Django LDAP extension and not doing so can cause errors trying to
  fetch data from LDAP.

Huge thanks to @toaomatis for the initial implementation of this.

Fixes #72.
2015-10-15 09:16:58 -04:00
Tim Abbott
90e61d3b61 Call process_new_human_user consistently when creating new users.
Previously we only did this when new human users were created via the
login process, which meant the management command to create a user did
not add the user to default streams (for example) and any future code
that might want to register a new Zulip user (such as the LDAP
integration) would need to import views/__init__.py in order to
properly set this up.
2015-10-15 09:16:58 -04:00
Tim Abbott
355e1bbd94 Move process_new_human_user and helpers from views to actions.py. 2015-10-15 09:16:58 -04:00
Tim Abbott
792075ddeb sync_api_key: Don't throw a messy exception when user doesn't exist. 2015-10-15 09:16:58 -04:00
Tim Abbott
3e735d36d1 Rename tools/postgres-init-db to tools/postgres-init-dev-db.
The previous name was confusing because we also have
scripts/setup/postgres-init-db.
2015-10-15 09:14:21 -04:00
Allie Jones
99a2ba38b1 Expand new feature tutorial. 2015-10-15 09:12:22 -04:00
Tim Abbott
e8e38e911b Fix casperjs tests in Travis CI.
For reasons I don't understand, it appears that in Travis CI we're now
seeing errors using Casper that seem to correspond to a compatibility
issue introduced in PhantomJS 2, even though we're still using 1.9.8.

The solution for that compatability issue of patching casper's
bootstrap.js to get arguments from system.args at a slightly different
time than before seems to work in our setting as well, and that's what
this implements.

Probably the right long-term solution involves upgrading both
phantomjs and Casper to the latest versions.
2015-10-14 21:49:09 -04:00
Tim Abbott
eac6ea75dd emoji_dump: Exit with nonzero status when there are failures.
Previously, emoji_dump would happily exit successfully even if it
wasn't able to generate all the emoji.
2015-10-14 21:48:13 -04:00
Tim Abbott
5ee50cdced Install libfreetype6-dev in the development environment.
This fixes a problem where the emoji_dump tool was not generating the
black-and-white emoji.  The issue is that Pillow compiled without
libfreetype cannot extract those emoji (and gives an error of the form
"The _imagingft C module is not installed"), and if libfreetype-dev
isn't installed, pip will happily build and install Pillow without
libfreetype.
2015-10-14 18:58:36 -04:00
Tim Abbott
1dc09f3abd Document need to restart run-dev.py when developing queue workers. 2015-10-14 16:11:04 -04:00
Tim Abbott
4309f92062 Pass worker errors through to the run-dev.py console. 2015-10-14 16:08:32 -04:00
Kara McNair
d72f75a7e1 email-mirror: Support missed message email token string format.
The do_send_missedmessage_events_reply_in_zulip function in the email
mirror didn't support EMAIL_GATEWAY_PATTERN that wasn't of the form
%s@example.com (which resulted in replies to missed message emails failing
to be parsed).
2015-10-14 16:02:15 -04:00
Tim Abbott
0d85ab2062 README: Clean up Mac installation instructions for Virtualbox/Vagrant.
* Removes the hardcoding of an old version of Virtualbox (and doesn't
  specify the version to avoid getting stale again over time).
* Flips around the langauge to assume you don't have Vagrant already.
* Makes clear that the first-time installation is a lot slower than
  future runs will be.

Fixes #5.
2015-10-14 12:05:23 -04:00
Tim Abbott
c6761e8604 provision.py: Check whether git repository is present.
Fixes #148.
2015-10-14 10:18:59 -04:00
Tim Abbott
6569018de7 Disable apt caching in Travis CI configuration.
Apparently it isn't supposed to work reliably with the container-based
infrastructure that we're using and empirically it's causing build
failures.

Thanks to @mijime for tracking this down.
2015-10-14 10:04:27 -04:00
Andrew Drozdov
f6311478e6 Add docs on how to update default streams. 2015-10-13 11:09:37 -04:00
David Farrell
59dfec8f8b Add Fedora-specific instructions to the manual install guide. 2015-10-07 15:23:59 -04:00
Raphael
0608e32eeb Cause install to return 1 on failure.
This fixes issue #123. Namely, the script in scripts/setup/install was
returning 0. Adding `set -e` and `set -o pipeline` causes the install
script to exit and return 1 if any part fails, including piping output
(`set -o pipeline` does this).
2015-10-07 08:46:16 -04:00
Darius Bacon
741e9d00d8 Install zulip_english.stop in 'By hand' install instructions.
This step was previously only present in provision.py.
2015-10-06 23:00:18 -04:00
Darren Worrall
77fad7a16e Add an api endpoint to fetch GOOGLE_CLIENT_ID
Further to #102, this provides an endpoint suitable for mobile apps to
consume the GOOGLE_CLIENT_ID if configured.
2015-10-06 23:28:08 +00:00
Raphael
ea65715ef8 manage.py: Give a nice error message if run as root on posix systems.
If the os is posix, this will check to see if the user is root and
alert them to run as zulip user if so.

Fixes #114.
2015-10-05 21:41:35 -04:00
David Farrell
e4cea98ccd Correct the filepath for rebuild test database script. 2015-10-05 21:28:54 -04:00
Luna Lunapiena
0ec99a0838 README: Add explicit instruction to clone Zulip repository. 2015-10-05 21:27:08 -04:00
David Farrell
411531ecaf Update script paths in by-hand instructions to execute as written. 2015-10-05 20:36:07 -04:00
Nicholas Bergson-Shilcock
759ab33981 Add note about installing Vagrant on Mac to README. 2015-10-05 20:34:27 -04:00
Justin Valentini
d490779307 Add a relative link to production README. 2015-10-04 16:28:36 +00:00
Luke Faraone
e014b68b84 Include license text in THIRDPARTY 2015-10-03 15:44:13 +00:00
Darren Worrall
14389145cd Make twitter settings validation test more explicit 2015-10-02 12:01:25 +01:00
Tim Abbott
a65656dd9d Fix backwards-compatibility for old python-requests .json property.
In b59b5cac35, we upgraded our Google
Oauth code to support new python-requests, but because Ubuntu precise
still has old python-requests, this broke the codepath for older
systems.
2015-10-01 18:54:17 -07:00
Tim Abbott
8e0479e7a0 Clarify Zulip upgrade process instructions. 2015-10-01 12:56:18 -07:00
Tim Abbott
ea7e5527be README.prod.md: Expand documentation on filling in settings.py. 2015-10-01 12:42:36 -07:00
Tim Abbott
feca065dd8 README.prod.md: Improve instructions for downloading server tarball. 2015-10-01 12:42:35 -07:00
Liam Marshall
a822118dcb Fix a bunch of formatting issues in README.prod.md.
Removes:
* Several unused <hr>s

Fixes:
* Odd linebreaks
* Inconsistent headers
* URLs which should be links
* Headers which should be headers

Code-formats:
* envvars
* FQDNs
* commands and command options
* config options
* code
2015-10-01 12:42:16 -07:00
Allie Jones
cd1fa6a42e Fix notifications in Firefox by calling the constructor with 'new'. 2015-10-01 09:31:05 -07:00
Tim Abbott
ad75959b92 README.prod: Add documentation for how to create an SSL certificate. 2015-10-01 09:31:05 -07:00
mijime
2db2fcea18 Fix a puppet config to use SSO.
puppet::enterprise was renamed to puppet::voyager.
2015-10-01 09:31:05 -07:00
Darren Worrall
8b002040e0 Correct twitter library in requirements.
This also requires updating the required version of oauthlib; previously an
appropriate version was being installed only because it was a dependency of
the wrong twitter library.

This only affects development environments and/or hand-built
installations relying on the contents of requirements.txt.

To fix existing environments, the incorrect api needs to be explicitly
removed with `pip uninstall twitter`.

Fixes #86.
2015-09-30 13:49:33 -07:00
Ged Lawrenson
21b7048e54 install: Verify that the script has sufficient privileges. 2015-09-30 10:55:49 -07:00
Darren Worrall
bec3c0943a Fix validation that twitter creds are present.
They are looked up as secrets which initialize to `None`, but the code
was checking for empty strings.

This, along with #80, fixes #81.
2015-09-30 09:27:37 -07:00
Jason Michalski
7352f31c4b Add documentation for the pagerduty integrations
Add pagerduty to the list of supported integrations and walks users
through the setup process.

Fixes #36
2015-09-30 09:24:00 -07:00
Jason Michalski
dafe69761e Use stock emoji in the pagerduty integration
The pagerduty integration was using realm emoji. Use stock replacements
in the open source release.
2015-09-30 09:23:59 -07:00
Guillaume Simon
956fd7c420 puppet: Ensure rabbitmq-server and epmd services are running.
[tabbott@mit.edu: Added a few comments]
2015-09-30 09:21:45 -07:00
Tim Abbott
f819c1e901 Update the Zulip development documentation.
Fixes a few major issues:
* Documents RAM requirements for running Zulip development
* Fixes missing steps in the "by hand" installation process
* Improves the emphasis in the section no how to run tests on the common case.
* Documents that you can use LXC on newer Ubuntu as well.
2015-09-30 09:04:16 -07:00
Tim Abbott
3b00029c52 Show the username/password form if ZulipLDAPAuthBackend is enabled. 2015-09-30 09:04:16 -07:00
Tim Abbott
1482a386c2 Fix documentation for how to enable ZulipLDAPAuthBackend. 2015-09-30 09:04:16 -07:00
Tim Abbott
92aebe595b Dramatically extend post-install documentation for production Zulip. 2015-09-30 09:04:14 -07:00
Tim Abbott
5ad84fd997 Improve documentation for the Zulip email integration.
* Document fix for the 'less insecure' email problem.
* Mention that general Django email documentation applies.
2015-09-29 18:58:27 -07:00
Tim Abbott
40ec59b93e install: Add nice error message for RabbitMQ not having started. 2015-09-29 18:41:31 -07:00
Tim Abbott
5bf66e04fc initialize-database: Print nice instructions for how to redo if fails.
Most of our installation process is idempotent, but this step in
particular is not, so it's important to provide a clear error message
about how to proceed.
2015-09-29 18:27:27 -07:00
Tim Abbott
3efdb7ebf3 Document how to setup the Zulip S3 integration. 2015-09-29 18:11:58 -07:00
Tim Abbott
80fa5006f8 Document the purpose of local_settings.py properly. 2015-09-29 18:05:04 -07:00
Tim Abbott
bda9d78092 Use settings.ZULIP_ADMINISTRATOR as contact list for deactivated users. 2015-09-29 17:59:47 -07:00
Waseem Daher
6bb9b129f7 Update Zulip support email to zulip-devel@googlegroups.com.
Ideally some of these templates should really point to the
local installation's support email address, but this is a
good start.

Exceptions:
* Where to report security incidents
* MIT Zephyr-related pages
* zulip.com terms and conditions
2015-09-29 17:59:47 -07:00
Thomas Butter
d93d4c7216 Fix settings documentation of twitter keys.
Twitter keys are stored in zulip-secrets.conf.
2015-09-29 17:45:05 -07:00
Tim Abbott
852ac66f8e Extend the Google oauth documentation in local_server_template.py. 2015-09-28 10:05:58 -07:00
Amanpreet Singh
e20bc9f9b3 Fix "by hand" installation instructions.
- Add missing `python-dev` in apt-get install command
2015-09-28 09:24:55 -07:00
Tim Abbott
1f2f497cab Unrevert run Zulip tests automatically using Travis CI.
This contains a fix written by nemeth from PR #63 for doing argument
parsing properly.
2015-09-28 09:18:51 -07:00
Luke Faraone
578f769f60 Revert "Run Zulip tests automatically using Travis CI."
Improper list access from `sys.argv` would result in an exception if no
arguments are passed.

This reverts commit d2f5937d89.
2015-09-28 14:33:13 +00:00
Ian Whitlock
54fd321941 Add Vagrant-caused permissions problem to Possible Issues. 2015-09-27 17:48:07 -07:00
Tim Abbott
b6c1f1d162 Fix incorrect name for email_password secret in settings template.
Fixes #49.
2015-09-27 17:06:03 -07:00
Tim Abbott
d2f5937d89 Run Zulip tests automatically using Travis CI.
This is a bit hackish in that ideally we'd use proper options parsing
in provision.py, but it works and I even ran the tests 100x for tests
for flakes and didn't get any, so it's definitely an improvement!

With this we'll be both testing the runtime and effectively the Dev VM
setup process, which is awesome; the additional thing I'd want to add
tests for is the production setup process...
2015-09-27 16:29:20 -07:00
Caleb Anderson
ed742fa847 small typo fix 2015-09-27 01:10:01 -06:00
Tim Abbott
a625ca49ec puppet: Move /var/lib/nagios_state creation to zulip::base.pp.
Previously, in Zulip voyager, the cron jobs would spew error emails
every time they ran, due to this directory not existing.

This also tightens the permissions for the folder and avoids needing
to create a nagios user for Zulip voyager; it should be writeable by
both root and the zulip user and world-readable (and thus readable by
the Nagios user on zulip.com systems).
2015-09-26 21:44:23 -07:00
Tim Abbott
96bd1c38dc install: Make sure python is installed before using it.
This is relevant for completely bare Ubuntu systems which might only
have python3 installed.

Fixes #40.
2015-09-26 21:34:36 -07:00
Tim Abbott
9748780192 Remove unnecessary puppet.conf configuration.
Fixes #23.
2015-09-26 21:34:19 -07:00
Tim Abbott
bc3f096918 Update redis config to be supported on Trusty.
Previously our redis config was built for precise.

Synced from redis-server 2:2.8.4-2 plus our one change, which is
disabling saving to disk, so just put that at the bottom for maximum
obviousness.

I wish there was a better way to represent the fact that this is all
we're doing, since this will make life more difficult for running on
precise as well.

Fixes #28.
2015-09-26 21:33:55 -07:00
Tim Abbott
af4aac6836 settings: Document SMTP firewall issues in email configuration. 2015-09-26 21:32:47 -07:00
Tim Abbott
e5f7000a23 Add description of Zulip at top of README.md.
Based on PR #22 by GedLawrenson.
2015-09-26 18:07:06 -07:00
Tim Abbott
00bf7b25b5 install: Remote the python-django-guardian hack.
This is no longer required since it's in the PPA now.
2015-09-26 18:01:18 -07:00
Tim Abbott
2c6bfe136a Remove confusing EMAIL_HOST_PASSWORD setting in SMTP configuration.
This was one of the various configuration options made confusing by
the secrets-to-configuration migration.

Fixes #27.
2015-09-26 17:48:21 -07:00
Jon Johnson
db51a1c547 Fix typo in jabber mirror error
assistence -> assistance
2015-09-26 22:03:00 +00:00
Tim Abbott
3f76745235 Reorder README.md to highlight contributing section earlier. 2015-09-26 14:02:28 -07:00
Yuvi Panda
b59b5cac35 Fix TypeError in Google OAuth authenticator.
requests 1.0 changed response.json attribute to response.json()
instancemethod. The code wasn't updated to match that change,
causing a TypeError when attempting to use the Google OAuth
Authenticator backend.

This is fixed simply by using response.json() instead of response.json.
2015-09-26 13:51:27 -07:00
Tim Abbott
5dd330e769 Document how to setup Google auth for Zulip voyager. 2015-09-26 13:50:46 -07:00
Tim Abbott
140e598a89 Update configuration examples to use current Google auth backend. 2015-09-26 13:50:28 -07:00
Alice Pote
8159c03205 Add backticks around 'apt-get install'. 2015-09-26 12:13:21 -07:00
Anders Kaseorg
0d12dfd06f Improve shell quoting hygiene
Most of these problems were found by ShellCheck
(http://www.shellcheck.net).

Signed-off-by: Anders Kaseorg <andersk@mit.edu>
2015-09-25 23:25:08 -04:00
Josh Nichols
6888826d5b Link to settings page with absolute path, rather than explicitly zulip.com 2015-09-25 22:59:35 -04:00
Adam Smith
f0add4638c Update the puppet nginx file to match apache
this updates the nginx configuration file to match the installation documentation requirements and apache configuration file.
2015-09-25 19:34:58 -05:00
Leo Franchi
974a9bd0f3 Use -O option to wget when fetching zxcvbn
Otherwise the downloaded zxcvbn.js also includes garbage we don't want
2015-09-25 15:24:44 -07:00
Andreas Litt
aeb6a5df7c Use current working dir instead of /tmp 2015-09-25 22:11:59 +02:00
Andreas Litt
94c35d8fb0 Fix 'python-django-guardian' download
While the docu on https://www.zulip.org/server.html says:
```
cd /root/zulip
./scripts/setup/install
```
This script downloads the `python-django-guardian_1.3-1~zulip4_all.deb` file to current working dir (`/root/zulip` if you follow the docu), but tries to install it from /root/.
This fails obviously. So i changed the download location to /tmp/.
2015-09-25 22:02:13 +02:00
Thomas Boyt
1d40b2291c Fix Markdown formatting of code blocks & snippets 2015-09-25 12:07:55 -07:00
Allen Rabinovich
d6a41b4fe3 Add announcement of open sourcing to certain zulip.com pages. 2015-09-25 12:07:55 -07:00
Tim Abbott
5bf6f05f60 Add readthedocs requirements.txt. 2015-09-25 10:53:47 -07:00
Tim Abbott
b69c6228af Hackishly install a correct version of python-django-guardian in prod install.
(imported from commit 1027e05a1a9805a17fcb4b8dea2c2cf8cda280af)
2015-09-25 09:45:26 -07:00
Tim Abbott
f4be74dafc Postgres configuration updates for Postgres 9.3.
(imported from commit d643e742f3e582ecf1cc4db9635039b938e18a06)
2015-09-25 09:45:26 -07:00
Tim Abbott
abb1a13e31 Switch to new Trusty PPA for Voyager install process.
(imported from commit 91fdc16f121938d36c389f5b285f0da942558759)
2015-09-25 09:45:26 -07:00
Tim Abbott
3c3238d8e1 Fix puppet module name for voyager module.
(imported from commit c9db2eac98d77f94b432d96363c75cee01f2870d)
2015-09-25 09:45:26 -07:00
acrefoot
5accdf6d69 Add vagrant-lxc step to README.md
(imported from commit 1c0796dd70f535d11f492cb144b71ce3f34d3d4a)
2015-09-25 08:47:46 -07:00
Tim Abbott
1156a82297 Make ErrorReporter run successfully on Zulip voyager.
(imported from commit 8ab2fb57fb3e580775cb8959e3b8b5a1277ea9d3)
2015-09-25 04:09:16 -07:00
Zev Benjamin
81fe34d011 Stop deleting server logs and increase the size before rotation
(imported from commit c9bba20c5d7525b859833aa5eaa6ce210434970c)
2015-09-25 03:58:31 -07:00
Tim Abbott
3caa743951 rss: Support feeds that don't provide any sort of timestamp.
(imported from commit 9acc9dad7543a0e0a6bc2e71360b7017c3c7c63d)
2015-09-25 03:57:51 -07:00
Tim Abbott
45a8b050ac Change get_events restart log notices to log level (not error).
(imported from commit 52c3828d1c880545303f00bdf68585bdac844599)
2015-09-25 03:57:39 -07:00
Tim Abbott
b21a105a99 Reorganize and delete obsolete content from testing.rst.
(imported from commit 1d62b50c0b01d5386c8a6ffbde745abb6d79ad6e)
2015-09-25 03:40:31 -07:00
Tim Abbott
8967029729 Clean up GitHub API hook v1 comment.
(imported from commit 3777f2c9305bb8000e5ea4142bd2974805fa3c90)
2015-09-25 03:18:00 -07:00
Tim Abbott
9c0c5c57a7 Download zxcvbn.js rather than vendoring it.
(imported from commit 8d55b6b903dc2292852636dfb444219b643b5f64)
2015-09-25 02:24:07 -07:00
Tim Abbott
f31816072d Remove last customer-specific hack from github hook.
(imported from commit 897d9fd91e4f6c558d687f5ae6c360fad80574d9)
2015-09-25 00:47:15 -07:00
Anders Kaseorg
0ace7fe502 zanitizer: Remove -- argument that confuses some Git verisons
(imported from commit 42555ac7ca17c1568507ba665a8133a4db3375e6)
2015-09-25 00:46:00 -07:00
Tim Abbott
3770142635 Revert "Host "preview failed" image locally."
This reverts commit 39f2908a32c0276b1d87ecedc876c71dd35a9b2f.

We're not including the preview_fail.png image in the release.

(imported from commit 2de1451de2f9b1727fc3a7e64c380b71c0f2caa8)
2015-09-25 00:44:20 -07:00
Tim Abbott
441fa8ed9d Add build_emoji command to by-hand setup instructions.
(imported from commit 343ee4bc6397ba52c9bf1d2563c54a0470e3478b)
2015-09-25 00:44:20 -07:00
Luke Faraone
11a51cf943 License disclosures and project licensing.
(imported from commit 65776787f62e954ed22a521968effa4559fd6d33)
2015-09-25 00:44:19 -07:00
Tim Abbott
cc33b68d73 Remove pre-built emoji images from version control.
Instead, build them automatically when provision the development
environment and in update-prod-static.

(imported from commit aac8dfeaafbe872c113e5f2b6bd8f655a1af36f2)
2015-09-25 00:22:15 -07:00
Tim Abbott
fcf4731ed9 python-django-south is no longer required with Django 1.8.
(imported from commit 4b07d0e7a8d926c2a412ec2d468b7b1437790e8a)
2015-09-25 00:22:15 -07:00
Tim Abbott
8269b4dc76 Upgrade Zulip voyager to postgres 9.3 in preparation for trusty.
(imported from commit 1dd8bd8fe1361979b3a52f595d2ff0c92bb03e05)
2015-09-25 00:22:15 -07:00
Tim Abbott
2348a83678 postgres-init-db: Fix running with cwd=/root.
(imported from commit d2ac25fa8c54b89eed80e941b3eacf1a4c2f5546)
2015-09-25 00:22:15 -07:00
Tim Abbott
ae4cb6df35 Make python-postmonkey not a required package.
This is in some ways a regression, but because we don't have
python-postmonkey packaged right now, this is required to make the
Zulip production installation process work on Trusty.

(imported from commit 539d253eb7fedc20bf02cc1f0674e9345beebf48)
2015-09-25 00:22:14 -07:00
Tim Abbott
a0006d5faf Remove duplicate REQUIRED_SETTINGS check.
This makes fetching settings from here for the rabbitmq config not
work; and the main place we check for this is in initialize-database
anyway.

(imported from commit fcc6eff3882f880fdc8b127daffc9a3173f3ff20)
2015-09-25 00:22:14 -07:00
Tim Abbott
6540807761 install: Copy rather than moving local_settings_template.py.
(imported from commit 23e5af225738af32567c543df75375cd5ce378dc)
2015-09-24 22:41:00 -07:00
Tim Abbott
2fb9560476 puppet: enterprise=>voyager for single-server configuration.
(imported from commit 7cc47ac7c470239cd00f69cfd3137b39a0d06e3a)
2015-09-24 22:40:59 -07:00
Tim Abbott
d7618ff8dc Don't include zulip-dropbox.png in open source project.
(imported from commit 3b0068521818534ce34f039a3e16c418c448ed9c)
2015-09-24 22:40:59 -07:00
Anders Kaseorg
be844b628d Revert "Install git pre-commit hooks in the vm as part of provisioning."
This reverts commit b3aa3b44de198abea49f5b43e2403f466f30f66c.

The hook was actually being installed through the bind-mount into the
checkout outside the VM.

(imported from commit 7fcb4806743508e530b46593a1022ea00b74259e)
2015-09-24 22:59:27 -04:00
Tim Abbott
ce5e9093e6 Add missing --interface option for run-dev.py.
(imported from commit 94628eaa4d62597eda44f6f53be8bde4dfc33cfc)
2015-09-24 19:34:28 -07:00
Tim Abbott
3e5e40a3ed Remove redis tunnel from staging configuration.
(imported from commit 855cec4607fb6dc3913db8d0ddab2184849b135e)
2015-09-24 19:34:28 -07:00
Tim Abbott
da5fe944e1 Set limits for export tool.
(imported from commit 0c582223f5b3ac4caf7685217719d4c32c5d2fae)
2015-09-24 19:34:28 -07:00
Tim Abbott
ca4db5ac4b Extent contributing section in README.md.
(imported from commit 8d0a56f9450419a10b12d40437213b9b7184f8bd)
2015-09-24 19:34:28 -07:00
Tim Abbott
95056c6681 Rename zulip-enteprise.{key,combined-chain.crt} to drop -enterprise.
(imported from commit 6f51577866c36a768b1e63df59e5f8a6f4c64cf9)
2015-09-24 19:08:52 -07:00
Anders Kaseorg
c0bf02b4c2 zanitizer: Support renaming files
(imported from commit 6a094177d652a267b53aa5042110b39fcbf21b42)
2015-09-24 18:10:02 -07:00
Anders Kaseorg
49cf7abaed Tool for removing secrets from Git history
(imported from commit 1345658dc83eb9a98178d8c8ca8f37d19e281549)
2015-09-24 18:10:02 -07:00
Tim Abbott
827e7ad19c docs: Cleanup new feature tutorial and note unfinished.
(imported from commit 668eabb53f746afe7455b0f5fd1e8f5741894c5e)
2015-09-22 22:38:55 -07:00
Tim Abbott
a3c122eb41 Remove largely obsolete documentation pages.
(imported from commit eb02c24dd25a12a5676b5e52c914993650f73aa6)
2015-09-22 22:37:45 -07:00
Tim Abbott
1be909a450 docs: Content editing for directory-structure.rst.
(imported from commit aa331a561f1e905c9453bd0590eb1147c19f2be4)
2015-09-22 22:17:56 -07:00
Tim Abbott
3c1c14a7cc docs: Fixed a bunch of factual issues in coding style guidelines.
(imported from commit 6320d45ad064fcc5b3e8f01247b18af1a85bf91f)
2015-09-22 22:13:28 -07:00
Tim Abbott
ac8167062b Markdownify README files and add contribution documentation in README.md.
(imported from commit aac3bc2d051dd328cb55be05fd44d77b626e1201)
2015-09-22 21:43:54 -07:00
Tim Abbott
485c907721 Return to recommending running run-dev.py manually.
(imported from commit f050f2a8f2242dc23267c341d53517847d7fc560)
2015-09-22 21:31:54 -07:00
Tim Abbott
53f74ef06a Reorganize README.prod to not emphasize SSO so much.
(imported from commit 356b689685ab1ff645c76f0a1f92f44c1d29f64e)
2015-09-22 21:22:16 -07:00
Tim Abbott
b6e2fd6e83 Rename build-voyager-tarball to build-release-tarball and document.
(imported from commit 06f102f4f4c5caf187f4930fadff06147f095401)
2015-09-22 21:22:11 -07:00
Tim Abbott
cf17168c9f Move prod README to root of repository.
(imported from commit db108ffa7f88f22610ecee085abdcd6c5a2bb681)
2015-09-22 21:22:11 -07:00
Tim Abbott
78a9b301d0 Make clear the meaning of the colors in Zulip Dev Login.
(imported from commit 1b7d1de2bbf9d9e0c30873a1f65df16f6ecde225)
2015-09-22 21:21:43 -07:00
Tim Abbott
99fd2924cf Add nice logging output for build-voyager-tarball.
(imported from commit 6d11550aac6e8d6c123398b137987f93b31fbece)
2015-09-20 15:21:17 -07:00
Tim Abbott
efa7a90ecc Install closure-compiler directly for use on the Dev VM.
(imported from commit 0dae11b46364026acf29e1fc953401162db68746)
2015-09-20 15:21:16 -07:00
Tim Abbott
38ca08b18f Add support for emphasize_branch_in_topic feature.
(imported from commit 35a447ee7b94b83bd1c9425c678167003a398ae3)
2015-09-20 15:21:12 -07:00
Tim Abbott
4a858d7d1b Clean up api_github_v1 logic around issues stream.
(imported from commit d40997de594834d2ec6f8f190ad04b20bfd45a4c)
2015-09-20 13:21:15 -07:00
Tim Abbott
c5b44dc921 Simplify logic for the GitHub API hook.
(imported from commit 95dd8e16930f512b13a0413cf18b25694bd6ba66)
2015-09-20 13:21:15 -07:00
Tim Abbott
32878e8343 Enable GitHub issues messages for all realms.
(imported from commit 108fddc0b1f8b2d1ae74c09d1e96cff40d8c2ab1)
2015-09-20 11:49:03 -07:00
Tim Abbott
ade363f3af Remove some GitHub hook hacks for old customers.
These features are in most cases possible to setup directly via our
GitHub services integration UI, and the customers aren't using Zulip
anymore, so this is worth doing to clean up the code.

(imported from commit 1e6f4ec523d85b6233a8e5b4eaa13eacfbe6e5f4)
2015-09-20 11:46:26 -07:00
Tim Abbott
b68d116e3a Remove old is_super_user helper functions.
(imported from commit 85655ea9369f5dc309f6f687bac578924571c9ee)
2015-09-20 11:13:20 -07:00
Tim Abbott
858d0a984b Move API super users configuration into the database.
(imported from commit 3cc702f93e7252b42930dba4bde93a915b6dbf44)
2015-09-20 11:13:20 -07:00
Tim Abbott
bfcae58cac Deprecate old Zulip internal server installation script.
(imported from commit 5d6aeaff6126aae1aa5bf610fc94cfdb0eda595e)
2015-09-20 00:39:53 -07:00
Tim Abbott
80a8725a03 Remove certain hardcoded email addresses in Zephyr mirroring.
(imported from commit 9fd492b5463f04741558687f27522d48a5dc795b)
2015-09-20 00:36:12 -07:00
Tim Abbott
36a9dc2cf7 Cleanup various minor Zanitization issues.
(imported from commit 5784eb5ac70706f72b05463354434a83a6e1beaa)
2015-09-20 00:25:38 -07:00
Tim Abbott
5e0b6b809a Clean up tools/ by deleting files and moving others to deprecated/
(imported from commit 57a8e6c3bd746e83e2d22e941a8321ead1396aef)
2015-09-20 00:18:48 -07:00
Tim Abbott
602077f75b We're no longer using the review script.
(imported from commit 9840ebdfdacee6e3cb32934b81502c70c133e2b0)
2015-09-20 00:10:54 -07:00
Tim Abbott
94d7ed006f inject-messages: Document and remove hardcoded API keys.
(imported from commit 9152ef85937b707157800da9efed068b151a438c)
2015-09-19 23:53:42 -07:00
Tim Abbott
e29c473077 Simplify analytics code to not filter certain low-interest users/realms.
(imported from commit 2dcf2e50b65c8b96d893cbe7dcdbbe652e6a90ff)
2015-09-19 23:42:28 -07:00
Tim Abbott
23a81af8ad Clarify the left_side_userlist comment.
(imported from commit d2aa403d3165096776b68e59cef9814bc5dec00a)
2015-09-19 23:39:54 -07:00
Tim Abbott
7fc7e5ee8c Remove now-unused og_zuliper_emails variable.
(imported from commit f89e1931ca05f163c51315d567425e71458e131f)
2015-09-19 23:37:48 -07:00
Tim Abbott
232de3015a Add lint checks for tab-based whitespace.
We exclude the one file we have with issues that comes from a
third-party vendor.

(imported from commit 47e097b39440aea8e4d7468892176ffce4818b5f)
2015-09-19 23:23:02 -07:00
Tim Abbott
eff0d31dcd Fix existing tab-based whitespace in the codebase.
(imported from commit 3bd8f51d1bb303455597d238af47b1b5541aed04)
2015-09-19 23:23:02 -07:00
Tim Abbott
176e3f4a54 Fix buggy yellow alert bar at top of admin page.
One of the alert rows Was missing a "-status" at the end.

While we're fixing this, make it more robust by adding .expectOne().

(imported from commit 8cb0a560701e2ee48f78471ef8fe5cfa060782af)
2015-09-19 23:23:01 -07:00
Tim Abbott
f340778798 Ensure gear_menu.js is initialized before hashchange.js.
This fixes a bug where loading directly to /#settings didn't work.

(imported from commit 4472373749a01db669e68866c7ce1a7a7c280ed6)
2015-09-19 23:23:01 -07:00
David Roe
3ac95ddc1a Add UserProfile flag to control whether we have a left side userlist.
Previously this was hardcoded for a single customer.

(imported from commit a6b7095050aa10cef976541505d9b09a35453f48)
2015-09-19 23:22:59 -07:00
Tim Abbott
a59e41b5ee Simplify twenty-four-hour time logic to be more generic.
(imported from commit bda4972b32b17a36518eddef701748f3a548e376)
2015-09-19 23:22:26 -07:00
David Roe
9590d988c5 Clean up code duplication in settings.js error reporting.
We can save a bunch of code by using the handle ui.js error reporting
helpers.

(imported from commit 7e993cae6e314c84d4ba8eaefd2ff7711c4bc19d)
2015-09-19 23:16:05 -07:00
Tim Abbott
21ac93ae9c Remove the send_to_prod hack.
(imported from commit ba2a4d5e7d83769add979cc05996dbd8b014e8a2)
2015-09-19 21:54:51 -07:00
Tim Abbott
fcec80461b Remove the SSO-only realm integration.
It's messy code, only one customer ever used it, and it's not in use
today.

(imported from commit af3f512ac6af74af66c588c7d40d699e98514d0a)
2015-09-19 21:54:51 -07:00
Tim Abbott
25a9ccccf1 Clean up comments in feature_flags.js.
(imported from commit aad58c3f8b3d21ee9d5a3a45dbf2440b3d51c6e8)
2015-09-19 21:54:51 -07:00
Tim Abbott
b7bb55932a Remove unused customer29.zulip.com nginx configuration.
(imported from commit cbba9437d872bd480a276aeaa8103f2da5210f88)
2015-09-19 21:54:51 -07:00
Tim Abbott
3b84a9a010 Modernize management command for deactivating a realm.
(imported from commit 9ef681193ff04e447c0afbba66187357624d98f3)
2015-09-19 19:10:27 -07:00
Tim Abbott
a5c1fc6d76 Remove unnecessary import_realm_filters.py management command.
It's superceded by realm_filters.py.

(imported from commit b53c8bc4daf965387f5ba88711dd7ece2db1dfd9)
2015-09-19 19:05:16 -07:00
Tim Abbott
b3dfacae19 Change API example usernames to use example.com domain.
(imported from commit 41b7be58735df0ea3d3a3daf23bc0f78606abc0d)
2015-09-19 18:12:02 -07:00
Tim Abbott
c0ec9e985a Remove old humbug/ hack.
We shouldn't have any sessions still in existence from 2 years ago.

(imported from commit 7a96271ed8015d8a9908720cd84525e823bf3b21)
2015-09-19 18:07:18 -07:00
Tim Abbott
eca3c3bfaa Add api/examples/print-events.
(imported from commit 8c0e3f7809f06e4aff3bd8c0640479819853c418)
2015-09-19 18:05:21 -07:00
Tim Abbott
87d2d543a5 Remove some tools unlikely to be relevant externally.
(imported from commit 557f5590d87b3267a2e37e9be72a77815ca392d9)
2015-09-19 17:45:31 -07:00
Tim Abbott
155958871d Include Zulip financial projections tool in open source release.
It doesn't have any sensitive data since that lives in a separate
configuration file, and it's potentially useful.

(imported from commit 094e315439f8bd23ad07a8c2bc7d9776c8c7f096)
2015-09-19 17:45:31 -07:00
Tim Abbott
166192fb57 Add additional missing IP addresses to ALLOWED_HOSTS.
(imported from commit 4f81101a1df35074947228c259e944c4565061c6)
2015-09-19 15:51:27 -07:00
Tim Abbott
24dfa10556 Fix some test-related documentation in the README.
(imported from commit 130f316ffc87c8032219660a26c0c9681c6ab52b)
2015-09-19 15:51:26 -07:00
Tim Abbott
36445d1576 Fix running single frontend tests using just the test-names.
(imported from commit 0b93abc0379b0a2ec900fe317843a7839258f7a9)
2015-09-19 15:51:26 -07:00
Luke Faraone
7f8ef32704 Revert "Revert "Clarify test status in README.dev""
This reverts commit 89bf83fb93d4e61dc799857571c6a7bfc6774a1c.

(imported from commit 0663832146f485a74bdf325f39c31b0a30df5f63)
2015-09-19 15:35:17 -07:00
Luke Faraone
394a0aa774 Revert "Clarify test status in README.dev"
This reverts commit 910e58904e9af44b9382075b72e03b624c29256b.

(imported from commit 89bf83fb93d4e61dc799857571c6a7bfc6774a1c)
2015-09-19 15:33:20 -07:00
Luke Faraone
a8643e44b4 Clarify test status in README.dev
(imported from commit 910e58904e9af44b9382075b72e03b624c29256b)
2015-09-19 15:31:47 -07:00
Neeraj Wahi
9f0a6272fa Removed dbx_branding flag and Dropbox corner logo
(imported from commit d205898671643985e2de7c0d6d300bdca32cae21)
2015-09-19 15:16:42 -07:00
Tim Abbott
cf1aff661c Add current production IP addresses to ALLOWED_HOSTS.
(imported from commit c255acb6ad7cd47d8a51509f4c24a05ac06ebd9a)
2015-09-19 15:13:02 -07:00
Reid Barton
5be0c2902e Connect to the zulip database correctly in postgres-init-db
(imported from commit b6ab80567ff5d229a00c7d2cf5866bca0ee9c7c5)
2015-08-29 12:07:33 -07:00
Reid Barton
73264ab530 Move VOYAGER detection to after initialization of ZULIP_COM
(imported from commit c9aa814ebc30a78abe8babfc3bf2eedb8198d17d)
2015-08-29 12:07:33 -07:00
Reid Barton
0a3bdc20e9 Only autofocus email/username fields when they are present
(imported from commit e5fa2e19a6e2ffaeeccf32b82e993188144e48ba)
2015-08-28 16:18:12 -07:00
Reid Barton
942e97d886 Create directory to write log of initial installation into
(imported from commit fa352a7b4f57379df14249fd5f168249ead64777)
2015-08-28 09:40:30 -07:00
Reid Barton
d8b44606a3 Make configure-rabbitmq fail on error
If there's a problem with Django settings then RMQPW would just be
empty, causing more confusing errors downstream.

(imported from commit 5948b1a15eb92fc032ea02e499be58365d8e9ecb)
2015-08-28 09:37:58 -07:00
Reid Barton
4e61c06903 Fix postgres syntax when creating zulip schema in production
(imported from commit 51ba85b995e4b5044f914163dab7f2ae14df908f)
2015-08-28 09:37:46 -07:00
Reid Barton
3239ca6728 Update build-voyager-tarball local settings hack
The tarball build process runs in DEVELOPMENT mode, assuming it is run
on a dev VM (since then there is no /etc/zulip directory). Commit
d067bcfe9d71 made settings.py import local_settings_template.py in
DEVELOPMENT mode (then "not DEPLOYED"), not local_settings.py.

(imported from commit 9a08138d748dfca9c4ab8b366bee5c2fb96c25af)
2015-08-23 23:08:45 -07:00
Reid Barton
1f07cbed1e Remove tree forcefully when finished in build-voyager-tarball
Just importing zerver.lib.cache creates a file memcached_prefix that
is mode 0444, so we need to use -f or rm will prompt about whether to
remove it. Not sure why this is apparently a new issue.

(imported from commit 93c5140b66992339859e2b204c200d1dd7a35f2d)
2015-08-23 23:00:32 -07:00
Reid Barton
36716fe518 Add remaining custom indexes that were created by South migrations
(imported from commit 9798afa8161af4ae6b3fa0c5f4894a3211b77cd4)
2015-08-23 21:47:12 -07:00
Reid Barton
5768fd7f49 Remove reference to Zulip deployment key from Zulip Voyager README
(imported from commit 74a4f86839fb76eb175016453d91b916b9ce416d)
2015-08-23 21:44:27 -07:00
Reid Barton
bf8cc35edc Add puppet to provision.py
We don't use it to set up the dev VM environment, but we do use it to
verify the Voyager puppet configuration parses in lint-all.

(imported from commit 3f116633ba3f535dfb4ae27915b6356e560ac84f)
2015-08-23 21:35:14 -07:00
Tim Abbott
1f2aa2fcab Fix write_log_line for real.
(imported from commit cbb5c38b8e6c31822b28c478463978aa6cab33d4)
2015-08-22 14:40:47 -07:00
Tim Abbott
51841d5bcb Fix terms of service and Dropbox logo on website.
(imported from commit 29c838fbd3aa495bb85b730b134b31f544de7a8b)
2015-08-22 14:33:15 -07:00
Tim Abbott
1d2efb46c1 Remove stray reference to our signup form.
(imported from commit d6e48d198c2e44387d4f2cd2f9cbcddd535a32db)
2015-08-22 14:24:02 -07:00
Tim Abbott
f1bf5ba24f Fix write_log_line breakage for websockets.
(imported from commit 43bf24822329cf9729654ba58e9ffb0bff3403da)
2015-08-22 14:19:35 -07:00
Reid Barton
827a825c06 Schema migrations for Django 1.8
These are the result of either the upgrade to Django 1.8 itself
(username max length increased to 254), or the changes needed for
Django 1.8 compatibility.

(imported from commit 6b1d7e73c85e9a2f7de9e5b91d851977eb4959e8)
2015-08-22 13:51:35 -07:00
Tim Abbott
17fd248f23 Move postgres host configuration for zulip.com out of settings.py.
(imported from commit fe95011ae86ff7c5f20c789b459a763326da374d)
2015-08-22 13:49:43 -07:00
Tim Abbott
930c64df8a Move zulip.com-related statsd configuration out of main settings.py.
This also removes the convenient way to run statsd in the Dev VM,
because we don't anticipate anyone doing that.  It's just 2 lines of
config to configure it anyway:

STATSD_HOST = 'localhost'
STATSD_PREFIX = 'user'

(imported from commit 5b09422ee0e956bc7f336dd1e575634380b8bfa2)
2015-08-22 13:49:43 -07:00
Tim Abbott
3e87c82d56 Reorganize settings.py to put the default values in a sane place.
(imported from commit 00f09c6c65cb95d29c466e996b17f80a30635acf)
2015-08-22 13:49:43 -07:00
Yoyo Zhou
50ccbc4230 Refactor database configuration to make ZULIP_COM the special case instead of the default.
(imported from commit bba7a3a78dc4fd0e442503f8707295eabc581652)
2015-08-22 13:48:52 -07:00
Yoyo Zhou
8549606eb3 Require ALLOWED_HOSTS to be set in production.
(imported from commit 581e3d44aa42b5c8e6322b760b8b66a1f0aaf375)
2015-08-22 13:48:52 -07:00
Tim Abbott
da84aa3412 Require REQUIRED_SETTINGS in PRODUCTION.
(imported from commit 7f43ba4d54021f806481b2e369c5482b0e0f99fe)
2015-08-22 13:48:47 -07:00
Yoyo Zhou
ab5e04ef36 Add backend tests location
(imported from commit 2f2dcd1773be746bee5d9003ca99020230acae04)
2015-08-22 13:08:11 -07:00
Yoyo Zhou
e130884c6a code-style: Simplify rST syntax.
(imported from commit c2bd43f97969b7be61476435ac00ae03fd05ec4d)
2015-08-22 13:08:07 -07:00
David Roe
c17e50e0c4 Add new feature tutorial.
(imported from commit 1577c2567232aba1a1f1c6d1df83370acf54af55)
2015-08-22 12:56:57 -07:00
David Roe
a9cf471239 Remove documentation on ALLOW_REGISTER since it is out of date.
(imported from commit 75938998507f2b903f49bd9c7c4ecc0eadb3259d)
2015-08-22 12:55:18 -07:00
David Roe
33b7b2d021 Add welcome.rst with info for new developers.
(imported from commit 14e27efc47cfb0802f16ec5d2d6c5eadeba7a2c2)
2015-08-22 12:54:20 -07:00
David Roe
1a3bc517d9 Improve docs/README.md
(imported from commit 78193958bdb5f92ae5d8706340a739dae0da5367)
2015-08-22 12:53:54 -07:00
Anders Kaseorg
2e5c82203d Fix 05-settings.js test
The tests run as iago, who is now an administrator and therefore has
control over many more bots.  Be specific about which bot to operate on.

(imported from commit 7a9d3e12da905338624747dd402702bb66907cfd)
2015-08-22 12:52:44 -07:00
Tim Abbott
cecbab3609 Remove now-unused is_customer4 flag.
(imported from commit 4ccd2126d7faef82c588f9523f3fe771fff273af)
2015-08-22 12:48:54 -07:00
Reid Barton
9eee250720 Give the realm created by populate_db a name
I got tired of seeing the tab title "null - Dropbox Chat".

(imported from commit fb88bf1e01b0d0ecbfe2320abb02a69afbb2ac38)
2015-08-21 17:02:47 -07:00
Reid Barton
a3d85f501b Create tsearch_extras in production database setup
(imported from commit e6c699b06f022d923b57ccee7ad778f870bf890d)
2015-08-21 16:54:35 -07:00
Reid Barton
3649c7be73 Display instructions for debugging the frontend tests when they fail
(imported from commit 21f7e6adf1f3f500ce1faf3667f40674bf0f3d6e)
2015-08-21 15:04:50 -07:00
Reid Barton
f25f935c02 Install PhantomJS 1.9.8 from binary download
Now the tests don't crash for me all the time.

(imported from commit bbecff2840f888ca44115f83eed84709434500b2)
2015-08-21 15:04:50 -07:00
Reid Barton
3cfebbd9c0 Fix peer authentication error for process_fts_updates in run-dev.py
(imported from commit 1c73877a1c437ec51d909034460c3c1b54178183)
2015-08-21 14:10:52 -07:00
Tim Abbott
6f50a2703e Remove duplicate ZULIP_COM detection from settings.py.
And fix up some required configuration.

(imported from commit 761758638baa297118848c9f5640638d6b2f4f67)
2015-08-21 10:48:13 -07:00
Tim Abbott
e78361f985 Move STATSD_CONFIGURATION below setting defaults.
(imported from commit 48d833c672ad96318f738c663c3bea61cd1ec382)
2015-08-21 10:42:15 -07:00
Tim Abbott
83a653efce Change semantics of ZULIP_COM to include ZULIP_COM_STAGING machines.
(imported from commit 2e84c756b4ac41c13d619ab6ceb99e347d1f48cb)
2015-08-21 10:41:14 -07:00
Tim Abbott
a8261dd6ac Remove Deployment initialization from Development.
(imported from commit 4596fcf480c10c88496cd6506edb0a6e702d823c)
2015-08-21 10:40:57 -07:00
Tim Abbott
16e0f21687 Fix a bunch of Zulip Voyager related comments.
(imported from commit 176e875cbc310ba00d6137930ddb718bd68f1866)
2015-08-21 10:40:54 -07:00
Tim Abbott
d0afb75619 Clarify documentation for SMTP delivery code.
(imported from commit 3b13f39fd56e9c381201911479c1326883c38445)
2015-08-21 10:33:36 -07:00
Tim Abbott
d281fc75fd Rename generate_voyager_secrets.py => generate_secrets.py.
(imported from commit c2f370c3b241601b4f6883d3953ceec1efda71be)
2015-08-21 10:33:36 -07:00
David Roe
e3f38acbce Enterprise => Voyager.
(imported from commit 41b9a67301aeaf5fd40bbbb8f34a326ca98431fd)
2015-08-21 10:33:35 -07:00
David Roe
3f7cb34b00 enterprise => voyager
(imported from commit 04be792bb480d5e5db1c91d296d1000cf1682571)
2015-08-21 10:33:35 -07:00
David Roe
edf7e732a2 ENTERPRISE => VOYAGER.
(imported from commit 4f8080b9f506a87ca40bef32e39de5218cba916a)
2015-08-21 10:33:35 -07:00
David Roe
f9f1fdc4d7 change deploy_type in zulip.com conf file.
(imported from commit 6fad28d15f530a619d7359bce0a182ed61b876ab)
2015-08-21 10:33:35 -07:00
David Roe
f79adf830f deployed => production
(imported from commit 2d7b0a7a73b0c84b32634a88af1e0d666139d4ff)
2015-08-21 10:33:35 -07:00
David Roe
d702ddb3cf DEPLOYED => PRODUCTION
(imported from commit a7d365c07916c5103fc721c712db94f9af977640)
2015-08-21 10:33:35 -07:00
David Roe
63e576b811 STAGING_DEPLOYED => ZULIP_COM_STAGING
(imported from commit 25419979292218932c53cface59c1e8e2348a7c2)
2015-08-21 10:33:35 -07:00
David Roe
8778c4726a Add settings.DEVELOPMENT as a complement of settings.DEPLOYED.
(imported from commit 0437140d9fee7eec7b28abe583cfe8cde3e07c21)
2015-08-21 10:33:35 -07:00
David Roe
24f6743288 Eliminate TESTING_DEPLOYED.
(imported from commit 477d8b7a15f703df1e10ae5682e02fea5ce040e4)
2015-08-21 10:33:35 -07:00
David Roe
59b94a901c Moving ALLOWED_HOSTS to local_settings.
(imported from commit b89c6983fd87ede42954dd84706f999ed0de740d)
2015-08-21 10:33:35 -07:00
Tim Abbott
80651c99cd Stop using local_settings.py at all in the Dev VM.
(imported from commit d067bcfe9d71628d8f671c5bc7bb38f521f9a965)
2015-08-21 10:33:35 -07:00
Tim Abbott
78277b5ee5 Make ADMIN_DOMAIN and ZULIP_ADMINISTRATOR have sane dev defaults.
(imported from commit 3d2602166541c7eaa72ea7fad87a2dc86f7c8f15)
2015-08-21 09:01:58 -07:00
Tim Abbott
3e61714035 Make DEPLOYMENT_ROLE_KEY no longer required.
(imported from commit 046ce610d847cc987d3f6d584ccc0bc84b55df84)
2015-08-21 09:01:58 -07:00
Tim Abbott
90bfc39d55 Remove dead GoogleBackend from prod configuration.
(imported from commit 5fcf5c4bdb8d3564819005b624076878b59cd23b)
2015-08-21 01:42:22 -07:00
Reid Barton
ab9539cffe Remove OpenID authentication
(imported from commit 70a859041a851ed10dc40cfc068330e472d2ed09)
2015-08-20 23:52:48 -07:00
Reid Barton
e7dc77426a Django 1.8: record # of queries regression
I haven't tracked down the cause of this.

(imported from commit 05854d85c870361bd447083a22da780e7ed895f4)
2015-08-20 23:35:41 -07:00
Reid Barton
ae0ae3dde8 Django 1.8: declare positional arguments in management commands
(imported from commit d9efca1376de92c8187d25f546c79fece8d2d8c6)
2015-08-20 23:35:40 -07:00
Reid Barton
ecc07333af Django 1.8 compatibility: miscellaneous changes
(imported from commit 086fac44cbdce1986a07e2ade00412dd538b4f23)
2015-08-20 23:15:45 -07:00
Reid Barton
15fe02b618 Remove authhack
In Django 1.8 the username length limit seems to be 254 by default.

(imported from commit cf0027431f5a4fea9e366a49d345b9d09b90d869)
2015-08-20 23:15:45 -07:00
Reid Barton
d88efef74b Fix field name in get_bots_backend
Django 1.8 noticed that it was wrong.

(imported from commit d9578719e7713c1fd6756b80aac13f4d93f12fa7)
2015-08-20 23:15:45 -07:00
Reid Barton
0aab583bb1 Django 1.8 compatibility: transactions
- autocommit is now the default
- commit_on_success is now atomic

(imported from commit b6166ca666ff23d34f2871ca365ce3ec66b0fa86)
2015-08-20 23:15:45 -07:00
Reid Barton
9db521a931 Django 1.8 compatibility: extracting the user from a session
django commit 596564e80808 stores the user id in the session as a
string, which broke our code that extracts the user id and compares
it to the id of a UserProfile object.

(imported from commit 99defd7fea96553550fa19e0b2f3e91a1baac123)
2015-08-20 23:15:45 -07:00
Reid Barton
5ea3bf85de Django 1.8 compatibility: module_name -> model_name
(imported from commit 38ee96c9a8da5b3abfce8ba47f85dd7d59bcb599)
2015-08-20 23:15:44 -07:00
Reid Barton
e65d508907 Update requirements.txt for Django 1.8
(imported from commit 534e611d9cf61a38c9e1d862e9941cc400c386b9)
2015-08-20 23:15:44 -07:00
Reid Barton
362f9c6c5f Django 1.7: syncdb and migrate are now synonyms
(imported from commit b8a1b2476892bab2418240b04deea6aa40ff1b03)
2015-08-20 23:01:26 -07:00
Reid Barton
dfdc34603e Django 1.7 compatibility: handle both response.content and response.streaming_content
(imported from commit faaaff96819731a334d52b7d715c8ddb7c0d4293)
2015-08-20 23:01:26 -07:00
Reid Barton
9ded218950 Django 1.7 compatibility: miscellaneous changes
(imported from commit 1f63d936c3d195acd033bb42fddacd240af3889b)
2015-08-20 23:01:26 -07:00
Reid Barton
599742536b Switch from South to native Django migrations
This commit loses some indexes, unique constraints etc. that were
manually added by the old migrations. I plan to add them to a new
migration in a subsequent commit.

(imported from commit 4bcbf06080a7ad94788ac368385eac34b54623ce)
2015-08-20 23:01:26 -07:00
Reid Barton
64cccb2267 Update requirements.txt for Django 1.7
(imported from commit 9cdcba315c5bc380e15b82850c049b8a02ce50d7)
2015-08-20 22:44:22 -07:00
Yoyo Zhou
15abf9ed31 Move all remaining calls of get_secret from local_settings.py to settings.py.
(imported from commit 099a122121f8e06568cef3579f955cb73b20ee50)
2015-08-20 22:19:26 -07:00
Yoyo Zhou
bd5fc484f0 Move GOOGLE_OAUTH2_CLIENT_SECRET to be read in settings.py.
(imported from commit 814dc32cd6099516486be76fa8baffbafda69596)
2015-08-20 22:19:17 -07:00
Yoyo Zhou
4b3874988f Move DROPBOX_APP_KEY to be read from get_secrets
(imported from commit 99acd66c4478a0826b0e0ec7bf26c9a59f7febca)
2015-08-20 21:58:59 -07:00
Yoyo Zhou
ef320c6e95 Remove Redis remote authentication feature.
We can add it back later but for now we can just stick with localhost
since that's what most people will want.

(imported from commit c5fe524282219dc62a0670f569c0cb6af04be339)
2015-08-20 21:58:59 -07:00
Yoyo Zhou
e41c00107d Move twitter secret keys to use get_secrets in settings.py
(imported from commit cc21265ae64a49be20bec74386314d60ee822746)
2015-08-20 21:58:59 -07:00
Yoyo Zhou
32f6d1055d Get s3_key and s3_secret_key from secrets in settings.py.
(imported from commit 2c2574988486bbb6f0f769250664a5a2a4c9e6c9)
2015-08-20 21:58:51 -07:00
Yoyo Zhou
d34d44e1d4 Read ANDROID_GCM_API_KEY from secrets; move to settings.py
(imported from commit 0d0d59116065956b9cbbe895eb09f0433b752cf1)
2015-08-20 21:54:55 -07:00
Yoyo Zhou
ec5ed87ca0 Make get_secret return None instead of an exception if the secret isn't defined.
Remove empty key generation from generate_enterprise_secrets, since get_secret ignores missing keys now.

(imported from commit 32d61e3058f0d41bfb4b17775e581a3c84540fe7)
2015-08-20 21:54:38 -07:00
Yoyo Zhou
2cab113035 Rename getsecret -> get_secret and remove duplicate secret-reading code in settings.py
(imported from commit 097d6b4fad1fcf8b6f09dc212056fdb313efe5e4)
2015-08-20 21:52:26 -07:00
Nemanja Stanarevic
d9f111ec28 Added import_dump command to manage.py to import JSON database dumps
(imported from commit abd410e5299f15c1a5851e87d18664b59837fbb0)
2015-08-20 21:19:57 -07:00
Jonathan Dahan
e95dfd78ed Fix production deployment script.
(imported from commit 5b8398a0075dc297d3f86c65ce2ef43977e57ecb)
2015-08-20 20:50:41 -07:00
Tim Abbott
58e5c654fa Make feedback button option default-off.
(imported from commit 23b89ab72bd04826016631e01da950af0a5df694)
2015-08-20 19:47:00 -07:00
David Roe
13f3b448e5 Kill Embed.ly integration.
(imported from commit dfe42a26e57100108c3c50298041bd520e0d8b1b)
2015-08-20 19:46:48 -07:00
Anders Kaseorg
95afea9006 Remove enterprise registration form
(imported from commit 58914685752bff3c9d0e56ffe21bd3cd367e70e7)
2015-08-20 18:40:34 -07:00
Anders Kaseorg
bded0d9d54 Remove corporate beta signup form
(imported from commit 1b3a0cd8a59a124905fa4cbd3121a78d23aeb3a2)
2015-08-20 18:40:34 -07:00
Anders Kaseorg
cb88147ca9 Remove corporate marketing page
(imported from commit 24128853fd78ef9e89df7f3353f45ac2531a42e1)
2015-08-20 18:40:34 -07:00
Anders Kaseorg
1b5f9e4374 Remove corporate jobs pages
(imported from commit 3f1789f6a4f90a33ddd2352fab85d3cf751b0f46)
2015-08-20 18:40:34 -07:00
Anders Kaseorg
5c6cd40fe7 recipient_for_emails: Fix type error
Fixes
[
  File "/srv/zulip/zerver/lib/actions.py", line 605, in recipient_for_emails
    if not (normalized_emails & admin_realm_admin_emails or normalized_emails & settings.CROSS_REALM_BOT_EMAILS):
TypeError: unsupported operand type(s) for &: 'set' and 'list'

(imported from commit f39a95dad7b3207e9188fc03926cd116061ef3f3)
2015-08-20 18:40:31 -07:00
Anders Kaseorg
36c6f1e731 provision: Do not silence stdout and stderr
(imported from commit 58cd23b0d77a26c9961c0c1f9a37433ac0fb9290)
2015-08-20 18:36:34 -07:00
David Roe
3515a69e43 Remove public_streams_disabled.
(imported from commit 1d0c8db92bf8e4c44bd1c96063acfd6eea74925c)
2015-08-20 18:12:53 -07:00
Luke Faraone
d2979ab5d4 Move main body of provision.py into a function
(imported from commit befd4f45bf5876c61456bd2c262bfa9136b514e7)
2015-08-20 18:08:08 -07:00
Tim Abbott
222ea05a3a Warn users that twenty-four-hour-time doesn't update without a reload.
(imported from commit e3c00082746284fb0e6f9b958a887b9d1a1b86a3)
2015-08-20 17:59:16 -07:00
Tim Abbott
1880e96a22 Fix tests broken by twenty-four-hour-time feature.
(imported from commit 4f6215b303de8e27323141f687e046048f1456b5)
2015-08-20 17:59:16 -07:00
Kate Buckner
b58867451d Add dev-secrets.conf generated by latest version of dev VM to gitignore
(imported from commit 001bb790e530038fe38cd38550e495c47c5dea92)
2015-08-20 17:33:17 -07:00
Kate Buckner
4d0f7c7ea4 Add a user-visible setting for 24-hour time display.
(imported from commit d934824fd6b72e64a455aac9ff4585b262145f02)
2015-08-20 17:33:16 -07:00
Tim Abbott
9734d1ab3f Remove confusing half-implemented retention policy code.
(imported from commit 539bd5f0a49a8cb564112d12723526887d955f71)
2015-08-20 17:33:16 -07:00
David Roe
bfa70675cb Remove notify_for_streams_by_default.
(imported from commit 9963c97ffec82fe7cf2921bd51422545c29a8915)
2015-08-20 17:33:16 -07:00
David Roe
def426aa34 Remove exceptions for two domains where all streams were private.
(imported from commit 1e391a50875091f6a8843d3915a6893f2d903f22)
2015-08-20 17:33:16 -07:00
Tim Abbott
6176dfd039 Install yui-compressor for building enterprise tarballs.
(imported from commit 917d6a5221b5c2c50fc399c9942cb3682e3471ca)
2015-08-20 17:33:16 -07:00
Tim Abbott
9000d27f12 Update generate_enterprise_secrets to support running in production.
(imported from commit 1051f668ebe684cc60ba4444e815ef60398fad61)
2015-08-20 17:33:16 -07:00
Tim Abbott
e79447131f Make build-enterprise-tarball run again.
(imported from commit e3dd8d75811458d0cee8a2d05a4b47abd6eda7fd)
2015-08-20 17:33:16 -07:00
acrefoot
0a6bb975c3 Replace settings.OG_ZULIPER_EMAILS with database lookups
Also renames the OG_ZULIPER_EMAILS to CROSS_REALM_BOT_EMAILS

(imported from commit a9e0ccebbd6b37376e535600670ad493dc8de7e1)
2015-08-20 17:20:41 -07:00
Reid Barton
53c2b3f6f4 Clean up vagrant postgres user creation code
We don't need to check whether the user exists before creating it:
CREATE USER failing is fine.

(imported from commit e8b2bc5495e328ee30d15445a566c0edff2f069d)
2015-08-20 16:30:21 -07:00
Reid Barton
748f931999 Fix postgres users when re-provisioning
If we run provision.py a second time, there will already be
zulip/zulip_test users, so the CREATE USER will fail and the password
won't get updated to the newly generated value. By creating the user
and setting the password in two commands, we allow the creation to
fail without affecting whether the password is set.

Also the quoting for updating .pgpass was wrong.

(imported from commit 5e249813c17cb4829e4e4958e92aaa30563c5f96)
2015-08-20 16:30:21 -07:00
Anders Kaseorg
dd8eda4edc run-dev: Run compile-handlebars-templates inside the pgrp
(imported from commit bb13f8804b7e9e930ecd2542ea8772c76370d32e)
2015-08-20 15:54:53 -07:00
Anders Kaseorg
bd66b2139b run-dev: Eschew useless shells
(imported from commit 34dab15941f5c63f381f5b2b7b78482dbc2b02ea)
2015-08-20 15:54:53 -07:00
Reid Barton
664db6b622 Generate more test messages to avoid test failures
Sometimes I get the error "Selected message id not in MessageList"
when running the casper tests. I think it's probably when the test
user's home view does not contain any messages.

Ideally we would fix this in a way that guarantees that we generate
whatever messages the test suite needs...

(imported from commit 51a02da612dda88d60681b9e09cd6e6a2c39a470)
2015-08-20 15:43:43 -07:00
David Roe
8cb7b759c6 Add tests for new realm properties, fix revealed typo.
(imported from commit 49ffcf7edc64c2dbc3cf41ed64222390072c2e88)
2015-08-20 15:29:46 -07:00
David Roe
086d8eee22 Add name_changes_disabled realm field.
(imported from commit 6b04ba2f7ad64c44f2ef18302f0fbd819259d632)
2015-08-20 15:29:46 -07:00
David Roe
5b7f3466ba Add feature where only admins can invite new users.
This is controlled through the admin tab and a new field in the Realms table.

(imported from commit e78a6f48160e2a1bbc68d278beb726fe31515266)
2015-08-20 15:29:46 -07:00
David Roe
809efc4f2b Add realm option to show or not show digest e-mail.
(imported from commit e9cfe519aa9f2857a1dcc7c75f5e1889834fcb86)
2015-08-20 15:29:45 -07:00
David Roe
e5cb2a468f Enable Lab features for all users
(imported from commit 4e2658d28a5e02067ad472fec76c66f46592d520)
2015-08-20 15:29:45 -07:00
David Roe
90e2f5053f Add mandatory topics as a realm option.
(imported from commit 929a884b8610669aa24a167367b899683e33a045)
2015-08-20 15:29:45 -07:00
Yoyo Zhou
6a63303736 Add dependencies for test-js-with-node and test-js-with-casper to provision.py.
Create a .bash_profile in the VM that activates the python venv on each login.

Node dependencies include some npm packages that haven't been backported to trusty yet.

(imported from commit 8307740004a05b0c9d6ea26f97c2e80b9d1bbaf4)
2015-08-20 14:29:45 -07:00
Yoyo Zhou
f78abd2dcc Update schema changes content and formatting.
(imported from commit 46f3d43bfe62883d490ea870b2d29f7a45397c08)
2015-08-20 14:24:59 -07:00
Yoyo Zhou
4a6e132a44 Add "Schema changes", rST generated via pandoc -r mediawiki -w rst
(imported from commit f3c5621a8b612217986c879d3d15b85c9098ccca)
2015-08-20 14:24:59 -07:00
Yoyo Zhou
1e3249c94e Add note that provision.py sets up postgres test db for you
(imported from commit 87d31b04db15b8ea994f40362ab910ccc028c91a)
2015-08-20 14:21:55 -07:00
Yoyo Zhou
a1237aa2b2 Update testing notes formatting and content.
(imported from commit 44cc34888f14d101c29bcd1c8d63cc082b4ffe09)
2015-08-20 14:21:55 -07:00
Yoyo Zhou
bb45f8d8e3 Copy "Testing the app" from the wiki, via pandoc -r mediawiki -o rst
(imported from commit 7150179ff1008ffa6849b983fb579a36fffc9c06)
2015-08-20 14:21:55 -07:00
Reid Barton
5a747ab690 Make the CasperJS frontend tests work again
(At least when PhantomJS doesn't crash...)

(imported from commit 62936b12883e4c6bbd3701da80783b4bffe46025)
2015-08-20 13:33:07 -07:00
Anders Kaseorg
dfb1601aed Turn on cleanup_before_reload for everyone
(imported from commit 724a7b2bb5a0679b58eac62eaaf41d8397726c38)
2015-08-20 11:10:39 -07:00
Anders Kaseorg
62973fce0f Remove unused zulip_mit_emails, is_zulip_mit_user
(imported from commit 8d49bd9a490a367c58befa09e0922f66e7923e77)
2015-08-20 11:10:39 -07:00
Anders Kaseorg
3043859700 Remove CUSTOMER3 advertisements
(imported from commit c48b478cbb7b682f1c76af027b487af73893c2be)
2015-08-20 11:10:39 -07:00
Anders Kaseorg
7cd1d9665d test_settings: set CAMO_KEY = 'dummy' to make tests pass
(imported from commit d8705d8bbcad365b6b94a456d1942a8afc1a32d4)
2015-08-20 11:07:52 -07:00
Cat Miller
0a20f168a7 Auto-generate dev-secrets file.
Source LOCAL_DATABASE_PASSWORD and INITIAL_PASSWORD_SALT from the secrets file.
Fix the creation of pgpass file.

Tim's note: This will definitely break the original purpose of the
tool but it should be pretty easy to add that back as an option.

(imported from commit 8ab31ea2b7cbc80a4ad2e843a2529313fad8f5cf)
2015-08-20 00:20:44 -07:00
Tim Abbott
86278804c9 Use the EmailAuthBackend for the test suite.
(imported from commit 2f7bf9864991358e9dabacbd2b0f652a9f69230c)
2015-08-19 23:34:30 -07:00
Tim Abbott
dc5a5ce1de Fix lint error.
(imported from commit 4c0897d109ddb229989afd8e4b4db270569e558a)
2015-08-19 23:24:56 -07:00
David Roe
4bd93325de Don't create the MIT realm in the Dev VM.
(imported from commit 2e8122cfca87ace24f5048a6ecc57c8c5b3d101c)
2015-08-19 22:24:53 -07:00
David Roe
a9023935e4 Make the default Dev VM user Iago a Zulip admin.
(imported from commit ebec7b44c1d7fdbd270ee534f2c5453a21ae3884)
2015-08-19 22:24:53 -07:00
David Roe
dedc83e5dd Switch links on login page to the register page in Dev VM.
(imported from commit 16e285b2d8f3c5124eaef0b20aa1097d4a1934d0)
2015-08-19 22:24:53 -07:00
David Roe
472898cfc6 Allow adding users to realms more easily in Dev VM.
Include new field on Realm to control whether e-mail invitations are required
separately from whether the e-mail domain must match.
Allow control of these fields from admin panel.
Update logic in registration page to use these fields.

(imported from commit edc7f0a4c43b57361d9349e258ad4f217b426f88)
2015-08-19 22:24:53 -07:00
David Roe
32783ebbfb Admin users in red, at beginning, in dev login view
(imported from commit 530f0a5d26d5c2b637834281e45adb399852ae0a)
2015-08-19 22:24:53 -07:00
Tim Abbott
902edf5200 Fix comment typo in provision.py.
(imported from commit d8fcfb6d2ab5820f0d6032ae66bda16cf92132f0)
2015-08-19 21:41:44 -07:00
Jonathan Dahan
580cdb55be Install git pre-commit hooks in the vm as part of provisioning.
(imported from commit b3aa3b44de198abea49f5b43e2403f466f30f66c)
2015-08-19 21:41:04 -07:00
Jonathan Dahan
795f191fb3 Remove git commit domain restrictions.
(imported from commit a756428d0b95db95fb093e78a182ad8873914f54)
2015-08-19 21:40:04 -07:00
Luke Faraone
1e7d7c0b71 Install a supervisor job for run-dev.
The development server will automatically start after provisioning finishes.

(imported from commit 6be3d954d9049acd0360189b07b1481756b69eef)
2015-08-19 21:07:23 -07:00
Luke Faraone
7e78dc4ca1 Clean up, comment more in provision.py.
Also remove unused import.

(imported from commit 8ba0020758ad842085b4f7dae7bfa3560281bd3a)
2015-08-19 21:07:23 -07:00
Luke Faraone
75d0146d33 Don't assume the user's OS in provision.py
We still need to put in the work to support other platforms, but now at least
we'll error out if you're not on 64-bit Ubuntu 14.04.

(imported from commit 3a35953206906044947e3447c7ab8fca78a76e1e)
2015-08-19 21:07:22 -07:00
Luke Faraone
0d7f749ad8 Run provision.py as a provisioner.
This way, vagrant up for the first time will set up the developer's VM
correctly

(imported from commit cee17b15e2f53a1b6de1f1ee16dbad00071ba55c)
2015-08-19 21:07:22 -07:00
Luke Faraone
e2d416ad8b Clean up additional comments in the Vagrantfile.
I'll fixup this before publication.

(imported from commit a57cc240c6b57da4423749c13aa72fa63e4812c5)
2015-08-19 21:07:22 -07:00
Luke Faraone
04d3eb33b1 run-dev.py: Reword --interface help text.
The old language was confusing because "the interface" could refer to something
like eth0, but in actuality refers to the IP/hostname to listen on.

(imported from commit 4f77d72a4dfcdbe7e7747c6228975aa68dfbe6ac)
2015-08-19 21:07:22 -07:00
Jonathan Dahan
6f77e68622 Add GET /export endpoint, which dumps important tables in json.
Meant to be used in tandem with the manage.py import command.
The following sensitive data is scrubbed:

  * user api keys
  * user password hashes
  * stream email keys
  * invite-only streams
  * messages from invite-only streams
  * messages from users from other domains

(imported from commit 8e58dcdcb80ef1c7127d3ab15accf40c6187633f)
2015-08-19 15:31:08 -07:00
Jonathan Dahan
be23e6d189 Ignore generated event_queues.json and .vagrant directory.
(imported from commit c499a500cbc9e1354b84ab1a6b7fe859f2509db1)
2015-08-19 13:36:44 -07:00
Yoyo Zhou
6e55b4df8a Update directory-structure.rst content to fix internal references
- Delete references to zilencer
- Replace "local server" references
- Add directories for message views, frontend templates/tests, and docs

(imported from commit 7295835434c17609595399e3aec7f9d565fd6b3d)
2015-08-19 11:52:49 -07:00
Yoyo Zhou
1629e77174 Directory structure generated from pandoc, with formatting fixes
(imported from commit d54bb062b641bac0520494f0a2cb151d69018d61)
2015-08-19 11:52:49 -07:00
Yoyo Zhou
127cdf63c6 Add CSS style override for RTD to make tables use word wrapping
(imported from commit 29007c052dd7048eaf86388a6a9715fc13f102b5)
2015-08-19 11:52:49 -07:00
Yoyo Zhou
5f74e6e76d Fix a lint warning in notifications.py caught by newer pyflakes (0.9.1)
zerver/lib/notifications.py:353: list comprehension redefines 'msg' from line 336

(imported from commit 094a21616f8fe7ffe05719c6de6449ade5c43517)
2015-08-19 11:43:49 -07:00
Reid Barton
54adbb1737 Create vagrant postgres user and grant it rights to zulip{,_test}
(imported from commit bb57a3f5ef8bc48553f1eff95c47894aed4ef975)
2015-08-18 22:41:31 -07:00
Tim Abbott
7cffb41e13 Reorganize and document settings.py.
(imported from commit e2694979d5aee95c22b83b7aa84d80b56ffae1d6)
2015-08-18 20:57:35 -07:00
Tim Abbott
5b8894cd25 Rename USING_SSO to something more clear.
(imported from commit 94e8ae84b01419783872a5d09bafe5c2eb933c18)
2015-08-18 20:48:15 -07:00
Tim Abbott
05b0cbb36a Zulip doesn't use MEDIA_URL.
(imported from commit ebc370d9c5cf2d7e7d366cbb25fe721c817f212e)
2015-08-18 20:48:15 -07:00
Tim Abbott
dcc3b3fe37 Don't create Zulip employee accounts automatically in Dev VM.
(imported from commit 378f12d3f2ac4c131919c0efbd049b9eaa961694)
2015-08-18 20:46:35 -07:00
Tim Abbott
2de3e2ebdd Move several secrets to using the get_secret function in settings.py.
(imported from commit 08fb828265c4a9e35294a51c0901bd5ad3990344)
2015-08-18 20:17:48 -07:00
Tim Abbott
8c88746912 Move iOS App IDs to settings.py since it's needed to run the app.
(imported from commit 891e32ffa82430487fc333fa549ee465f0d018c0)
2015-08-18 20:17:48 -07:00
Tim Abbott
43c7ff64d1 Remove unused FULL_NAVBAR configuration setting.
(imported from commit 47c3be669f7ba44426301a46e3f54054f3e2440b)
2015-08-18 20:17:48 -07:00
Tim Abbott
0dae10eab4 Remove unused secret HASH_SALT.
(imported from commit 831c4cb7680b7bf8dadbd930195175e9a4186356)
2015-08-18 20:17:48 -07:00
David Roe
e61de3e052 Fix invitation e-mail to use http:// in non-deployed case.
(imported from commit af68962c078036ce0fe4f37feaec6b43766b3059)
2015-08-18 20:17:48 -07:00
David Roe
2ffd022a5f Include defaults for AUTHENTICATION_BACKENDS
(imported from commit cdfffacc45f30e6959085ba8bc5aed72ae3527cf)
2015-08-18 20:17:47 -07:00
David Roe
78f32dcbd8 Fix bug in dev login which showed email/password prompts on logins after the first.
(imported from commit 626684ef1da8feb53aca05c9225ee628156f9810)
2015-08-18 20:17:47 -07:00
Tim Abbott
f792b67098 Fix send_to_prod redirect to not run on the Dev VM.
(imported from commit 6006c71348706d39740b0d6302df0a548e65b65e)
2015-08-18 20:17:47 -07:00
David Roe
46e224997e Add a new dev login page for logging in without a password on the dev VM.
(imported from commit ac8f2504771c9907b7e92dc91cec5f7220ce951b)
2015-08-18 20:17:47 -07:00
Yoyo Zhou
ef50e74873 Fix up rST formatting in code-style.rst.
- Make all code blocks look like code blocks.
- Eliminate nested inline formatting (rST doesn't support it:
  http://docutils.sourceforge.net/FAQ.html#is-nested-inline-markup-possible).
- Punctuation nits.

(imported from commit cd0d780d843b72065678e0f032a2a47d44836adc)
2015-08-18 20:17:47 -07:00
Yoyo Zhou
7b9e027e77 Expand the Lint section to replace the Python and JS subsections; remove obsolete comment from Secrets.
(imported from commit a6945617913700d4e18c398a68022ed90f56039e)
2015-08-18 20:17:47 -07:00
Yoyo Zhou
8461048a11 Add 'Code style', generated via pandoc -r mediawiki -w rst and html_unescape.py
With a basic README.md

(imported from commit 91728b2c591bc88b7bee520669cb0b3f53426cd8)
2015-08-18 17:34:02 -07:00
Yoyo Zhou
c25d9679a5 Utility for unescaping HTML entities leftover from MediaWiki->rST conversion
(imported from commit 2f2507f299c3d09c67bfd26d6c11fab47431d935)
2015-08-18 17:31:33 -07:00
Yoyo Zhou
16e462d9d2 Use sphinx_rtd_theme when not on ReadTheDocs
(imported from commit ba97a475f85251f694e4c88d1dd25eaf69078fc4)
2015-08-18 17:31:32 -07:00
Yoyo Zhou
ac63d942ce Initial sphinx setup from sphinx-quickstart
(imported from commit b9fc7a8f2f9352129c104f5dc9305203f2efc63d)
2015-08-18 17:31:32 -07:00
Tim Abbott
29ed28af00 Fix ZulipRemoteUserBackend for activating mirror dummies.
If you're using e.g. our Jabber<=>Zulip mirroring capability along
with the RemoteUser SSO integration, previously it would fail if a
user with a corresponding dummy user tried to login/signup (since they
didn't have an account but one wouldn't be created because
ZulipRemoteUserBackend was reporting that an account already existed).

(imported from commit 006eaa9afa8feedddd860c2bef41e604285228a7)
2015-08-18 11:28:36 -07:00
David Roe
81d0f7c172 Switch copyright clause on signup page to link to /hello.
(imported from commit 77b711acf017a3b17da8fe4e167f2f9263e6cf19)
2015-08-18 10:52:28 -07:00
David Roe
147304c676 Remove +Dropbox from login logo
(imported from commit f4f811ae33122d5fd2f226ec45f2ca7bd759a148)
2015-08-18 10:52:09 -07:00
Reid Barton
9c310c6cdd Update review email address
(imported from commit 2642b9fb91ab4ca0445063bccc0d46738adb64eb)
2015-08-17 15:24:33 -07:00
Luke Faraone
c6ca60d6dc quick fixes to provision.py
(imported from commit c2726fee7634498b627dae99a7a87f76f5bc83fd)
2015-08-17 11:15:21 -07:00
Luke Faraone
01d3c0c6aa Update docs for OS X
(imported from commit 1fb3219f6531a18bf8f8a1ad93568a2c1689854a)
2015-08-17 11:15:03 -07:00
Luke Faraone
f38aa4ca39 Increase memory for VM
(imported from commit 1f3976bff1526483c5f7f791fbe66ee3dcbb7980)
2015-08-17 11:14:52 -07:00
Luke Faraone
dd71771a82 Fix syntax error in Vagrantfile
(imported from commit 68366c2be0a0d08e332934100ef03570e9e20df4)
2015-08-17 10:18:40 -07:00
Luke Faraone
e8ea761fbe Initial attempt at Vagrantization
This is slightly hacky; it doesn't support as many arches as I'd like, but it works.

(imported from commit 5993014b0518d6d6dd2856fbf73180830e934b5f)
2015-08-17 09:45:51 -07:00
Luke Faraone
4702d8e9b3 Fix broken shebang in postgres-init-test-db
This was causing failures when execing outside of a shell

(imported from commit b63f8269d121b2bb8be5bcd84b3f868c9bedc9cd)
2015-08-16 21:36:36 -07:00
Luke Faraone
f5089e535d Add dummy secrets for use in development.
We also reference these secrets from zproject/local_settings.py, keying
off IS_DEPLOYED.

(imported from commit eb83310e219616ed1c6c253f0d6893134bbe3517)
2015-08-16 21:35:34 -07:00
Luke Faraone
2fb2300d1b Initial attempt at README.dev and requirements.txt
(imported from commit dea8b88114a419a127105a81c334f54670f65625)
2015-08-16 16:46:17 -07:00
Luke Faraone
48f1a84d6e Additional defaults for dev.
(imported from commit 1b4bd71ff4ed27a83a24e58e797d900a7869c72d)
2015-08-16 16:46:08 -07:00
Luke Faraone
494d02cc35 Skip S3 write/read test cases
(imported from commit 838c9a5245b45fc9082f753fe6756f270c7378a7)
2015-08-16 16:45:15 -07:00
Luke Faraone
81a2a20bbf Disable sync_api_key if no zuliprc
(imported from commit f9e7f924c00230137ca45c204158b709cd311ebb)
2015-08-16 16:45:15 -07:00
Luke Faraone
8ea139c772 Fix bugdown fixture for dummy camo key
(imported from commit 698b261918457117a01ce51f69d49f54f35b3297)
2015-08-16 16:45:15 -07:00
Luke Faraone
cf7ea9bef9 Allow configure-rabbitmq to be run w/o sudo
(imported from commit 98e820d92b42420d6851a967f6675940ee4d8217)
2015-08-16 16:45:07 -07:00
Tim Abbott
e4fce10f46 Give root higher nofile limits in limits.conf.
(imported from commit f7fd9ce325449931f8866f6696f8484769c39a14)
2015-08-16 13:39:48 -07:00
acrefoot
2f88b7dcd0 fix test_messages; othello can't be created twice
(imported from commit a3407a3f876dd3a7e3136ec19f23dc5cf9d33649)
2015-07-30 21:08:22 -03:00
acrefoot
c545a42a67 fall back to debugger if one of the test modules has an importerror
(imported from commit 856415f91dee53c72511e68f710a952fbe1a5f2e)
2015-07-30 21:08:13 -03:00
Zev Benjamin
466a678c2c Remove "More messages below" indicator
It's been very buggy for a while, has limited usefulness compared with
unread counts, and profiling over the weekend indicates that it's very
slow.

(imported from commit 716fe47f2bbec1bd8a6e4d265ded5c64efe2ad5c)
2015-03-30 15:44:36 -07:00
Zev Benjamin
4d3f0cdc74 Encode unicode strings using UTF-8 before applying search highlighting
(imported from commit 45ded691fb89ccff12e76d5ca3b593ce3ff3f2e0)
2015-03-19 15:25:42 -07:00
Jason Michalski
802a3dd357 Enable missed message notifications for zulip.com
Also increase the number of messages sent as context from 5 to 10 and
look up to 15 minutes in to the past for context.

(imported from commit bfaed9bcff1ee2047fc3b7a63acf93cd2d47cc7d)
2015-02-20 21:13:36 -05:00
Zev Benjamin
d3822c5d7b Fix initial stream subscription notification settings
(imported from commit 899577caaf5f5ea9bcff43e1bd97f8c6be453ac1)
2015-02-12 15:02:26 -08:00
acrefoot
0b7ef24a34 Add option to explicitly add pagerduty topic
(imported from commit 39ee1b37a807b19570d494f56bf7557228813ed5)
2015-02-10 23:56:03 -08:00
Jason Michalski
4eaf88e8d1 Add missing pagerduty fixture
(imported from commit 692317cfac44343788327dbd8fc65319512276de)
2015-02-10 23:56:03 -08:00
Leo Franchi
0ae8e28635 Exit without exception if this APNS attempt has no connection
(imported from commit bbdd9f3e11946739459f34b2580e4a7371b158a0)
2015-02-11 07:20:51 +00:00
Leo Franchi
d865732e0d Maintain two APNS connections and send correct notifications to each
Now we have 2 different Zulip apps out there, and they are signed with
two certs: Zulip and Dropbox. The Dropbox-signed apps are going to need
to be sent APNS notifications from the appropriate APNS connection

(imported from commit 6db50c5811847db4f08e5c997c7bbb4b46cfc462)
2015-02-11 06:57:25 +00:00
Leo Franchi
1c22b48bb1 Add an optional ios_app_id field to PushDeviceToken
(imported from commit 32d6efd1ecc58297b83e515350e6daac3bce8469)
2015-02-11 06:57:22 +00:00
Luke Faraone
910429f365 Move secrets to their own file
(imported from commit 4e46f217e8a1df9b7cc03db9dc9fc41a6c273365)
2015-02-10 17:31:26 -08:00
Leo Franchi
64a0b86917 pagerdudy -> pagerduty
(imported from commit 7cd25db67a8b20875edceafe881c872061a48fab)
2015-02-10 07:25:46 +00:00
Leo Franchi
2bb268476e Rename Streams to Manage Streams, remove hr
(imported from commit aa0dccbb35d1e10b8c7b4bbad777e176e838b965)
2015-02-10 07:23:00 +00:00
Jason Michalski
3ad140e5a7 Convert all template strings to unicode
(imported from commit ddf60d53d30a02e1bb87fac35bb45768d17e378c)
2015-02-08 22:12:33 -08:00
Jason Michalski
179bf06940 The subject is an optional field in the pagerduty API
Pages from MP are using the description field not the subject field.
Include both in the page if given and don't fail if the key is missing.

(imported from commit 4351e5656d4ea025a03c07c8bb3bb5d406ef2d3d)
2015-02-08 21:30:19 -08:00
Jason Michalski
15713964a5 Add the notification-bot to the cross realm PM whitelist
(imported from commit 92a19f955a99650c79b83c6afb23726caf02e577)
2015-02-08 21:03:45 -08:00
Jason Michalski
a0a537e0ce Add the feedback bot to OG_ZULIPER_EMAILS
The feedback bot needs to be included in the OG_ZULIPER_EMAILS so users
can send feedback.

(imported from commit b0c3295379d0f062a912f8b6c957419335be1c48)
2015-02-08 10:08:32 -08:00
Jason Michalski
2c1ef7d89e Remove failing missed message test
We disabled missed messages for the zulip realm and this test was
failing.

(imported from commit c37d301ac98c38495ff16e95d773f3d6d700772d)
2015-02-07 18:16:12 -08:00
Jason Michalski
f4239d60ca Add pagerduty webhook
(imported from commit 06219066b423f53d08094f3f97a98016e145b2a7)
2015-02-07 18:16:11 -08:00
Jason Michalski
53b02a694a Update the review script to use @dropbox.com
(imported from commit 30c8c516d0542c1319cb2faf5a9da8e9c8b26041)
2015-01-30 23:39:47 -08:00
Jason Michalski
1eebcb472d Only allow users in the OG zuliper list to send cross realm PMs
Changes from allowing all of the zulip realms to a whitelist of users.

(imported from commit 5ad2db9a62b430ef2c9d867e4afdf661b11ae96a)
2015-01-30 23:39:47 -08:00
Zev Benjamin
2c760ae735 Remove mixpanel
(imported from commit 9b6cc58ee9be483db8bf2d2eaaaecabc14f821e4)
2015-02-06 13:59:30 -08:00
Luke Faraone
a901677be1 Use a unicode string when grabbing SSO unames
(imported from commit 5742147003928e2207d9eac8704aa6090fb8cb8a)
2015-02-06 09:56:39 -08:00
Jason Michalski
6ba5271824 Fix the SSO path to support mirror dummies
The SSO flow which was never used on a realm with mirror dummies before.
Also change the redirect to stay on the same doain.

(imported from commit 0f1b8a8fcef82ae6eaa5a264686f98d62a683fac)
2015-01-30 20:07:13 -08:00
Zev Benjamin
517703ab47 Update default api/site URLs to prod
(imported from commit bcd32a0e8f197abd728616d1b0ae1c78a6639e68)
2015-02-05 22:46:31 -08:00
Zev Benjamin
b9baf049e6 Send deployment zulips to prod
(imported from commit 8f75e028ead3016093ff7f8eacdebf05dc0687f5)
2015-02-05 22:46:30 -08:00
Zev Benjamin
8ecb555a98 Update log2zulip bot config
(imported from commit c25802d55cd50c1a81050466d9a59a29501aca87)
2015-02-05 22:46:30 -08:00
Zev Benjamin
db0cec8d70 Update Trac bot config
(imported from commit 07e976637882030faedbf2e34448404e7e1de379)
2015-02-05 22:46:30 -08:00
Zev Benjamin
83dafb662a Update Git bot config
(imported from commit 8c189e199178efd8aa054d9762cb26330ab4ae86)
2015-02-05 22:46:30 -08:00
Zev Benjamin
3c76c3fe54 Update Nagio's zuliprc
(imported from commit ac06b7cf41b1c0353c2096c4b9befae432fd7c5b)
2015-02-05 22:46:30 -08:00
Zev Benjamin
fc828ed116 Update review script
(imported from commit f8902233a29dcde900218fc7a62735024eb67974)
2015-02-05 22:46:30 -08:00
Zev Benjamin
9738f2fa17 Send feedback to prod
(imported from commit 52c76dfb6f8b8e49d1a9e799852a1683e85673c6)
2015-02-05 22:46:30 -08:00
Jason Michalski
a3de75bf8b Update redirect to stage copy
(imported from commit 995a147de57752aa5e8321ea0c580975147d15d1)
2015-02-06 01:09:16 -05:00
Luke Faraone
d3ebfbd042 Redirect c.d.n users to google auth
(imported from commit 72d6d486593155e346e7e856149fca3712868d89)
2015-02-05 21:40:23 -08:00
Jason Michalski
bb9ced6e57 Redirect users on the dropbox realm from stage to prod
This commit should only be pushed to stage after c290b630e has been
pushed to prod otherwise it will create a redirect loop.

(imported from commit 408407b845ded596705b1abd8ad13c0aedf6d732)
2015-02-06 00:07:06 -05:00
Jason Michalski
7b82db214c Update the last SSO redirect to use the host header as well
(imported from commit 4392543d5ea4fd4c29c221338e8c5f7919e40b7c)
2015-02-05 23:49:33 -05:00
Jason Michalski
01d018ba31 Change the other use of EXTERNAL_HOST in the oauth2 flow
(imported from commit ff92fcbb43ee19bb2b1520e68c5f6768649246f5)
2015-02-05 23:32:59 -05:00
Jason Michalski
35d22949ed Build the oauth redirect url with the host from the request
(imported from commit 972fed686b556bc8845cf7ae5bca555dc9cbeb13)
2015-02-05 23:14:04 -05:00
Jason Michalski
7e9c121ad3 Use the full_name if available
We were trying to default the users first name when using google auth,
but it was getting lost when rendering the form.

(imported from commit 710e0c2ce591488920458dca74209c75e7031abd)
2015-02-05 21:54:28 -05:00
Jason Michalski
439b86fe3b Migrate the google SSO from openid to oauth2
(imported from commit 6938c1cc5d245cc5642043279470365ff04df903)
2015-02-05 21:54:28 -05:00
Jason Michalski
3f68c56554 Disable password auth for dropbox
This change disabled password auth, but the UI still shows the login
form. I will remove that once we have the new hostname.

(imported from commit 6ca119571854ac54645680b40255e346be1c1613)
2015-02-05 21:47:59 -05:00
Jason Michalski
b3461ac3b5 Skip a failing dropbox test
The url format changed so this dropbox bugdown test is now failing.

(imported from commit cdd770b05d16ce3cb47aa93ba134227a5f82349c)
2015-02-05 21:47:59 -05:00
Tim Abbott
4f1388706c Disable digests and Missed Message notifications for internal realm.
(imported from commit 24a25bcf6653c674ac8a34324a4674e438f0af38)
2015-02-05 18:40:13 -08:00
Tim Abbott
1dbe00f164 Clean up indentation in do_send_messagemessage_events.
(imported from commit 010f0087693b1cf56bff380737e0070f476ca61a)
2015-02-05 18:40:13 -08:00
Luke Faraone
e241e6e833 [manual] Support chat.dropboxer.net hostname.
This needs to be deployed on both prod and lb0 to be functional

DEPLOY INSTRUCTIONS: restart carefully

(imported from commit d97a450754608357418c80e5b3c7b3bbcd1d09fb)
2015-02-05 17:55:29 -08:00
Luke Faraone
acccd2d5be [manual] Cert for chat.dropboxer.net from Tom Cook.
DEPLOY INSTRUCTIONS: Copy the cert over and restart carefully.

(imported from commit e7d96b231a70de89d3d8c5641df70354e7b7319d)
2015-02-05 17:55:23 -08:00
Luke Faraone
e8f63e2041 [manual] external-content now shares www IP
This is safe because we have the wildcard-all cert.

DEPLOY INSTRUCTIONS: Change the CNAME in R53 for external-content.zulipcdn.net
to the same as www.zulip.com

(imported from commit 075984943ce3a3b17518b913ea650992e45f705e)
2015-02-05 17:49:35 -08:00
Luke Faraone
8a8356221e puppet: remove dbx.zulip.com -- HW project
(imported from commit 6edc3f1af44969427b2a12bee1983367855b4b88)
2015-02-05 17:48:47 -08:00
Luke Faraone
0f27554423 puppet: TLS cipher changes
This has been live on lb0 for a few months.

(imported from commit 32688aa82a891dd34ca1e7fbcdd84f18b25880c6)
2015-02-05 17:19:51 -08:00
Leo Franchi
a5063cf046 Dropbox domain is zulip.com
(imported from commit 73e9196783eaba7c62f5668e373bb1b5d372663e)
2015-02-05 15:30:08 -08:00
Jason Michalski
693857a1f8 Flip the prod to stage redirect for the armooo@dropbox.com
This change will redirect armooo@dropbox.com from stage to prod. It also
removes the prod to stage redirect for all users. This will be rolled
out in two commits to prevent a redirect loop.

(imported from commit c290b630e746f757429b8bbdadbe7768367a5e33)
2015-02-05 17:19:14 -05:00
Tim Abbott
eb1631f78d Set session cookie domain for *.e.zulip.com hostnames.
(imported from commit 42b15de3b4576341304041588ffaceac6f40baaf)
2015-01-15 21:09:52 -08:00
Tim Abbott
7e786d5426 Import default session middleware as start for custom session middleware.
(imported from commit 76aae367ab6ea5c2a7b0d98368482a3cb312b217)
2015-01-15 21:09:52 -08:00
Jacob Hurwitz
d401d1cb47 Fix the scrolldown bug (T27850)
(imported from commit 4ae017908b9cc37231ba201c058a6630ceed908f)
2015-01-15 15:26:25 -08:00
Tim Abbott
87d1809657 Send digest emails 3 hours later now that we're on the west coast.
(imported from commit c7d5d0b30ac21314518132b5cf7dd9d7b2780f99)
2015-01-12 22:18:49 -08:00
Luke Faraone
f2e7f4cb67 Revert "Exclude dormant users from the buddy list."
Resolves a AmbiguousTimeError.

Approved by Leo.

This reverts commit ebfaeb97ffda22b618be7a9206877f9d2ec53404.

(imported from commit 42b29c6c57eb954952a740bc89611031cef1834a)
2014-12-16 22:56:45 -08:00
Zev Benjamin
f63ee86730 Fix login popup on cross-realm authenticated content previews
We were serving 401s on /user_uploads when the user wasn't authenticated (due to
it being a REST endpoint).  This was causing a login popup to display instead of
just a broken image preview.

(imported from commit 62640f5bd59eb3b86ab5aae5923ccfa742459805)
2014-10-29 17:53:05 -07:00
Jason Michalski
9c4764fe68 Set the read flag on a message in unread.mark_messages_as_read
I could not find where we were setting the read flag on messages in
response to a update_message_flags event. This fixes a bug where a
user's read position will not be correctly synced in muted streams. For
muted streams the cursor updates seem to force the client to mark the
messages as read.

(imported from commit e7e392be4c8cbf6f734abfa7fee748b07fd495bb)
2014-10-15 03:16:13 -04:00
Steve Howell
187469ea86 Exclude dormant users from the buddy list.
You must have accessed Zulip in the last 45 days to show up
on the list.

(imported from commit ebfaeb97ffda22b618be7a9206877f9d2ec53404)
2014-10-06 15:27:56 -07:00
Jason Michalski
50c43b45ee Allow mirror dummy users to register with google auth
Mirror dummy users should not be found during login to allow
registration.

(imported from commit d8cc4c97438193d7bb13d065705e2202ba96591c)
2014-10-06 15:27:56 -07:00
Steve Howell
6b1adf11f7 Disable stream desktop notifications for new Dropbox users.
(imported from commit 42deed48a2d475912041829a700fea4217868e9e)
2014-10-06 15:27:55 -07:00
Luke Faraone
b2688bcf43 Add dbx to nginx config
(imported from commit 48f633eb1f4e949cfdb3ededc78bb774163fde19)
2014-10-06 15:27:55 -07:00
Luke Faraone
fe0a1c2643 Add dbx.zulip.net to post-receive
(imported from commit 824f664f4622e0096b9a6004006a02903ac869e1)
2014-10-06 15:27:55 -07:00
Luke Faraone
0ca76e8cd8 install-server: don't fail if ~root/.ssh already exists
New AMIs install an authorized_keys file that rejects user login.

(imported from commit ad64d0a92e38319b705225a599edfd31a6ba037b)
2014-10-06 15:27:55 -07:00
Luke Faraone
d515f92d20 CORS headers for hack week API access
This has been live on staging for a while.

(imported from commit bd8b7ef500887fefc10656121fde389dca2aa217)
2014-10-06 15:27:55 -07:00
Jason Michalski
2a5826242d Add the hipchat bot to the list of API_SUPER_USERS
This is a public mirroring bot that needs to be able to send forged
messages to a stream.

(imported from commit 3fa691b1f1d06bf68a8cbc2c31ed5e3e5efef177)
2014-10-06 15:27:55 -07:00
Jason Michalski
718a6ea697 Fix the message count in missed message email
Missed message email were including the context messages in the number
of messages you were mentioned in.

(imported from commit 1749c5d272d2e17d6e28456ace932f80715103a3)
2014-10-06 15:27:54 -07:00
Jason Michalski
a2c1fca488 Fix a dropbox preview test
Dropbox changed the format of the preview image URLs

(imported from commit a4f5690155e98c526142462ad80f8b5cb4ee21a4)
2014-10-06 15:27:54 -07:00
Jason Michalski
30e4729254 Raise the queue depth limits for missedmessage_emails
(imported from commit 73a0da21930d9bc121e07c811483311ec171fe7b)
2014-10-06 15:27:54 -07:00
Jason Michalski
23ef278d29 Allow replying to missed PM emails on the zulip.com realm
* Fixes a few bugs with missed message address for PMs and huddles.
* Uses missed message address for all missed message reply-to headers on
  the zulip.com realm.

(imported from commit 61dd09386e1bbdf9a5096e2400984d31e73a5b74)
2014-10-06 15:27:54 -07:00
Jason Michalski
0726ec5931 Fix a bug when uses_left starts out larger than 1
(imported from commit cc08b63912c3188eeddbeee7ae73ae73143ec6ab)
2014-10-06 15:27:54 -07:00
Jason Michalski
0bc2f43e32 Add a new postfix virtual address for missed message emails
The one time use email addresses are prefixed with mm and need be sent
to the local zulip user to be picked up by the email mirror.

(imported from commit e17cfe6855ab7886f25ded52790b8f31df955ef2)
2014-10-06 15:27:54 -07:00
Jason Michalski
2a5ec20295 Add support for one time use email address
The one time use address are a unique token which maps to stored stated
in redis. We store the user_id, recipient_id, and subject. When an email
is received at this address it is sent to the stored recipient by the
stored user. Anyone with this address can send a single message as this
user.

(imported from commit 4219417bdc30c033a6cf7a0c7c0939f7d0308144)
2014-10-06 15:27:54 -07:00
Jason Michalski
52944622f8 Split missed message emails by recipient
Send a different missed message email for each recipient. This allows us
to set a different reply to address for each one. PMs and huddles use
the existing logic, replies will be sent to all parties via email.
Missed @-mention emails will have the reply to address set to the
stream's email address.

(imported from commit bfb7cf7c1382adbf3720caa74cbb927c10dea267)
2014-10-06 15:27:53 -07:00
Zev Benjamin
7411ce9092 Fix Github webhook exclude_* options.
We were expecting Github to send us the string "true" when the exclude_* options
were set.  However, we were actually getting "1" when an option was set and the
empty string when unset.  So we were always setting the options to False.

(imported from commit 067ba60b0b0404aebc6eda9487b1201fc2764243)
2014-10-06 15:27:53 -07:00
Waseem Daher
569abda653 Host "preview failed" image locally.
Who knows when this Cloudfront URL will stop working!

(imported from commit 39f2908a32c0276b1d87ecedc876c71dd35a9b2f)
2014-07-29 21:46:35 -07:00
Paul Ruan
12cb8ceae0 Time out when waiting for OpenGraph links that take too long.
One common place that this happens (for us) is on a local
Dropbox .dev.corp.dropbox.com instance, which can't be reached
by the Zulip servers.

This commit also:
* Fixes the test suite
* Properly previews /photos/ links

(imported from commit b4788b6236e7a9d390e1efc4673be34d9ba5e091)
2014-07-29 21:46:35 -07:00
Waseem Daher
752ff34f8f Whitelist Zulipers that can use the dropbox.com realm on prod.
And make this impossible to do in the Desktop app.

(imported from commit 2caa1b05256a3a55fe1b98d44e7dea5ed2dac86f)
2014-07-29 21:46:35 -07:00
Jason Michalski
748fb9afe5 Add avatar_url to v1/users
(imported from commit c89b85e1826dc3fbfdd65ec0529dd364b5e463d5)
2014-07-29 21:46:35 -07:00
Jason Michalski
94ec1f3741 Better previews for dropbox shmodel.
Getting previews for docs using open-graph protocol images.

(imported from commit 11a9b446eeb5786fdbf536681a100f43ad6db978)
2014-07-29 21:46:34 -07:00
Waseem Daher
6ff3070c8e Fix test related to bots form.
After I reverted the change to the bot stetings page, this
broke a test. This commit fixes that.

(imported from commit 394b29fea4f75096f7cb8d819145a9adc386276b)
2014-07-29 21:46:34 -07:00
Jason Michalski
e4db196032 Add an options to set jabber server details
--jabber-server-address=JABBER_SERVER_ADDRESS
                    The hostname of your Jabber server
--jabber-server-port=JABBER_SERVER_PORT
                    The port of your Jabber server

(imported from commit f6b73ce6a2e3dcdbb100a1b6aba5ad89fc99a457)
2014-07-29 21:46:34 -07:00
Jason Michalski
6b13f4a3c9 Update message events to include is_mirror_dummy
This can be used by mirroring scripts to only forward messages to users
who do not zulip accounts.

(imported from commit 200d6bcaaf39238bfb01480a9e906d567d4d9e11)
2014-07-29 21:46:34 -07:00
Luke Faraone
5147b52267 Return correct OPTIONS in rest_dispatch
(imported from commit 095175cad4df982d2bf5603f3b927a3aa6d7f41f)
2014-07-29 21:46:34 -07:00
Waseem Daher
a54d50ab2d Initial steps towards whitelabeling new realms.
Truthfully, the actual way to do this is going to be a bit
more involved and also involves changing Realm.NOTIFICATION_STREAM_NAME,
probably on a realm-by-realm basis.

(imported from commit b6a05849d215e07ee6716d116ff5e2c819d5b4be)
2014-07-29 21:46:34 -07:00
Waseem Daher
47873c181b Unbreak 'email hint' tooltip.
Streams no longer have ids, they have stream_ids.

(imported from commit 5080b8452711a1975d4a5bc7e647d8ef2528395b)
2014-07-29 21:46:33 -07:00
Waseem Daher
c90b76444d More whitelabeling stragglers.
Most notably:
* Tutorial
* Some Handlebars templates
* Some modals

(imported from commit b9fb92fa2f0f78d1efbd8f7fcd280fa5652059a8)
2014-07-29 21:46:33 -07:00
Waseem Daher
307d367346 Initial support for white-labeling Zulip as "Dropbox Chat" or otherwise.
Known issues:
* No support for whitelabeling in the email
* No whitelabeling for any externally-visible branding

(imported from commit 9eab7b0744e56a87007b8621a8bb18bbb1080256)
2014-07-29 21:46:33 -07:00
Jason Michalski
710a802f49 Add context to at mention missed messages
When you are at mentioned in a stream we will now send you up to the
last five messages which were sent in the past 5 minutes on the same
topic and stream.

(imported from commit 6df6c1cf868722a7bf76e54710e38741a7ac8f31)
2014-07-15 20:21:28 -07:00
Waseem Daher
6c424e8446 Reenable Dropbox integration on Staging.
(imported from commit 3f76b795046ee08d8d5226eb104701dc6765ebc0)
2014-07-14 14:24:04 -07:00
Waseem Daher
70ac98b860 Disable new bot UI, for now.
(imported from commit a5352f3dffd064fcd28b7029006a58db72ab686e)
2014-07-14 14:22:18 -07:00
Jason Michalski
58429a617b Do not save state when reloading due to an expired event queue
When an event queue expires the client is in an unknown state and trying
to restore state during a reload will keep the incorrect state.

(imported from commit e0828626142029aecd86a7c4cec8c77d261eb3eb)
2014-07-04 04:44:09 -07:00
Waseem Daher
203c04fdb8 More forcefully redirect Zulip users to staging.
(imported from commit e9ed69008c198da6f5af74a85e0af73f3f49bb6f)
2014-07-08 22:29:24 -07:00
Jason Michalski
0ea54a043e Use settings.EXTERNAL_HOST when sending activation emails
Activation emails were using django's sites framework which always has
the domain set to zulip.com.

(imported from commit b81eae96e1a75b64dd93970760b869f3271ce88c)
2014-07-03 12:28:29 -04:00
Tim Abbott
6ac6fd5e56 Remove requirement that local_id by a float in local echo.
(imported from commit c3de78760c1c7e11c6791719420b59df604d5319)
2014-06-25 11:44:16 -07:00
acrefoot
f62b9a199c fix typo in rules.v4 for iptables
(imported from commit 198259fec740c9e025ed56fd6e0b5d42f8d4323c)
2014-06-10 23:29:10 -07:00
Allen Rabinovich
3cf0d40436 Fix the overflow issues on status messages
(imported from commit 1b204bd95d80f1752b7df889b1a7e436360f144a)
2014-06-10 14:35:05 -06:00
acrefoot
27217fddb3 make bootstrap inline-code preserve whitespace
(imported from commit be7d45663b3a9ecd40968cae5d0fb6c734a05212)
2014-06-10 13:18:02 -07:00
Luke Faraone
5507575b7e Switch install scripts to use apt.zulip.net for ops systems
(imported from commit 3ff243459237ac673c5e8ae23077e628fa07a6b9)
2014-06-10 13:16:27 -07:00
acrefoot
0b9884ce5b add issues traffic to the CUSTOMER17 stream
The default today is to not have issues traffic except on a whitelist. This is despite the fact that we have
an exclude_issues boolean on Github's Zulip-integration page, since if we changed the default, all realms
currently using this default would have to go make this change on every repo. That's something that would require
some work, in terms of communicating with them about this, and logging integrations settings for all realms, to
see which are correctly setting exclude issues. Unfortunately this probably isn't high priority today, but let's
try to get this whitelist change out to prod ASAP.

(imported from commit 256fe32bb6aaf7de18ff02d8d7e204a13bc02b7a)
2014-06-09 08:30:10 -07:00
Zev Benjamin
23c108a05c nagios: Check HTTPS instead of HTTP
(imported from commit ba0bb76d9bea6661e5396308eb431ff95ef51771)
2014-06-05 17:30:15 -07:00
Jason Michalski
cb153967ec Fix notifications on chrome
Chrome has removed the webkitNotifications API and not only has the w3c
web notifications API. This adds a shim when webkitNotifications is
missing but Notification is present.

(imported from commit e21c476f9ae6570c297c88bd6ff90a97818688e6)
2014-05-28 20:11:16 -07:00
Jason Michalski
8c72eddb72 Add a warning when in the zulip.com realm on production
Display a red warning box to get users to direct users to staging for
the zulip.com (dropbox) realm.

(imported from commit 01ad4209d9247406bc82f5dedaf21371101a1d84)
2014-05-21 13:13:27 -07:00
Zev Benjamin
298e008cc2 [manual] Turn off GIN fast update for zephyr_message_search_tsvector
Apply this commit after hours!

To apply this commit, first run the migration and then run the following as the
zulip user on staging:

$ echo 'VACUUM zerver_message' | python manage.py dbshell

The above VACUUM is needed to clean out the existing fast update pending list.
It might take a long time and block new message inserts!

See discussion near Zulip message 18377486 for why we're turning off the fast
update mechanism for zephyr_message_search_tsvector.

The high level overview is:
As a consequence of the high work_mem setting on our postgres server, the
fastupdate pending list for zephyr_message_search_tsvector can grow very large.
This leads to the occasional INSERT or UPDATE taking inordinately long (many
minutes) as the pending list is flushed, blocking other inserts.

One other possible solution for preventing the list from growing too large is to
set the autovacuum storage parameters on the table such that the autovacuum
process will run after a reasonable number of INSERTs or UPDATEs.  However, the
table is mostly INSERT-only.  Therefore, only the autovacuum_analyze_*
parameters will actually do anything to affect when the autovacuumer will run,
but when it does, it will do a VACUUM ANALYZE instead of a plain VACUUM.  We
don't particularly need the table to be re-analyzed that often.

Turning off fast update will eventually cause the index to become less
efficient, but we can always rebuild it later if we notice it starting to get
too slow.

(imported from commit f280c193c3bc0a3f312960510c5a7dcf97f30c3d)
2014-05-20 22:38:48 -07:00
Zev Benjamin
8e9c019b35 Update user_root path for personal zmirrors
The location of the api directory moved.

(imported from commit 408ef7d47e729a0ad2454a5326cfaddcfff9855f)
2014-05-20 17:29:29 -07:00
Zev Benjamin
4e1d86f775 Handle platform.system() throwing an IOError
This can happen if the calling process is handling SIGCHLD.  See
http://bugs.python.org/issue9127

We ran into this in the zephyr_mirror.

(imported from commit 80fade2274714b7c2c4b9fe38c66a1db8cc63234)
2014-05-20 17:29:29 -07:00
Zev Benjamin
b5f7ed037c zephyr_mirror: Specify a z_charset of utf-8
andersk reports that we are "incorrectly sending outgoing zephyrs with z_charset
= ZCHARSET_ISO_8859_1, which breaks zwgc (other clients tend to ignore
z_charset). I'm assuming you're shelling out to zwrite; you need to use zwrite
-x UTF-8, or export LC_ALL=en_US.UTF-8."

(imported from commit 8abb28bf8acbe0b5aa99ca13faab24e1e554a031)
2014-05-20 17:29:29 -07:00
Luke Faraone
b383884019 Change expected autossh processes to 10
(imported from commit 41b06ce3f7cded7a29101a6de2d471bdffab5bcc)
2014-05-15 10:49:54 -07:00
Leo Franchi
e4dbe57c10 Fix Google OAuth login by checking True as well as true in oauth response
(imported from commit c80620eca4dbd9b5b0122e8e564bc7257a2bd4f5)
2014-05-14 10:00:03 -07:00
Waseem Daher
ffc75cb074 A script to export an entire stream.
(imported from commit 7c8bc0c0c1f9c987bda9503ca53051d2e4ad27dd)
2014-05-13 22:42:42 -07:00
Tolga Tezel
667a3a06cd gitignore *.DS_Store instead of .DS_Store
(imported from commit c22b8c9d786c5e35bc10f6db8cf6e8ffa4d357ad)
2014-05-07 14:06:59 -07:00
Tolga Tezel
410e557bad fix old messages tests to use dynamic sql queries - ids were hardcoded.
(imported from commit 533872f5bebc1068925591c9381463a7c9317482)
2014-05-07 14:06:59 -07:00
Tolga Tezel
8b1199ee35 Add support for creating users with a specific ID.
(imported from commit 9a3438924cab8477a9c2494af1b5c2d32783e71c)
2014-05-07 14:06:59 -07:00
acrefoot
148959f1b7 Rewrite humbug-user-uploads.s3.amazonaws.com urls
add_messages is a good entrypoint for this, since it gets called by:
1) get_old_messages
2) get_events_success (for new messages, via insert_new_messages)

which is all the places that rewrites should happen, but nowhere
where extra work is being done.

(imported from commit 844c33bc32d35aa39c9cdacf42eb7e8ddf5ae63c)
2014-05-05 22:21:19 -07:00
Luke Faraone
8f8b2519ea Redirect legacy URLs to their new secure location.
URLs with a realm of "unk" will be queried against the new bucket to
determine the relevant realm of the uploading user.

(imported from commit 5d39801951face3cc33c46a61246ba434862a808)
2014-05-05 20:26:29 -07:00
Luke Faraone
ef8b6e5a42 New certificates from Dropbox.
Thanks Tom Cook for getting these through Digicert!

We no longer need separate wildcard certificates, etc, because we have SAN star
certs.

(imported from commit 40a8961da51b6a0ae90c68b40b2af6d59cb5cf9f)
2014-05-05 18:24:14 -07:00
Tim Abbott
8b74a3e052 Remove unauthenticated file upload support from Zulip.
(imported from commit 97262590ac5ad56c18f415fa1c777510aed2baeb)
2014-05-05 16:14:09 -07:00
Tim Abbott
f7535a0a1b Fix traceback sending bot messages to invite-only stream.
(imported from commit b9af67e87d8b7d52bddb8fa576af8fe9326ba13c)
2014-05-02 15:49:50 -07:00
Jason Michalski
d2d9d9cb01 Fix references to local_id and failed_request
Both missed in the refactoring that split global messages and
message_list_view message_containers.

(imported from commit 127d09204a9e363b78eccfe3d72212e78beb2600)
2014-04-30 16:03:38 -04:00
Tim Abbott
ddbb3a37fb Allow committing with dropbox.com email addresses.
Later we can remove the ability to commit with older emails.

(imported from commit fe44cc1ffcc79f3c393e3a84c15741130605d3ec)
2014-04-29 10:55:12 -07:00
Jason Michalski
672603d6cd Add missing logger
(imported from commit e27d78f04fb8cb60b0cbdf4a544a047265abf9d5)
2014-04-28 19:51:04 -04:00
Jason Michalski
1a47683d32 Change data to attr in inline subscribe buttons
(imported from commit 72fef9dd3cb58ff15e74709b0470033a7f8796b4)
2014-04-28 19:43:47 -04:00
Tim Abbott
0494e40c39 Merge zerver/tornado_callbacks.py into zerver/lib/event_queue.py.
It had stopped being a coherently distinct component a while ago.

(imported from commit 0617957bcfe8dcaf69143c88a96ddd51ecb31a98)
2014-04-23 17:22:31 -07:00
Zev Benjamin
5219851de4 zephyr_mirror: Use timeout_success_equivalent in front-end script
(imported from commit 2263a371edda74c1c38a377e0fef5372999888b4)
2014-04-23 11:31:04 -07:00
Zev Benjamin
6d43b22ebe jabber_mirror: Use timeout_success_equivalent in front-end script
(imported from commit 6ca8ec5a2c31d20e4e437804c65650c5a98c69f9)
2014-04-23 11:31:04 -07:00
Zev Benjamin
1e7994d97d api: Add an option to backoff classes for making the passage of time count as a success
The idea here is that for usages like in the zephyr mirror bot:

  backoff = RandomExponentialBackoff()
  while backoff.keep_going():
      print "Starting zephyr mirroring bot"
      try:
          subprocess.call(args)
      except:
          traceback.print_exc()
      backoff.fail()

we want it to be the case that the mirror bot running for a while counts as a
success so that the bot doesn't have a finite number of crashes over its entire
lifetime.  We only want the mirror bot to stop retrying if it fails too many
times in a row.

(imported from commit 7b10704d3ce9a5ffb3472cbb4dfa168c9c05ae7a)
2014-04-23 11:31:04 -07:00
Zev Benjamin
a9e439d9e0 jabber_mirror: Explicitly exit when we encounter an error in the main loop
(imported from commit 19b0f29bfd8c01fa300bdb9db2011bba0b55ddd4)
2014-04-23 11:31:04 -07:00
Zev Benjamin
0224fe2db6 jabber_mirror: Don't try to restart on errors caused by initial configuration
(imported from commit 5d9e6c88e1a159fe6e5e46c21c483b5c79444223)
2014-04-23 11:31:03 -07:00
Zev Benjamin
7053fd2a24 jabber_mirror: Split out into front-end and back-end processes
This adds auto-restarting capability.

(imported from commit 74a01a0272025706f2eb902eeedd9c05ee054272)
2014-04-23 11:31:03 -07:00
Zev Benjamin
7ed182c08f Move backoff classes to the Zulip API
(imported from commit 76c5d499874f0397c505ab3fcda631a1a46847b6)
2014-04-23 11:31:03 -07:00
Jason Michalski
768b3b5011 [notify customer Z899] Collapse messages in the home view when narrowed
Collapsing a message in a narrow should also collapse that message in the
home view. Previously this would only happed with the message was
rerendered.

(imported from commit fa82888eba51eb2f4f2b93521d4b7daee852898d)
2014-04-18 18:51:14 -04:00
Zev Benjamin
b190a24f40 puppet: Convert zmirror2 to use apt module for debathena sources
(imported from commit 67c71e15b5e5cbdffaa12953eaa7c0c72e7b107a)
2014-04-17 17:12:36 -07:00
Zev Benjamin
08a6969f48 puppet: Fix zmirror apt source resource
The resource is called "apt::source", not "apt::sources_list"

(imported from commit 5ace3d9a62e361b3c7f0b54bf69ac91c1136bb6d)
2014-04-17 17:12:36 -07:00
Zev Benjamin
50b763b12b puppet: Make iptables rules a puppet template
This allows us to specify different rules for the zmirror machines, which need
ports open for Zephyr.

(imported from commit f3c061e9492cbb99783f156debccf03161347e47)
2014-04-17 17:12:36 -07:00
Allen Rabinovich
0b44b7eb4c Switch to a Zulip+Dropbox logo in the header
(imported from commit bbd36b362f4480c83455981fce1c05faca5acabe)
2014-04-16 22:24:35 -07:00
Allen Rabinovich
2fbb13be0a Switch from hiding overflow-y to hiding overflow
(imported from commit 5d595c030b1098165965dd3c693371f7521cf26f)
2014-04-15 12:18:31 -06:00
Tim Abbott
52424cd67a Improve Zephyr personal mirror Nagios check.
(imported from commit 713f8f1ff1463537b46d493ac3571c2727d85379)
2014-04-11 16:44:13 -07:00
Zev Benjamin
caef3f8bf3 [puppet] Allow Zulip to be loaded in an iframe on all domains
This removes "X-Frame-Options DENY" from our nginx config.  We need to be able
to load Zulip in an iframe for embedding and we decided that it doesn't actually
provide much protection.

(imported from commit 5bc363693db949010f6163cb3000c12229618a83)
2014-04-07 14:42:02 -07:00
Zev Benjamin
3498a04613 Call authenticate() when logging users in via JWT
Otherwise the user_profile.backend attribute doesn't get set.  I didn't notice
this previously because on first register authenticate() gets called, and then
the UserProfile object gets cached.  This means that subsequent logins work just
fine as long as the UserProfile object is in memcached.

(imported from commit 834d95c46aa07724ea84802f09b7249de99b5ca8)
2014-04-07 11:01:38 -07:00
Zev Benjamin
5b080bd0cf Fix one name_changes_disabled check
(imported from commit f1bf125949bd282c8a9054d3e3b2e92c7bd5ab4e)
2014-04-06 17:00:28 -07:00
Zev Benjamin
2f7af69091 Add customizations for CUSTOMER16 employees' realm
CUSTOMER16 wants their employee realm to:
* only use JWT logins
* have name changes be disabled (they want users' full names to be the
  their CUSTOMER16 user name).
* not show the suggestion that users download the desktop app

(imported from commit cb5f72c993ddc26132ce50165bb68c3000276de0)
2014-04-04 16:51:32 -07:00
Zev Benjamin
bd3f1c6a9e Add JSON web token (JWT) authentication
We currently expect the use of HMAC SHA-256, although there shouldn't be
anything preventing us from using other algorithms.

(imported from commit 354510a0b7e9e273d062a1ab5b2b03d4a749d6a3)
2014-04-04 16:51:32 -07:00
Zev Benjamin
bd20b295e1 [manual] Add python-pyjwt dependency
This will be used in the next commit.

(imported from commit 559fedd41fb731575ba7201dfbcef45d03461ef2)
2014-04-04 16:51:32 -07:00
Zev Benjamin
04f211bbff Refactor some of the remote user handling
(imported from commit 13facd7afddfb018af39b39ee48c644d355d8ec3)
2014-04-04 16:51:32 -07:00
Zev Benjamin
2e1d5ffd1c Make password_auth_enabled() take a realm object
This will actually be used in an upcoming commit.

(imported from commit 5d3db685a245899b2523440398f2ed2f0cfec4f4)
2014-04-04 16:51:32 -07:00
Zev Benjamin
2cfeef606c register.html: Don't try to focus the full_name field if it doesn't exist
(imported from commit f420d9075e5129582522e79f706c448f6c82f6aa)
2014-04-04 16:51:32 -07:00
Zev Benjamin
6759a78d07 Remove extraneous (and incorrect) realm lookup
(imported from commit 9c618c50b0f27795c91da172d5bc63dd5d5f2e61)
2014-04-04 16:51:31 -07:00
Zev Benjamin
3fc779278b Use EXTERNAL_URI_SCHEME instead of hard-coding 'https'
(imported from commit 3a4d2e0591debd7d5e4b5650b050a1eb1d86aa55)
2014-04-04 16:51:31 -07:00
Zev Benjamin
9114715030 Factor out the check for whether name changes are disabled
(imported from commit 56ddd9cf53ec49e2e096abe82ed44f758912272e)
2014-04-04 16:51:31 -07:00
Zev Benjamin
8518801601 Untabify app_frontend.pp
(imported from commit 2555cafa3bf3f9ef3551e4beab7ca2ad17ed05d4)
2014-04-04 16:51:31 -07:00
Jason Michalski
80db1b9feb Fix test to not depend on timezones
Use UTC milliseconds from epoch not string formated time in tests.

(imported from commit c1f23367fd9e4d9b11a8fd58efb8b4b4b6980552)
2014-04-01 20:57:06 -07:00
Allen Rabinovich
56789e55b4 An ultra-compact view for embedded cases
(imported from commit 3012702158a94627d13ffc03e2e60d02bdf667b7)
2014-03-31 19:05:22 -06:00
Jason Michalski
55e762b069 Fix bug with date separators when prepending messages
When the date changes between an existing group and a new group the
existing date separator needs to be updated. This is done by rerendering
the existing group.

(imported from commit a3775815e33872b0ec07704dc7ccf5fd2671fa21)
2014-03-29 22:00:00 -04:00
Leo Franchi
1e9efe441a Fold case in people.js' dicts
(imported from commit 971742d2a44d54bc2c8d493b034df7809b646b2f)
2014-03-20 11:33:39 -04:00
Jason Michalski
c147daa312 Firefox does not have an innerText so use textContent
textContent is supported on all browsers and IE 9+

(imported from commit ea13d58bf85b6ffb30fdbece20f9dbdcd6c32896)
2014-03-19 17:30:11 -04:00
Jason Michalski
94279c0522 is_me_message is an attribute of the message not the message_container
(imported from commit db36e529de92a82bb9c5df97030833ca2e3e0f80)
2014-03-19 11:43:32 -04:00
Jason Michalski
536449c6a4 Remove the extra zulip emoji autocomplete option
(imported from commit 69afbcafa8fda4de874d97f27c83476ee8c30dad)
2014-03-19 10:11:16 -04:00
Jason Michalski
456e735725 Fix autoscroll forever
(imported from commit 66cc2661767f54de54012b4abf930e748071585e)
2014-03-19 09:38:10 -04:00
Luke Faraone
0a1d142d69 Refer to correct settings variable in email_mirror.py
(imported from commit c4e8b9ef417d8ba3c4db9692f4720b1cc1dc17a0)
2014-03-18 23:37:19 -04:00
Jason Michalski
3158075405 Use the match data on the message not the message_container
(imported from commit 1289108c767732c76efc7369206ef065f2395e0d)
2014-03-18 18:24:23 -04:00
Jason Michalski
7bc98d1634 Update the message group fading to be message_container aware
update_rendered_message_groups needs to use the message not the
message_container when testing to see if the fade states need to be
updated.

(imported from commit b1c3baba07169a369d827c89afdc3c406ada0b79)
2014-03-18 16:13:04 -04:00
Jason Michalski
28245ce4e4 Mark messages as read globally
If you read a message in a narrow it should also be marked as read in
the main list.

(imported from commit e892fad0a5b635b5c8de6ebdc79fbfd2b54fab2b)
2014-03-18 16:03:25 -04:00
Jason Michalski
c3ded56a7e Do not try to rerender muted messages
(imported from commit 1430b204cd7d32ddcee273b142bcbc2d699caffb)
2014-03-18 15:46:32 -04:00
Jason Michalski
e60f76487f Rename message to message_container
Now that we are not directly using message in the message list view
rename the uses of message that are message_containers.

(imported from commit 5c355703a8934a74864f5de6ecb1e2fd851e5d41)
2014-03-18 15:05:39 -04:00
Jason Michalski
1613cad6f6 Separate the global message data from the list display data
The messages being passed to the handlebars templates were global
messages which we were adding per list details to, show name bar etc.
This causes rendering bugs when you try to rerender a message, because a
different list may have changed it. This commit moves the global message
data to a msg attribute on the message_container which will contain the
per list attributes.

(imported from commit 26b1f0d2c72d6288a6d3e7ed5f8692426f2a97ad)
2014-03-18 15:02:31 -04:00
Jason Michalski
c39e657a3b Do not try to incrementally update the DOM when it was cleared
When clear_table is called message_groups must also be cleared.
Otherwise render will try to incrementally update the DOM which will
fail when the expected existing nodes are not found.

(imported from commit 5ec3ce01717741b17c719fabded316619cdc4b25)
2014-03-18 13:20:29 -04:00
Jason Michalski
61c16a20b4 Only message rows should be post processed and added to the DOM
The handlebars template adds a text node with a newline after every
message. So we need to filter the jQuery object to include only the
message rows.

(imported from commit 07513b485e805570e450fb93c07091be89bcbd50)
2014-03-18 10:05:20 -04:00
Jason Michalski
35fe8bf81b _post_process_messages realy wants DOM nodes
(imported from commit c419248ff1f7a4338f503f6705dede32e195ed3b)
2014-03-17 22:31:25 -04:00
Luke Faraone
e6bb683922 Suppress presence changes to IDLE until timeout
This way if two browsers are disagreeing about your active status, the
active one wins. The active browser continues to update your timestamp,
and the idle browser's changes are discarded until the timestamp on your
active status expires.

(imported from commit dc29e013d045c4b72793097f611ba6802c58e57a)
2014-03-17 14:27:20 -04:00
Zev Benjamin
286bd3005d nagios: Disable idle transaction checks
We apparently still have some process that occationally sits idle in a
transaction for a while, which makes this alert super noisy.

(imported from commit 074b04ad746bac0da1b8714763538d1ce22da64e)
2014-03-17 14:17:43 -04:00
Jason Michalski
c38c9cf894 Me messages should always display the sender
(imported from commit af42ed8dcb9f4bc44e66d4973b9e613302647e12)
2014-03-16 15:14:57 -04:00
Jason Michalski
441688b41e jQuery object's get method returns an array
Passing anything other than an array of DOM elements to
_post_process_messages is an error. In this case we were passing an
array of arrays of DOM elements.

(imported from commit 9e3be18598c406f3578a867dab36731ffeeac921)
2014-03-15 23:46:27 -04:00
acrefoot
c69f1dae3f Prevent resize operations from trying to access the reply() tutorial after the tutorial has finished
I had to move a function to prevent linter errors

(imported from commit 7634bd7d29ca2d204d17566f166ce9d580aaac4b)
2014-03-14 20:49:00 -04:00
Steve Howell
e5467d3268 Move ui.js click handlers to click_handlers.js
(imported from commit adfeb1f152cca473bc4c6ba5ccd142b38947b335)
2014-03-14 20:48:59 -04:00
Jason Michalski
a9235a74f4 Split the group merging logic form the DOM update logic
The goal is to have a more data centric piece that can be unit tested.
We also try to minimise the number of one off jQuery DOM updates and
rerender handlebars fragments instead. This will prevent the
message_group and DOM from drifting apart and not being able to rerender
correctly.

(imported from commit 03f09803f2bc0c3b8187f76f2cfe90be9f7512a3)
2014-03-14 20:48:59 -04:00
Jason Michalski
4f6ee6744d Split out group creation from rendering
To make the rendering process a bit simpler to read this commit is
refactoring the message group creation into its own function.

(imported from commit b53ce96ed8fee3064d7cf891fc248d0c3d821d1a)
2014-03-14 20:48:59 -04:00
Steve Howell
16faed0a83 Create copy_and_paste.js (with code from ui.js).
(imported from commit 37a06af5489e7da5196e5710f384d1f5a7ee7578)
2014-03-14 20:48:59 -04:00
Jason Michalski
fa440d0be2 Only empty the message list DOM on reload
We are seeing error on CUSTOMER4 when clearing the DOM on reload. So
now we will only clear the message list.

(imported from commit f5d8d7d36cd1018f7def73ff9eda414387fcec5c)
2014-03-14 20:48:58 -04:00
Steve Howell
c5993c2d2d Create gear_menu.js (with code from ui.js).
(imported from commit fc4d058d49d5d4aaaa20ef6237ea3e927eac03e3)
2014-03-14 20:48:58 -04:00
Steve Howell
405c3d7626 Created floating_recipient_bar.js (with code from ui.js).
(imported from commit 2b6631938b0fc8e39c14aacd92f9f1670b68b199)
2014-03-14 20:48:58 -04:00
Steve Howell
f8b71fa497 Created condense.js (with code taken from ui.js).
(imported from commit 72b27b48614a7c396170d46936646e52757e2743)
2014-03-14 20:48:58 -04:00
Leo Franchi
af3411cab8 Handle removing the selected local message from the message list
(imported from commit 185fc33cc19699ebe61ce9d65262383e39289cf3)
2014-03-14 20:48:57 -04:00
Leo Franchi
9162ef3e0f Fix wrong logic in handling local-only message edit saves
(imported from commit a9074fbfb75884c3280807ddeba576c0fbe313b7)
2014-03-14 20:48:57 -04:00
Luke Faraone
bba2eb7622 Send missedmessage notifications as soon as you're idle or offline
Previously, you'd have to be offline to recieve missedmessage
notifications, or maybe idle for an hour. However, I'm pretty sure the
latter code didn't actually work, so we scrap that and just nofity you
via email or push as soon as you're idle.

Closes trac #2350

(imported from commit 899966e0514db575b9640a96865639201824b579)
2014-03-14 20:48:57 -04:00
Tim Abbott
5bb4a74ec0 Don't log warnings about various known-unsupported Pivotal event types.
(imported from commit e2044e06c02bc745608fe637ce44d683c5badcd8)
2014-03-14 20:48:57 -04:00
Tim Abbott
6850835273 Improve handling of unknown JIRA event types.
(imported from commit d9f823dc80b26a71f7b3a891559d2360d76a258f)
2014-03-14 20:48:56 -04:00
Tim Abbott
9aa3de0664 Fix GitHub tracebacks from issue['pull_request'] not existing.
(imported from commit f124a8e30e25d9321e9abe2fe04a5bd35ce24445)
2014-03-14 20:48:56 -04:00
Tim Abbott
400e355a2f Fix passing string as user_profile to upload_message_image.
(imported from commit b4841ef30527da6856482899d2e709cd528ff181)
2014-03-14 20:48:56 -04:00
Steve Howell
84b59d4335 Created scroll_bar.js (with code taken from ui.js).
(imported from commit 0c4e8538031ceb1a0f50eea9a34e315e23e7d9ff)
2014-03-14 20:48:56 -04:00
Steve Howell
be2a1c2893 Move resizing code to resize.js.
(imported from commit b6df0007307872751e1a4200af740076e08b5c11)
2014-03-14 20:48:55 -04:00
Leo Franchi
f760567b96 Fix topic edits that are initiated from the FRB.
Grab the id of the selected row, whether it's a message, recipient bar, or FRB

(imported from commit 93b9c282d4220ba9bb271733ded4d90d5c051c75)
2014-03-14 20:48:55 -04:00
Steve Howell
7fce920522 Move favicon-related functions to favicon.js
util.reset_favicon -> favicon.reset
util.set_favicon -> favicon.set

(imported from commit 250848ec5dc7ac58649197c8cc4b7b4e7b19f25c)
2014-03-14 20:48:55 -04:00
Steve Howell
77e7947f61 Add test_random_int()
(imported from commit 67ab9436463b3b4ff63f657fd8cd60cdd25f6047)
2014-03-14 20:48:55 -04:00
Steve Howell
23e791a3b9 Enhance test_array_compare().
(imported from commit c6d44acd2804005a41afe6b283e11905b7e4c7c0)
2014-03-14 20:48:54 -04:00
Steve Howell
a8d61fa930 Add test_normalize_recipients.
(imported from commit 9645cb471f8db01e810c9b6c396313ee4c1cf97f)
2014-03-14 20:48:54 -04:00
Steve Howell
d52e5e551d Remove {show,destroy}_first_run_message.
We essentially inlined the methods in the three places they
were called.

(imported from commit 622ee718d6dd226187f1e37ff754ee2fa635e6f2)
2014-03-14 20:48:54 -04:00
Steve Howell
84fc8f16dd Add test coverage for util.same_major_recipient.
(imported from commit 0b345679d2bf40c82167ded9968dd653823011bf)
2014-03-14 20:48:54 -04:00
Steve Howell
b12b44579c Set up $.fn.expectOne in setup.js
(imported from commit 77922cf8f506d4eb811498d418215eabf74b76ae)
2014-03-14 20:48:53 -04:00
Steve Howell
91e83731f0 Promote setup.js in the list of JS files.
I don't think this matters a ton, but there's no reason for
the two muting files to come before setup.js.

(imported from commit c18231b633fba6acccaf5bc180c7605f7591462e)
2014-03-14 20:48:53 -04:00
Steve Howell
3889edd824 Move xhr_error_message() into channel.js
(imported from commit c68c2d475b5673a3dd5f68c75624dfcfe56728ca)
2014-03-14 20:48:53 -04:00
Steve Howell
0e129614cf Remove unused util.recipient_key() function.
(imported from commit cee6a58344971ee1439e6b66ec301f1bd0f80502)
2014-03-14 20:48:53 -04:00
Steve Howell
50bc5401a4 Moved loading_indicator functions to loading.js.
util.make_loading_indicator -> loading.make_indicator
util.destroy_loading_indicator -> loading.destroy_indicator

(imported from commit 8a171622a6096476dd040912d3f1460d53159f20)
2014-03-14 20:48:52 -04:00
Waseem Daher
a1538b4bab Eliminate gap at bottom of portico pages.
(imported from commit 0e1d9bde16267f9b6533f256c28374ed98566578)
2014-03-14 20:48:52 -04:00
Waseem Daher
c09b6914ba Use new background image for /hello.
(imported from commit 06174760ee28a4c6b323f5c7e66cb20a50709d2a)
2014-03-14 20:48:52 -04:00
Waseem Daher
86ff8cdd8c Add San Francisco image to repository.
This is a public domain work.
Source: http://www.flickr.com/photos/allenr/13127238845/in/photostream/

(imported from commit 90f7e79131302a9da2323125ca27f78d5ac79a78)
2014-03-14 20:48:52 -04:00
Waseem Daher
9cefe46a1f Change /features icon color to match header.
(imported from commit d9cabd13acd8981a5bef93011ae4ea0c45cb451b)
2014-03-14 20:48:51 -04:00
Waseem Daher
202ac0fe10 Restyle /hello to be more consistent with current app style.
(imported from commit 7e1df8cb885908f40569692283e98ac851ca3d2e)
2014-03-14 20:48:51 -04:00
Waseem Daher
4eded59dbe Revert "signup: point to /register at the top too."
This reverts commit 517df29d10182c05780017c15225c9f95b844225.

(imported from commit 7820bb2dad7010579342450040d0f5c72ad2c627)
2014-03-14 20:48:51 -04:00
Leo Franchi
c832543168 Remove very confusing dom_id message attribute
(imported from commit c7e3e50bf8827f6f087d7df28ec7b7c173a3c041)
2014-03-14 20:48:51 -04:00
Leo Franchi
ef81999f3f Make sure to store raw DOM elements, not jQuery objects, in _rows
(imported from commit ccf85bfd514b5b143c1021d4a186f1448abc700d)
2014-03-14 20:48:50 -04:00
Allen Rabinovich
163d93c15b Move timestamp up when sender is included
(imported from commit a347b397a41028f3ca9642ad1edd704e3255245a)
2014-03-14 20:48:50 -04:00
Leo Franchi
6d2c6f269d Make sure to use the proper dom_id in the proper places
(imported from commit c4852f972d4fe8b2732c87dcc499f91f837e912c)
2014-03-14 20:48:50 -04:00
Leo Franchi
8f7542f34d Use elem.html() instead of elem.replaceWith() when swapping in new rendered messages
(imported from commit 82664bf2eb20faa8e98b7912b4c26174046d2dd6)
2014-03-14 20:48:50 -04:00
Leo Franchi
8b1f0223fe Update the dom_id of message objects when their id changes
(imported from commit e766eff7d966d95616ac192c8cb0cb328bd96b1b)
2014-03-14 20:48:50 -04:00
Leo Franchi
7f3ea34dc5 Make sure to re-select selected after re-ordering
(imported from commit 50878874372d1304014f5285b488db6ab896abbd)
2014-03-14 20:48:49 -04:00
Leo Franchi
26690adc47 Save the correct-from-dom rerendered message in _rows when rerendering
(imported from commit c021beef3106148a6d085ca16f34a1c4bb4fc7af)
2014-03-14 20:48:49 -04:00
Jessica McKellar
1c06e37245 [puppet] Change digest email send time by 1 hour for daylight savings.
(imported from commit 8ac1747f15e10b850f73ce28ea4579bee62ba1a4)
2014-03-14 20:48:49 -04:00
Leo Franchi
e7c8c322c0 Handle case where _lower_bound returns size of input list
(imported from commit bd91512615b11935eafd5809ca414eeb0cf189c4)
2014-03-14 20:48:49 -04:00
Jessica McKellar
fa1333c026 integrations: make Codebase dependency on python-dateutil explicit.
requests is already required generally by the API bindings.

(imported from commit 216c7031def710aac415cca755dbe2454514decb)
2014-03-14 20:48:48 -04:00
Jessica McKellar
fa461e86fd integrations: make Asana dependency on python-dateutil explicit.
(imported from commit 354b42f68e3d1f980649993bad4dbe4ff79a11d6)
2014-03-14 20:48:48 -04:00
Steve Howell
3dc9ee182f Add test for people.reify()
(imported from commit 3ad061ba52c1fd7fa2c2a053e91de87117370dd6)
2014-03-14 20:48:48 -04:00
Steve Howell
6ec72a290d Simplify condition for aborting people.reify().
Since it's basically impossible to add a person with an
undefined full_name--even "skeleton" people--there is no
need to check the full_name field to short circuit reify(),
because it will always be defined.

(imported from commit 3a30cfd583a040f7460739abea1604594c450ffe)
2014-03-14 20:48:47 -04:00
Steve Howell
cbb5878477 Test people.remove() only removes one person.
(imported from commit 7cd21cd9e4b99d0542bf81737a1c16a346ecc37e)
2014-03-14 20:48:47 -04:00
Leo Franchi
065fcf1a1b Handle out-of-order local ids in message_list
(imported from commit e805837d7d2790be90490cc9ec9415882ff9b549)
2014-03-14 20:48:47 -04:00
Leo Franchi
7cd814d92c Keep track of local ids in our message list
(imported from commit d96eaa14bf9f4b315d6893e6cd6c8d3c069c1d14)
2014-03-14 20:48:46 -04:00
Leo Franchi
86d310a984 Pass index of element to util.lower_bound matching function
(imported from commit eb8ba76b4855355bc23d6419cbb0f3a4aad8b6de)
2014-03-14 20:48:46 -04:00
Zev Benjamin
f7b64827e4 nagios: Don't check txn_time on trac
Doing so requires superuser privileges because check_postgres.pl only connects
to one database for that action.  We could theoretically work around this, but I
don't think it's worthwhile for non-production DBs.

(imported from commit 3ab06e4dd6f844c81128b81709cdc3cdfbe37c47)
2014-03-14 20:48:46 -04:00
Steve Howell
44bb9d58d1 Test startup logic in bot_data.js
(imported from commit 6410c584c2e1d8027a276902c67f34ee6a284e6f)
2014-03-14 20:48:46 -04:00
Steve Howell
0d0c427f2b Remove unused bot_data.get_all()
(imported from commit 70ec624667dacede72c00f1bb207d8d18dfdd4c1)
2014-03-14 20:48:45 -04:00
Allen Rabinovich
080f7229fc Make status messages larger
(imported from commit 0545d9d074b828c54fbb9156cd8e647c896e2b17)
2014-03-14 20:48:45 -04:00
Allen Rabinovich
f1db96143a Stick 'Edited' tag to the top and darken timestamp further
(imported from commit 682b72001cd317b2236cab23e9392c9e4452784d)
2014-03-14 20:48:45 -04:00
Steve Howell
72964a2194 Recognize humbug-user-uploads-test for images/attachements.
(imported from commit 8596a5c4bad6e1adbfe97cbe057d1bd6d8e7f530)
2014-03-14 20:48:45 -04:00
Steve Howell
d2f773a99d Handle empty Message table in act_on_message_ranges.
(imported from commit 609b0f531c4af23ddb6f3e5760dc9d251f1a4d3d)
2014-03-14 20:48:44 -04:00
Zev Benjamin
d445386adc nagios: Add Postgres check for disabled triggers
(imported from commit 08ff85aecfc44c9226e637383464fae4d2b8997a)
2014-03-14 20:48:44 -04:00
Zev Benjamin
1653541e83 nagios: Re-enable Postgres transaction time checks
We believe these will generally no longer be disruptive now that we have
autocommit enabled.

(imported from commit c8c1301e0d4b188d6708173cd8c8b16279e3d910)
2014-03-14 20:48:44 -04:00
Steve Howell
fa37ac1d73 Add act_on_message_ranges() migration helper.
(imported from commit 9e6567c1a12a7d8e447ed80ee08723376eaee6fe)
2014-03-12 21:15:23 -04:00
Steve Howell
9a5289b96c Change compose box only for going-forward topic changes.
(imported from commit 69de10fd9866acab2d12f15489c67eb9daab8d3d)
2014-03-12 21:15:22 -04:00
Steve Howell
b8de1dd13f Change narrows automatically on topic changes.
(imported from commit 7a8e606cc6fe0f2e4b5a164e1396e302ad969102)
2014-03-12 21:15:22 -04:00
Steve Howell
45002aa03f Close message edit before doing topic-related changes.
Closing the edit box earlier will make future changes less brittle,
when we, for example, re-narrow based on topic edits.

(imported from commit 36219c5129153beebfefe443932825fdf74abc43)
2014-03-12 21:15:22 -04:00
Steve Howell
d4fa917c49 Add has_topic() helper to filter.js
(imported from commit 8d8d9c2b6638968b18c7603e070c001d6b16cf21)
2014-03-12 21:15:22 -04:00
Steve Howell
0376d26c79 Add filter_with_new_topic() method.
(imported from commit 2ed9261ec70edf0a4ee1a25989cabfa9ab7907fd)
2014-03-12 21:15:22 -04:00
Steve Howell
65e9d0bead Change compose box for topic changes only if streams match.
(imported from commit 0bd6cd53ea4a8db5a457bb7dd5917f25c7c9434a)
2014-03-12 21:15:21 -04:00
Steve Howell
63097f32e5 Let arrow keys do the right thing for select widgets.
This helps the edit form in particular, when you change a
topic and need to select the propagation option.

(imported from commit c9dd1e62cd9e0b2142855685f04baa06eecf7226)
2014-03-12 21:15:21 -04:00
Steve Howell
da66220524 Add propagate_mode to event for topic updates.
(imported from commit c5bd140a46db5b6bc4164c21bcb698776fb0d786)
2014-03-12 21:15:21 -04:00
Steve Howell
9648fd1f9a Add stream_id to event for topic updates.
(imported from commit 2c0ff291672a2576e5812d8c3abdb71256ada61f)
2014-03-12 21:15:21 -04:00
Steve Howell
7a509af38b Add testing for update_message events.
(imported from commit 014cc8f3ed4c56108105e69f17d4894a0bf56c37)
2014-03-12 21:15:20 -04:00
Steve Howell
ff44fb6fcf For topic changes, set the compose subject outside the loop.
If we get a topic change, we can change the subject outside the
loop, since we are passed in event.orig_subject.  Doing it inside
the loop was mostly harmless, since after you encountered the first
message with the old topic, the condition to change the subject
evaluated to false, but it was still technically O(N), and it was
kind of confusing.

This commit changes behavior in the edge case that you have the
compose box open for a changing subject, but you are in a narrow
that does not have any of the affected messages.  After this commit,
the topic in the compose box will still change, which I believe
is the correct behavior.

(imported from commit 2363e432ebe7ae8e07379324ee0bfb52051428e6)
2014-03-12 21:15:20 -04:00
Steve Howell
dfc34eb074 Allow negated has:* searches.
Before this change, we were incorrectly trying to do local
filtering on negated has searches.

(imported from commit d1a6f1feef6b3cc1c984eb91a73cd16c4e66874e)
2014-03-12 21:15:20 -04:00
Allen Rabinovich
d6617a991c Remove mobile device indicator from template
(imported from commit 48a10a75b30c3f51a6dfa5af43ca138e391289d4)
2014-03-12 21:15:19 -04:00
Tim Abbott
12309c61b6 Remove Nagios monitoring for the old email mirror.
(imported from commit fc4d95b12d5ee29438a2d3e7d8d694e8aa21f202)
2014-03-12 21:15:19 -04:00
Steve Howell
24c23c2290 Remove unused json_to_bool().
(imported from commit 72f0db5f623ae9a06ffad2882bcad0e74ceaf884)
2014-03-12 21:15:17 -04:00
Allen Rabinovich
fcca1549b0 Darken the timestamps
(imported from commit c8934a422d8d770634015210fde80eced34aba64)
2014-03-11 13:26:32 -06:00
Luke Faraone
8b3b33c182 Reword error page; link to Twitter.
We use this error page for all 5xx errors, so I'm removing the error
number from the text.

(imported from commit c0c4c8829d466dd20c76dbbc920fc57cafbd6e6c)
2014-03-11 15:16:19 -04:00
Luke Faraone
f4196ed6ef Don't allow sending messages to deactivated users or realms
We still don't show this in the frontend, aside from our usual "Not
delivered" message that we also show when you send to a non-existent
user.

Addresses #2349

(imported from commit 2f348b15a4d539987ddbcccbbf40e2be87c1f92d)
2014-03-11 15:11:53 -04:00
Luke Faraone
9ea3198ddf Reject API key usage by users from deactivated realms
(imported from commit f1c791943f62bdde841ebb6975daef60e5a19174)
2014-03-11 15:11:52 -04:00
Allen Rabinovich
40164f4398 Move mobile indicator to the right and style it properly
(imported from commit 19f6bd27b30c355c1720d43580f5b6ff6c1c0b4a)
2014-03-11 13:06:23 -04:00
Luke Faraone
fd7dd0bc2c Use correct presence names for iOS mobile devices
(imported from commit d75f56c26d272342e2b4d074ea90a6d7fb9cff4e)
2014-03-11 13:06:23 -04:00
Luke Faraone
bd20a756f9 Show a mobile icon in the presence list when relevant
We show a user as "on mobile" if:
 * They are only active on mobile
 * They are inactive on all devices and can receive push notifications

(imported from commit 0510b9371727cd19c72f6990df7112921c36ad48)
2014-03-11 13:06:23 -04:00
Waseem Daher
4397c25976 Wrap 'Receive audible notifications'.
This resolves Trac #2366.

(imported from commit 0de4b20e0310980181716f7a29a82a4228a16b1b)
2014-03-11 13:06:23 -04:00
Zev Benjamin
bdee9721ec tests: Delay loading old messages and starting get_updates until phantomjs thinks the page has loaded
This doesn't affect code when not in testing.  It shaves 7 seconds off of casper
test time on my machine.

(imported from commit 7e27fa781bcf16f36d9c8f058427ba57c41068bd)
2014-03-11 13:06:22 -04:00
Zev Benjamin
f45f0b1df6 Get message row safely in the presence of local ids
(imported from commit 4f8c4742206a9fcba4eb19653152aeb4919159bd)
2014-03-11 13:06:22 -04:00
Zev Benjamin
dfa45a3689 tests: Wait until we've actually logged in to try to log out
(imported from commit f1a29520fdb868a91cf5145be49542c8db9b4316)
2014-03-11 13:06:22 -04:00
Zev Benjamin
d6f01ed7b9 tests: Clear phantomjs local storage before starting tests
(imported from commit 83ee6f1c95a6f1e4005b36af6be2d60f70c81a1d)
2014-03-11 13:06:22 -04:00
Zev Benjamin
917a4363e7 tests: Only initialize casper once
(imported from commit 849b8cfc0545fb0ff51dbfc32d2bc6081c0a5215)
2014-03-11 13:06:22 -04:00
Zev Benjamin
0fbfbf488b tests: Remove dead test
(imported from commit a85a0877c21b0eba5cdf708fc8d264b11f7a3fd9)
2014-03-11 13:06:22 -04:00
Zev Benjamin
e9acdd147f tests: Don't try to edit locally echoed messages
(imported from commit 04760e67b1c18766dc23072b4a735d8cb28a658b)
2014-03-11 13:06:21 -04:00
Zev Benjamin
2f01e9c51d tests: Use then_send_many
(imported from commit 228ee697a54643912eb3846d48c78e4464193632)
2014-03-11 13:06:21 -04:00
Zev Benjamin
719d551de6 tests: Always wait before sending messages
(imported from commit 1860f994b5698ba39ec9b45564c283f932d7502e)
2014-03-11 13:06:21 -04:00
Zev Benjamin
d3f14ae860 message_flags.js: Add comment
(imported from commit 6660076a04f765f67ade35664bd09678691d37c3)
2014-03-11 13:06:21 -04:00
Zev Benjamin
9d04b3d643 Don't tightly recurse when updating flags for local messages
(imported from commit a4a9f5278c9445fae753311ea16f165be15ff8eb)
2014-03-11 13:06:21 -04:00
Zev Benjamin
5fd58cf249 casperjs: Immediately check the condition in waitFor and don't wait after the condition is true
Normally, casper delays checking the waitFor condition for 100 milliseconds and
further does not act on that check for another 100 milliseconds.  This is just
silly.

(imported from commit ad046ceda81abda5c609ce25ef0d4fb27d3da716)
2014-03-11 13:06:21 -04:00
Zev Benjamin
39f632134d tests: Rename casper helpers for clarity
send_message -> then_send_message
send_many -> then_send_many
wait_and_send -> then_wait_and_send

Hopefully this makes it clearer that they should not be called inside of steps.

(imported from commit 4fcc971817b25056100311ba55303da2c5527f0f)
2014-03-11 13:06:21 -04:00
Zev Benjamin
0ccb794007 tests: Don't add new steps during execution
Casper can technically handle it, but it's cleaner to create all steps ahead of
time.

(imported from commit 37cda128818d663f57b6e2282a781e8d099fa77d)
2014-03-11 13:06:20 -04:00
Zev Benjamin
80ca037747 tests: Correctly wait for a message to be visible
I'm not sure how it worked at all before.

(imported from commit 608b0574d1a80cd631d9ea8198990d97d72ba64d)
2014-03-11 13:06:20 -04:00
Zev Benjamin
c7586a7135 casperjs: Correctly call the then callback in Casper.waitFor
Casper was calling casper.then(then) instead of calling the callback directly.
This meant that the callback was being added as a step, which worked, but was
not consistent with the rest of the casper model.

(imported from commit b3bf916f7c56dd3d4e7be3569ebdf9d3045cd085)
2014-03-11 13:06:20 -04:00
Zev Benjamin
6071a11419 tests: Defer sockjs object creation when in testing
This speeds up CasperJS tests by 25 seconds per main app page load.

When we switched the SockJS, the casper tests got inexplicably slower.  I
finially figured out what's going on.  The first SockJS XHR request (remember
that we don't get websockets in the test suite) gets considered part of the page
load and therefore the PhantomJS onLoadFinished handler doesn't get called until
the SockJS XHR finishes, which happens at the heartbeat, 25 seconds later.  To
fix this, we simply don't create the SockJS object on page load since it will be
created on demand, anyway.

(imported from commit 845a97526c5102df426cd6fc26182a734e7fcab6)
2014-03-11 13:06:20 -04:00
Zev Benjamin
1c7918495c socket: Factor out SockJS object creation
(imported from commit cedb2b3e6ade0b045e8d4982437f6499ae904222)
2014-03-11 13:06:20 -04:00
Steve Howell
72c9deb59e Handle errors better when rendering messages.
Catch any exceptions that happen in the process of triggering
the message_rendered.zulip event.  This addresses #2356.

(imported from commit ce771483cd2533d312fbd68e9c2753c80b3c8d49)
2014-03-11 13:06:19 -04:00
acrefoot
43d866dd71 fixup copy and paste logic
Our restructuring of the messages (especially grouping) seems to be the culprit for message copy and paste

(imported from commit 14632a67f55efea4f1b53cc718a4f655ac83b387)
2014-03-11 13:06:19 -04:00
Allen Rabinovich
c23028ec7a Move timestamps to the right
(imported from commit 1fb3e726b32065755cf1ff28e1371bc75609450e)
2014-03-11 13:06:19 -04:00
Waseem Daher
ef23a4efe4 Disable authed uploads for zulip.com.
(imported from commit 3c432e730005e4c8404245c974b53c5a49fd4c9d)
2014-03-11 13:06:19 -04:00
Luke Faraone
2d3a7e5418 Use a different status code and include seconds remaining header in ratelimits
This will make it slightly easier to consume the data from our clients.

Ref:
    RFC 6585 §4

(imported from commit 6d323dc25db78a6d84a163add950f039e03e73d3)
2014-03-11 13:06:19 -04:00
Steve Howell
105c742e92 Correctly identify images/attachments on humbug-user-uploads.
(imported from commit 081d00d99672e6b938c60d9e13665e21d935d8ef)
2014-03-11 13:06:18 -04:00
Steve Howell
e993b8fc40 Replace "/me" with sender's name in notifications.
This fixes #2358.

(imported from commit 579f217687bd2af80ab6919a72435336ab456410)
2014-03-11 13:06:18 -04:00
acrefoot
3d7c3a6de3 Bring the Github integration setup page up to date
We're no longer called 'Humbug', and we have more configuration options.

(imported from commit 56c1c4a25e601def35de102fba86960444ddf513)
2014-03-11 13:06:18 -04:00
acrefoot
c3543b06f0 Honor exclude_commits for github integration
We weren't before :(

(imported from commit 3691066a50f1b67c227dbfc056dc8cdf2c06eea8)
2014-03-11 13:06:18 -04:00
Steve Howell
bc9a9db9b3 Select message if you click on its pencil icon.
This addresses #2351.  While I could see the argument for
wanting to edit a message without changing your selection,
I think it's just very surprising behavior and inconsistent
with the rest of the UI.

(imported from commit 3bb4faca0656258b76bfaafbd7f4a645810578f6)
2014-03-11 13:06:18 -04:00
Waseem Daher
af16f6730e Remove border on message body gravatar.
(imported from commit e642facf6dccfafc35632aa6ad5e4e60ad79bf24)
2014-03-11 13:06:17 -04:00
Steve Howell
0eda5cbfec Add event schema checks to misc event tests.
(imported from commit 1c17f972cdd91b8da2169e1cb1cef817f683dd29)
2014-03-11 13:06:17 -04:00
Steve Howell
52478d684c Rename build_update_checker to realm_bot_schema.
(imported from commit ed75e9228a85c5e15290fdd31a0dbbd84327aae9)
2014-03-11 13:06:17 -04:00
Steve Howell
97511067df Sort imports in test_events.py.
(imported from commit 85443b002a3e9231a98d0d1cc85a56e949748ea3)
2014-03-11 13:06:17 -04:00
Jessica McKellar
e7ef654b45 [puppet]: Adjust zmirror Nagios checks to be more tolerant of a bad network.
We get a lot of alerts and sometimes pages due to network blips.

(imported from commit 4766585e71533b8551d49fa61bc4653114a65457)
2014-03-11 13:06:16 -04:00
Leo Franchi
9d8758557b Use global match in alert word regex to match all matches
(imported from commit aaec296ad6b18b20c1c2d1cb017cffef8e3e0512)
2014-03-11 13:06:16 -04:00
Leo Franchi
65b6c80f07 Don't highlight alert words that are in URLs, breaking them
(imported from commit e20ee33a1687f935482f48f829c19a1606ce6db1)
2014-03-11 13:06:16 -04:00
Leo Franchi
246a5737e7 Use a message's position not offset() to detect if it's off the bottom of the page
(imported from commit f7915c567b54ad5fd82daf137f89db566a1b417b)
2014-03-11 13:06:15 -04:00
Zev Benjamin
eda05d23bf Optimize get_occupied_streams
In a test run with a hand-constructed query, this sped up the query time from
280ms to 50ms.

(imported from commit 8cbe199ca50a487491d13d6d6ef940ea668c1038)
2014-03-11 13:06:15 -04:00
Zev Benjamin
2090d6ee27 jabber_mirror: Calculate the zulip domain from the client email address
We were previously calculating it from the zulip_email option, which might not
be set if it is being specified via the config file.

(imported from commit 76866c239ca63ef90a7967c9a6027aeec9be6390)
2014-03-06 21:59:55 -05:00
Zev Benjamin
27aaa3b1bf Rename mit_to_mit -> same_realm_zephyr_user for uniformity and clarity
(imported from commit 74063d6c8bb9e9fbf62c24dcd8a18294b8f7b51f)
2014-03-06 21:59:55 -05:00
Zev Benjamin
cc9fe19a9f Special case Jabber mirroring same-realm check for ist.mit.edu
We can't just check that the realms are the same because ist.mit.edu is an open
realm and uses @mit.edu email addresses.

(imported from commit 7dbaa81cea6e4f82563dfc0cfe67a61fe9378911)
2014-03-06 21:59:55 -05:00
Waseem Daher
3a8b663eb1 Square off bot avatar.
(imported from commit 628816b490732e03cca77d721614979ba25da2f3)
2014-03-06 21:59:55 -05:00
Waseem Daher
b5ec6c9958 Delete unused .profile_picture CSS class.
grepping for it turns up nothing relevant.

(imported from commit c7bb97515c993c0d5ed6de7e4ac9edc99ff83ff2)
2014-03-06 21:59:55 -05:00
Waseem Daher
c359499386 Square off avatars in commit messages.
(imported from commit 8c2c505e6b84b50b4498f51bbf170e4dea3af39a)
2014-03-06 21:59:54 -05:00
Waseem Daher
b80af20541 Larger emoji.
(imported from commit 3fb9a5df7fde4cd073f344d9aed5cb16c1b0de71)
2014-03-06 21:59:54 -05:00
Waseem Daher
96f6939284 Fix a few more unstyled 'cancel' buttons.
(imported from commit 1d8145fe1576af62b73be0badad9de1b75da816a)
2014-03-06 21:59:53 -05:00
Waseem Daher
d8108f944c Restyle bankruptcy "no" button.
(imported from commit 86520ec9e0067316d2f737175e59315745be62b7)
2014-03-06 21:59:53 -05:00
Waseem Daher
fb00ee79a0 Fix unstyled button on Settings stream notification propagation.
(imported from commit ebc046e8d0f29a6bbf64005c70f32522a366fa6b)
2014-03-06 12:45:06 -05:00
Steve Howell
8f37c3f5fd Tolerate spaces after language in markdown fences.
See #2357.  We now support `~~~ .py ` with that trailing space.

Note that the test coverage is Python-side only due to
bugdown_matches_marked being set to false, since we don't yet
support language syntax on the client side.

(imported from commit ccd5fcb0eee01478d349161400103480678d7486)
2014-03-06 10:15:20 -05:00
Waseem Daher
91fb286b0d Properly style integration-edit buttons.
(imported from commit dbbe831bbc86b24ba37fa9cb06dfdba32a1e8867)
2014-03-05 17:43:00 -05:00
Waseem Daher
ae326c066f Properly style 'Cancel' button in edit dialog.
(imported from commit 8c63567f7f696175b7293fabe26fea2d9c60a15a)
2014-03-05 17:33:01 -05:00
Waseem Daher
a9f01e382a Switch streams page over to use consistent buttons.
(imported from commit c4d7f658f361a759a38951349e027ac3e279fe9b)
2014-03-05 17:23:23 -05:00
Waseem Daher
66ecc7a6f2 Slightly tidy up realm name change 'Save' button on admin page.
This commit got lost in an earlier rebase.

(imported from commit 36bfad56fc08f443c3721c880cb4dd3427fd0541)
2014-03-05 16:43:10 -05:00
Waseem Daher
2429ed6eeb Remove old Bootstrap2 button code.
(imported from commit 1483c549a3d41802755fea4db7229324e1595b42)
2014-03-05 16:24:55 -05:00
Waseem Daher
095c82ecc4 Actually switch to Bootstrap3-esque buttons.
(imported from commit ddcecb8c5a63324a666ffe170e2d5a76171776c9)
2014-03-05 16:24:54 -05:00
Waseem Daher
82dfc7b109 Remove border-radius from Bootstrap3-esque buttons.
(imported from commit 1c86fb21ab39f8e489481aa0e3f82dc4247364b3)
2014-03-05 16:24:54 -05:00
Waseem Daher
23155bbbae Rename some class names for Bootstrap2 compatibility.
(imported from commit 6a9b9a9e431902640651cad0a02b848bd2717fbc)
2014-03-05 16:24:54 -05:00
Waseem Daher
a983a62ad2 [third] Import button CSS from Bootstrap 3.1.1
(imported from commit 07fea19901d31339d9cb7481f00a6d244b09bdb4)
2014-03-05 16:24:54 -05:00
Waseem Daher
6ef234ba80 Slightly tidy up realm name change 'Save' button on admin page.
(imported from commit dfa8d4a08d1e2f505f4edf8b0ef5314da47292a1)
2014-03-05 16:24:54 -05:00
Allen Rabinovich
b343d322fe Fix errant scrollbar in stream list
(imported from commit 7a70bad72adb5d57ea11e926f48301d2a9cc7fd0)
2014-03-05 14:14:27 -07:00
Leo Franchi
05d911b913 Allow auto-linked URLs to end with a !, without including the ! in the url
(imported from commit 26fbf8d8318dc32f31f94f366750521afab94ac5)
2014-03-05 15:22:05 -05:00
Steve Howell
957486cc95 Fix support for searches like "in:home search:foo".
Previously, if you searched for "in:home search:foo", we
weren't making "in:home" a public operator, so the back end
wouldn't know to exclude muted messages, but the front end
also wouldn't exclude muted messages, because it assumed
that queries with "search:" in them were fully narrowed by
the back end.

Prior commits made it so that the back end is now capable
of doing "in:home" narrowing, so to get the properly narrowed
results, we simply needed to make in:home be a public operator
in this commit.  We also made in:all be public for convenience,
although it's essentially a no-op.

(imported from commit e4a8b10813b50163c431b1721bd316b676be1b83)
2014-03-05 14:56:35 -05:00
Steve Howell
e7769d9004 Add back end support for in-home/in-all narrows.
(imported from commit bfa54fbb8c7eaced19e354514536d75c30a24b15)
2014-03-05 14:56:34 -05:00
Leo Franchi
aa9c98ef10 Make the selectable sidebar block width the same width as the overall sidebar
(imported from commit 078765c03dbc015b22b3cbb12df692573f6b33cd)
2014-03-05 14:48:54 -05:00
Jason Michalski
30f89f4669 Convert the bot section of the settings page to use bot_data
(imported from commit 63e6982f96ac46d1cebd2ea16d2a7abc7f8d6597)
2014-03-05 14:16:20 -05:00
Jason Michalski
fa37e91e5c Add admin status to bot_data
(imported from commit 47b84b3ef1e97e355dee84f0595e94a4612bf4df)
2014-03-05 14:16:20 -05:00
Jason Michalski
3f6e53db6e Add bot_data module that updated with events
(imported from commit b0bd714258132fc81db763d316a15f5a81b1f4ff)
2014-03-05 14:16:20 -05:00
Jason Michalski
86175e8627 Add events for bots disabling bots
(imported from commit 9de3410555a45038c31341b3857782ffc8246cf7)
2014-03-05 14:16:20 -05:00
Jason Michalski
0165da405f Add events for bot default_events_register_stream changes
(imported from commit 143ed5b110a7f3b37f145dcd3fbe9133a183c7ec)
2014-03-05 14:16:20 -05:00
Jason Michalski
f66d864f45 Add event for bot default_sending_stream changes
(imported from commit 7a859cf9f51b6ec1bacb1e3b3cfa9da2c6fbf32f)
2014-03-05 14:16:20 -05:00
Jason Michalski
b5ca2631e6 Add event for bot default_all_public_streams changes
(imported from commit f189fb6692cb8c833cc2a1951ad8a4695cc4c27f)
2014-03-05 14:16:20 -05:00
Jason Michalski
3772344e2d Add events for bot avatar_url changes
(imported from commit c058386ce5ef9d89165c44fd853808cfe1f625f4)
2014-03-05 14:16:20 -05:00
Jason Michalski
280575aff0 Refactor json_set_avatar and patch_bot_backend to use do_change_avatar_source
(imported from commit eba0ff8a5c4409ac01c710455fe200b28f953b56)
2014-03-05 14:16:20 -05:00
Jason Michalski
c0d104c110 Add events for bot api_key changes
(imported from commit 44e4e374ee4951c4d984c009ef7af825985fabbf)
2014-03-05 14:16:20 -05:00
Jason Michalski
64ba85aa19 Refactor regenerate_api_key and regenerate_bot_api_key to use do_regenerate_api_key
(imported from commit 5c54e4771b6730a8ebe304f6b6e86722d28eca8d)
2014-03-05 14:16:20 -05:00
Jason Michalski
b161f4cff9 Add events for bot full_name changes
(imported from commit 7a8945982a060b208c5459a2b3d130eb84a72922)
2014-03-05 14:16:19 -05:00
Jason Michalski
c17ed8dc8c Add bots to page_params and send events on bot creation
(imported from commit ce418b4f056576d57f82d26af621473c730c12d8)
2014-03-05 14:16:19 -05:00
Jason Michalski
494868d21d Group bot stream options lists by public/private
(imported from commit 940319a25edfd1943d78ff95542ffda6f482a40b)
2014-03-05 14:16:19 -05:00
Jason Michalski
f82cbe855f Support editing a bot's default streams
(imported from commit 72ceb5152745ddfcc22dfd929904927950bf46e4)
2014-03-05 14:16:19 -05:00
Jason Michalski
eebbf0d4ee Show the new bot's default stream settings in the edit view
(imported from commit d6f1872e0dedd57ebde31da2caf075804195dfb0)
2014-03-05 14:16:19 -05:00
Jason Michalski
eb1032c9c2 Add UI to set "all public" default to during bot creation
(imported from commit ec03ccdce309c9fbe866343368044b00ea0f5b81)
2014-03-05 14:16:19 -05:00
Jason Michalski
17b579911e Add UI to set listen on stream during bot creation
(imported from commit b481a55c16f853766c82883b4c6c86de5c87759e)
2014-03-05 14:16:18 -05:00
Jason Michalski
538d76e6ed Add UI to create bots with a default send to stream
(imported from commit 1333de89a75bd972ec85be7f11f6ea11d4fa34cd)
2014-03-05 14:16:18 -05:00
Jason Michalski
846dfd5105 Update patch bot API to support setting stream defaults
Adds APIs edit a bot's default_to_stream, default_events_register_stream
and default_all_public_streams.

(imported from commit c848a94b7932311143dad770c901d6688c936b6d)
2014-03-05 14:16:18 -05:00
Jason Michalski
50db83508b Add API support for setting defaults in the add bot API
Support setting default_to_stream, default_events_register_stream, and
default_all_public_streams during in the bot creation API.

(imported from commit bef484dd8be9f8aacd65a959594075aea8bdf271)
2014-03-05 14:16:18 -05:00
Jason Michalski
f3180b774b [schema] Add default user_profile options for register events
Allow bot owners to set which streams their will receive events for
without needing to change a configuration file.

(imported from commit 2b69e519dbc12ffbdba072031a7f7196c9e50e33)
2014-03-05 14:16:18 -05:00
Jason Michalski
de545d5fa0 [schema] Add a default to stream option to user profile
This allows bot owners to configure which streams messages are delivered
to without needing to change webhook URLs or configuration files.

(imported from commit 32a0c26657c145b001cd8cb3ce0a0364d48902ce)
2014-03-05 14:16:18 -05:00
Waseem Daher
8efa04437d Remove flaky inline subscribe button tests.
(imported from commit b7be5827a433d66d02a24349ba2fe299ce9e3d9f)
2014-03-05 14:05:40 -05:00
Waseem Daher
54ae946061 Squarify swatches on streams page.
(imported from commit 06d630d90acf4bc40e86c34cb85b7eaca92a7263)
2014-03-05 14:05:40 -05:00
Steve Howell
8efe4c0a1b Support has:attachment/has:image/has:link searches.
This commit finishes up support for has:* searches by adding
the front-end pieces, specifically the part that "has" operators
will not be applied locally.  It also implements basic
descriptions for search suggestions and canonicalization
of operands from plural to singular.

(imported from commit a3285bc33d06d76b5a2b403ebcdd911b4cc03980)
2014-03-05 13:58:53 -05:00
Steve Howell
82a935080d Support has:* searches on the back end.
(imported from commit a6a6f465ce0343d4a5313ee54f6ff427940a03ab)
2014-03-05 13:58:53 -05:00
Jessica McKellar
25a9eae74b Enabled authed uploads for Bargain Bit.
(imported from commit f793b7ac41341384b914168a3fc5ed637d63a645)
2014-03-05 11:55:02 -05:00
Steve Howell
58c44fee3e Document negated topic searches.
We don't have room in the dialog to show every variation of
the negated search syntax.  If we start by documenting negated
topic searches, we may get some discovery on the negated search
features without cluttering out the way more common search
options.

(imported from commit 3b2c2672d125788dc71a5eeb2b6f1e551380c62e)
2014-03-05 10:54:02 -05:00
Steve Howell
1b9752e10e [notify] Turn on negated search for all realms.
This fixes #730, which includes any customers we want to notify
about the feature being pushed.

(imported from commit c60959ddd7c61ea8e014e984047e9f7bc0d59296)
2014-03-05 10:54:02 -05:00
Steve Howell
89f10d7e7a Handle negated person-related operators in search suggestions.
(imported from commit e045a0910ff59d9b8569c5ba3b3b644fe2d7dad7)
2014-03-05 10:54:02 -05:00
Steve Howell
e5e0ba9e7c Handle negated topics in search suggestions.
Typing "stream:foo -topic:b" leads to "stream:foo -topic:bar" properly
as a suggestion now.

(imported from commit bb0acf52744f7b13977a3db5d3c130d1402b09b7)
2014-03-05 10:54:02 -05:00
Zev Benjamin
30f9fed766 jabber_mirror: Report a useful error message when fetching initial Zulip streams/subscriptions
(imported from commit 1133cb0ddb349cda7e16586fba4ba72888e66887)
2014-03-04 23:02:27 -05:00
Zev Benjamin
f495f79c90 jabber_mirror: Fix Zulip error handling
(imported from commit 8548576635e5be9b725e059c2d4d9ef9953ec97a)
2014-03-04 23:02:27 -05:00
Zev Benjamin
4721a9093c jabber_mirror: Add option to append a suffix to Zulip usernames
This is needed for the ist.mit.edu realm, where the same email address could be
used for all three of Zulip, Jabber, and Zephyr.  To disambiguate Jabber mirror
dummy users from Zephyr mirror dummy users with the same email address (but
which would be in a different realm), we force all email addresses in the
ist.mit.edu realm to have local parts that end in "+ist".

(imported from commit 5ebad2cc8f6c7286b4b9426d57ed75578703fb86)
2014-03-04 23:02:27 -05:00
Zev Benjamin
9f4bc9fb72 jabber_mirror: Remove dead code
(imported from commit b67faad6888713554929c7e6a8147d19c489956a)
2014-03-04 23:02:27 -05:00
Zev Benjamin
f999440cc6 Add bot1@customer36.invalid to the list of API super users
(imported from commit 07767022db0f894d398d0031053f93439258ea0d)
2014-03-04 23:02:27 -05:00
Zev Benjamin
2a3a98228e jabber_mirror: Allow the mode to be specified in the config file
(imported from commit 8de5006f6935271997204d958c44c03ebf14c403)
2014-03-04 23:02:27 -05:00
Zev Benjamin
d069ad0bc7 jabber_mirror: Remove --openfire option
It doesn't actually seem to be necessary to adjust the SSL version in current
versions of Openfire.

(imported from commit 6766d9fd5081cf16f2a5e3e2b008f20e7498caa4)
2014-03-04 23:02:27 -05:00
Zev Benjamin
137f5e5980 jabber_mirror: Allow the MUC nickname to be specified
This allows users to run the public mirror as a regular user.

(imported from commit 3512dacf329dadc784d7be492ad290b17082bad4)
2014-03-04 23:02:27 -05:00
Zev Benjamin
11fef6b627 jabber_mirror: Change the default resource to 'zulip'
(imported from commit 290dca7fce5230dc94425478ad48fb8b8a0952b6)
2014-03-04 23:02:26 -05:00
Zev Benjamin
6b4fe69227 jabber_mirror: Guess the conference domain when it isn't specified
(imported from commit 3fed4bdf5ca73b3b9d58ec42a2031e75e813bbd2)
2014-03-04 23:02:26 -05:00
Zev Benjamin
9b41b30487 jabber_mirror: Use sleekxmpp.JID when manipulating message recipients
(imported from commit 57b8384bf79a60abbaf535bd11f222d7f63db251)
2014-03-04 23:02:26 -05:00
Zev Benjamin
868b071eb2 jabber_mirror: Take a JID on the commandline instead of a separate Jabber username and domain
We also take the opportunity to use the sleekxmpp JID parsing more instead of
doing string manipulation.

(imported from commit 6e4ba0bd2c241666fcde42333ff68b879d8ab2b7)
2014-03-04 23:02:26 -05:00
Jessica McKellar
5f7df38b8a Unbreak custom alert words on the settings page.
This doesn't change the alerting UI logic, it just turns
alert_words_ui into a module and calls the setup code from settings.js
when the settings page is rendered.

(imported from commit 05f95383b046086641280f82f648be58688efe61)
2014-03-04 18:06:48 -05:00
Luke Faraone
f445202ba5 Change the topic in the compose box after a topic rename
This helps reduce "double-mixing", closes #2338, and basically also
closes #2037.

(imported from commit dadb70ae85d572d642bba4ac6c3b30f31f104ce0)
2014-03-04 18:06:09 -05:00
Leo Franchi
a4a47db9e0 Error out gracefully if edited message is muted
(imported from commit 1aefd61d5633ed67a919cccd2d8c68f7ba8e7bfc)
2014-03-04 17:19:59 -05:00
Jason Michalski
55fef4d60e Enable cleanup_before_reload for CUSTOMER4
(imported from commit dd81a22a64e8a1098bf3a6b875919a2a25499bb8)
2014-03-04 17:07:05 -05:00
Jason Michalski
09dfc9a89b Split selecting a message and hiding the empty narrow message
We should hide the empty narrow message message whenever the narrow is
not empty, but we should only select a message if non are currently
selected.

(imported from commit 22f6b0827dc84ed587a83b5d713b12c1d5d4c0a0)
2014-03-04 16:43:00 -05:00
acrefoot
eabd9341b6 Fixup 'force pushed' message when creating branches in Github
Github flags pushes as either `forced` or not. However, it always marks new branches as
forced pushes--but we don't necessarily agree with them. This commit checks for the `created`
flag as well.

This resolves Trac #2346

(imported from commit 960bd3ad707a4d1ad431e21dcd79389e8d4b297b)
2014-03-04 16:42:34 -05:00
Steve Howell
2da547efc6 Test match_subject/match_content in message_group.handlebars.
The match_subject and match_content template vars are notorious
for causing bugs due to the way handlebars forces the strange
../../.. syntax on us, so now we have some test coverage.

(imported from commit c6b151b964ae8b6fb199d9cdbe533a87c6b58947)
2014-03-04 16:41:28 -05:00
Steve Howell
46d9f581ab Added NarrowBuilderTest.test_add_term()
Testing directly against NarrowBuilder is convenient, as it
requires very minimal data setup to get a basic sanity check
of the SQL that gets generated.

(imported from commit 5f3bb0364713bd2e4228a9b9d4d16bde297b4e16)
2014-03-04 16:37:49 -05:00
Leo Franchi
12c04151e9 Prevent click on user filter from collapsing popped-out user list
(imported from commit 182d82f41218e12faeaf07cd92cbee88a9fa6624)
2014-03-04 11:11:31 -05:00
Leo Franchi
60d4c620b9 Disable left-side-userlist on staging, as only CUSTOMER7 uses it
(imported from commit 62d9e908cdb3132e22a58efcceee1d06a68d71bb)
2014-03-04 11:11:31 -05:00
Steve Howell
eec12ff268 Calculate has_* fields before saving Messages
Before saving a Message object, call update_calculated_fields()
to set the has_attachment/has_image/has_link fields.

Note that the pre_save hook we added here does not get called
if you call bulk_create, hence the explicit call to
update_calculated_fields() in do_send_messages().

(imported from commit 1d60ae5908ef186aa5ff1e39277dbb2b765e60d4)
2014-03-04 11:00:26 -05:00
Jason Michalski
16df239f39 Use the first unread from server on reload
When reloading the page we want to narrow to the location that is
restored from the query parameters. This is only done if we ask narrow
to use the first unread message from the server.

(imported from commit b585ef51cbb85788b24d90d831b42c45fd188569)
2014-03-03 18:17:15 -05:00
Jason Michalski
c753dfc9a8 Move reload initiation to an explicit initialize function
The reload initiation is required to run before other parts of the site
are started so that page_params will be setup correctly. This moves that
initiation out of an on ready handler to an explicit initialize call
near where the rest of the app is started.

(imported from commit b8994311299327aa3cfa57e3d9e92124a47123f4)
2014-03-03 18:17:15 -05:00
Leo Franchi
f2e8929b8a Hide rerender_message and use rerender_messages() in all cases.
rerender_messages() does extra work such as making rerendering in narrows
safe, as well as updating recipient bars. That should be the only valid entry
point for rerendering individual messages

(imported from commit f91aeb2070b1056ab95e01d68a342558c2813ae8)
2014-03-04 10:47:44 -05:00
Leo Franchi
ca031304b9 When rerendering single messages, grab messages from the view's own list
(imported from commit 5b3b5cefd65952b81406adcbd6208551228f0c5d)
2014-03-04 10:38:12 -05:00
Leo Franchi
1af7a9db1f Reify skeleton person objects that local echo creates when sending out-of-realm PMs
(imported from commit c0fcdba736f1270d8c05d00546444ee539301877)
2014-03-04 10:09:40 -05:00
Leo Franchi
bdaf8b2cfe Update message group recipient bars when rerendering messages individually
(imported from commit 3fb1386fee12c3a4a3f46810368cdd5d8cfb04d8)
2014-03-04 10:09:40 -05:00
Leo Franchi
6f67d94fc4 Split the recipient row of a message group into a partial
(imported from commit 660514daf932235b7c47ac4c22f963da17c7fc8b)
2014-03-04 10:09:40 -05:00
Zev Benjamin
28a6644384 jabber_mirror: Allow Jabber options to be specified in the Zulip config file
(imported from commit 7911fdd4c8a2e8668c01627697a3cd8a153d4612)
2014-03-03 17:30:58 -05:00
Zev Benjamin
66734d46cf jabber_mirror: Clean up help text
(imported from commit bd9a4682c754423047a993b8914d965c2e12fdf4)
2014-03-03 17:30:58 -05:00
Zev Benjamin
4fbe78d037 api: Expose function for getting the default Zulip config file
(imported from commit 89d6b48f9393670429aa960ad0ff27f030166e34)
2014-03-03 17:30:58 -05:00
Zev Benjamin
dfed7f0b7e jabber_mirror: Ignore attempts to join invalid MUCs
(imported from commit a82d53af1f581d059b6457a1bf7afe92af5d42d9)
2014-03-03 17:30:58 -05:00
Zev Benjamin
47f96dc2dd jabber_mirror: Configure rooms after joining
(imported from commit d4c6e895dca1c7002ce39db81b671ba1c975d517)
2014-03-03 17:30:58 -05:00
Zev Benjamin
38212f83fc jabber_mirror: Don't try to mirror messages from rooms themselves
These are usually administrative messages.

(imported from commit 58cbbc739fdd47acc586c235aedd2fccc83654fd)
2014-03-03 17:30:58 -05:00
Zev Benjamin
b21dc34eed jabber_mirror: Change character used for loop detection
Previously, we were using U+1B80, which is 'SUNDANESE SIGN PANYECEK' (i.e., an
assigned character).  U+1FFFE is a non-character (i.e., free for internal use)
on Plane 1.

(imported from commit f93d2401733afb96b6d717a7f659c011299071df)
2014-03-03 17:30:58 -05:00
Zev Benjamin
9634fccda7 jabber_mirror: Dynamically join and leave MUCs
For personal mirrors, this means that the mirror should join all Jabber rooms
corresponding to their Zulip subscriptions.  For the public mirror, this means
that the mirror should join all Jabber rooms corresponding to Zulip streams that
end in "/xmpp".

(imported from commit 16ed9e3deee7e02b2ae0dd79925f0ed5c4acd044)
2014-03-03 17:30:58 -05:00
Zev Benjamin
814aed7cbe Send an event when a stream is created, is deleted, becomes occupied, or becomes vacant
A stream is vacant when it has no subscribers and occupied when it has at least
one subscriber.

We have a slightly odd model where stream creation is conflated with
subscription creation.  Streams are created by attempting to subscribe to a
stream that doesn't exist.  We also hide streams with no subscribers from users
to make it seem like they've gone away.  However, we can't actually remove those
streams because we want to preserve history.

This commit moves us towards a separation of these two concepts.  By sending
events for stream creation, occupation, vacancy, and deletion, we allow clients
to directly observe the global state of streams rather than indirectly observing
subscription information.  A more complete solution would involve adding a view
for explicitly creating streams without subscribing to them.

This commit does not handle the intricacies of invite-only streams.  We
currently simply do not send these events for invite-only streams.

(imported from commit 5430e5a5eecefafcdba4f5d4f9aa665556fcc559)
2014-03-03 17:30:58 -05:00
Zev Benjamin
5c44fa9a29 Move bulk of get_streams_backend to actions.py
(imported from commit 3601444a2aabd1c613db61d71e6bc9fd6b4984d5)
2014-03-03 17:30:57 -05:00
Zev Benjamin
64b0550f58 api: Add get_subscribers method
(imported from commit 801021768431a04cfecf146b58f4d118e1dc7508)
2014-03-03 17:29:54 -05:00
Zev Benjamin
9c52818b93 jabber_mirror: Pull rooms to join from Zulip based on mode
(imported from commit 115d4d4732d8ff4f12d336cfc42a056183251d87)
2014-03-03 17:29:53 -05:00
Zev Benjamin
b23dc256e4 jabber_mirror: Document which mode handles which kinds of messages
(imported from commit 983224ac58bce724529806f6b8eaa3ea30cc730b)
2014-03-03 17:29:53 -05:00
Zev Benjamin
204e7e7e90 jabber_mirror: Only mirror messages from streams that end in '/xmpp'
(imported from commit 5213d40063361ffcf073772580ac0f699228cb3f)
2014-03-03 17:29:53 -05:00
Zev Benjamin
0e3af9b238 jabber_mirror: Mirror Jabber room 'foo' to stream 'foo/xmpp'
(imported from commit db771b5b5056cdca5780b90f66924c6f9ae3e84d)
2014-03-03 17:29:53 -05:00
Zev Benjamin
3fbdfeee88 jabber_mirror: Use new-style client name
(imported from commit a1bc5b076a9c0384c1abdc2377183b0eac19f450)
2014-03-03 17:29:53 -05:00
Zev Benjamin
406e3025fb Recognize new-style client name for Jabber mirror
(imported from commit 3c1f8120f4daa809e0844602bc8bea659837d84e)
2014-03-03 17:29:53 -05:00
Zev Benjamin
8155b8ea04 jabber_mirror: Add --debug option
(imported from commit 8d6986ba97f464359a1fe214d5605fa744660a9b)
2014-03-03 17:29:53 -05:00
Zev Benjamin
2850800e48 jabber_mirror: Exit if we fail to connect to the Jabber server
(imported from commit f5cc600325a3547412cf0b05239c988410354c10)
2014-03-03 17:29:53 -05:00
Zev Benjamin
0dd209c813 jabber_mirror: Respond to XMPP pings
Other clients like Pidgin sends these.

(imported from commit 61c69a080accda939b82ce8701b10ffc6dda672e)
2014-03-03 17:29:53 -05:00
Zev Benjamin
802bd6448c jabber_mirror: Working PM mirroring
(imported from commit 34617f989e83029c6591461adc3ffa18ddea2037)
2014-03-03 17:29:53 -05:00
Zev Benjamin
577d8d33e1 jabber_mirror: Working room/stream mirroring
(imported from commit 5d0a33423e90edaee3a1094b1d48fae73cfb54ca)
2014-03-03 17:29:53 -05:00
Zev Benjamin
2ca49c3735 jabber_mirror: Require the --conference-domain option when running in 'public' mode
(imported from commit 1dd564a212538e292ffc8b7a52caf7eae66d4475)
2014-03-03 17:29:53 -05:00
Zev Benjamin
40dd0c677e jabber_mirror: Clarify the two modes the mirror can run in
(imported from commit 8084e0552b06c6763f2f13a63c90c9dc73d6bf90)
2014-03-03 17:29:53 -05:00
Zev Benjamin
bf17ea0ee4 zephyr_mirror: Fix comment
(imported from commit aed76ecc3b4fd8bb01c299169a8e4eefd35f7cd8)
2014-03-03 17:29:53 -05:00
Zev Benjamin
cd1e07fed3 jabber_mirror: Take the Jabber username as a separate option
(imported from commit 86131c7502df7b841c34b09c0e94b071c89b3fde)
2014-03-03 17:29:52 -05:00
Zev Benjamin
e8843be3d0 jabber_mirror: Use zulip.init_from_options
(imported from commit 5839c5308a948d2c060d1eb5688b9cf0bd9ed3a2)
2014-03-03 17:29:52 -05:00
Zev Benjamin
8a16ea4cc6 jabber_mirror: Separate Jabber options into their own group
(imported from commit 223ecceee956ab30b1647eb0925d11982b2ef37d)
2014-03-03 17:29:52 -05:00
Zev Benjamin
4d47f487cb jabber_mirror: Use the Zulip API option group
(imported from commit 68243e4ebd44cd3b08bf0789c34bb85016d0d1b9)
2014-03-03 17:29:52 -05:00
Zev Benjamin
5ba0b6b633 api: Disambiguate the names of Zulip options
(imported from commit 67525764cc2f2a26081640063e2d78852f6229ca)
2014-03-03 17:29:52 -05:00
Zev Benjamin
213c0b49bc api: Let generate_option_group prepend a prefix to added options
(imported from commit 41cdd90a83914139c92cb3ea649cb5653f56d4ca)
2014-03-03 17:29:52 -05:00
Zev Benjamin
5696ff5ce6 api: Clarify that the API option group is for the Zulip API
(imported from commit e471fb60c04c4cf8d5e1ceb8cbd639dc3460fc48)
2014-03-03 17:29:52 -05:00
Zev Benjamin
fbe67f5d84 jabber_mirror: Use consistent casing for commandline arguments
(imported from commit e30aedc2f626d64b79a9b36b7f3a0fbee84a8ada)
2014-03-03 17:29:52 -05:00
Zev Benjamin
8bb359d194 jabber_mirror: Remove dead code
(imported from commit a8802340e1a624934a92d5bdd4ba8ad26faaadbf)
2014-03-03 17:29:52 -05:00
Zev Benjamin
52d6973191 jabber_mirror: Fix anti-looping
(imported from commit 5b0ee18b3ec4fd73912fde83b14083e77940ab6e)
2014-03-03 17:29:52 -05:00
Zev Benjamin
f6cec22e6d jabber_mirror: Do domain replacement more safely
(imported from commit 1a6a3d23120f06d54bc954d4e89d5fccf666332e)
2014-03-03 17:29:52 -05:00
Zev Benjamin
2aeb5dde67 jabber_mirror: Use str.replace instead of re.sub
(imported from commit 55798a06951366f0c3d246a243dbb3d41ee5b4f7)
2014-03-03 17:29:52 -05:00
Zev Benjamin
151370277c jabber_mirror: Use consistent method name casing
(imported from commit 0f68b94bab992ba20aa7c185fa40eafeea22f92e)
2014-03-03 17:29:52 -05:00
Zev Benjamin
adcec427b6 jabber_mirror: Factor out jid_to_zulip and use str.rpartition
(imported from commit 435f076d7125676b5b964c73ec1e3753496c32af)
2014-03-03 17:29:52 -05:00
Zev Benjamin
f7518ea853 jabber_mirror: Make copyright date clearer
(imported from commit a97382d174994be0592fbd98cdef1ed39c1b0400)
2014-03-03 17:29:51 -05:00
Tim Abbott
2ac428ad7d Add Jabber mirroring bot.
(imported from commit a539e1e9322bfbef4d93efce951f058d09fc58fe)
2014-03-03 17:29:51 -05:00
Jessica McKellar
df7f85d3c3 Don't show in-app notifications if stream desktop notifications are disabled.
(imported from commit efa29afaa40b65557149ea8a2cbc60e1bc44bee2)
2014-03-03 17:22:17 -05:00
Allen Rabinovich
2761f1338d Fix stream color changes
(imported from commit 37c0a2a5fba10404d9c51d1e4cdce7f45e18f54b)
2014-03-03 14:46:38 -07:00
Jessica McKellar
fae92685ae Convert /json/subscriptions/property to supporting bulk property updates.
This includes removing GET support for the endpoint, which is unused
and doesn't map well to this being a bulk endpoint.

(imported from commit 348ff9dfa84be1661368c6d7d35aebf2ae2a9ae0)
2014-03-03 16:08:33 -05:00
Jessica McKellar
816c0a4393 Add a validator for arguments that are of a variable type.
We'll need this to validate subscription properties, which can be
strings or booleans.

(imported from commit 2572e334cd04ffe05151cba266e15a0ea7ae21c5)
2014-03-03 16:08:33 -05:00
Jessica McKellar
4e24b432c4 [manual] Add script to migrate subs to new stream notification settings.
Previously, streams used `notifications`. Now they have separate
`desktop_notifications` and `audible_notifications`.

On staging, this should be run after the schema migration has been
applied (and technically before the code that uses the new fields is
deployed, but for staging, processing our notification settings a few
minutes late won't hurt anyone).

On prod, the script should be re-run just before the code using the
new notification settings is deployed to process any customer
notification settings changed since the staging deploy.

(imported from commit d99d238cd1b317c5180d7f940d70a7e2f8f9c712)
2014-03-03 16:08:33 -05:00
Jessica McKellar
66edc784f9 Generate and handle client-side events for global notification changes.
(imported from commit 40056e8ae284da27db0215e7d8320c8f7db2c52b)
2014-03-03 16:08:33 -05:00
Jessica McKellar
87635b9e32 Convert settings from static HTML to a template.
This will make life much easier for handling update events.

(imported from commit 66b101eb5fae89b4eec6fc797fee8be26ac99bfb)
2014-03-03 16:08:32 -05:00
Jessica McKellar
c96ceeaea4 Add a handlebars helper for variadic compound OR conditions.
(imported from commit 9f08e998f9f699c05ccf3f5948fe3361a3834ba1)
2014-03-03 16:08:32 -05:00
Jessica McKellar
88c8472a31 Clarify the cases in which you receive notifications.
(imported from commit 7b41b8a1f4baedbc744a6b222fa0ff3127e7a228)
2014-03-03 16:08:32 -05:00
Jessica McKellar
8a8efdc537 Use /usr/bin/env python for process_fts_updates.
`/usr/bin/env python` is almost always preferred over specifying the
specific python to run (and this script doesn't work for me on OSX
with /usr/bin/python specified).

(imported from commit 531e6062ba0ac1f25e3c681bb5cf83a918d0e3e7)
2014-03-03 16:08:32 -05:00
Jessica McKellar
07bb7b2fee Give users the option to propagate global stream changes.
This helps the common case of not liking our default of having audible
and desktop notifications enabled, and not making users adjust the
settings on every existing stream to fix it.

(imported from commit be75edb2c1385d1bd9a289416e2dffd8007f5e0a)
2014-03-03 16:08:32 -05:00
Jessica McKellar
e0bd15669a Don't post checkbox data directly to /json/notify_settings/change.
They have weird properties like not sending anything for unchecked
boxes, which makes it hard to wrap a client-agnostic API around.

(imported from commit fef73a57a55b218b55dab6be3453dd6eac73c789)
2014-03-03 16:08:32 -05:00
Jessica McKellar
7829e809c7 Factor notification settings success and error callbacks into functions.
(imported from commit 3bce060ac6ecbad075dbdb8b9ec5514b191f0f95)
2014-03-03 16:08:31 -05:00
Jessica McKellar
d89696291f Remove Notification (?) explanation popover.
(imported from commit f261f87c9571a76b8b0e2538ccb3bb4826ef449e)
2014-03-03 16:08:31 -05:00
Jessica McKellar
dfc462c24d Grey out per-stream notifications when you mute the stream.
This helps clarify that muting trumps notifications in most cases.

(imported from commit 1a6df169219d9501b1232cc7d2c64abec6fd03ea)
2014-03-03 16:08:31 -05:00
Jessica McKellar
b07f4efc13 Use new stream-level notification settings when notifying.
(imported from commit 8db2cf5a44ddc8a9ce285c5f0e50e049fea06573)
2014-03-03 16:08:31 -05:00
Jessica McKellar
53021bf7d3 Pass per-stream notification settings between frontend and backend.
(imported from commit 42e9b80a4c55e0911d457991d53ce71ca31625bb)
2014-03-03 16:08:31 -05:00
Jessica McKellar
600786983c [schema] Split Subscription notifications field into audible + desktop.
(imported from commit e160b9eb958fa5a06f990fccdeb25fa39e13e753)
2014-03-03 16:08:31 -05:00
Jessica McKellar
c673b3b0b1 Pass global stream notification settings between frontend and backend.
(imported from commit 28ec021e8e5166d3b270c81c5a4ad543d2185aa5)
2014-03-03 16:08:30 -05:00
Jessica McKellar
df39a7bde2 [schema] Add separate notification settings for streams.
(imported from commit 2122a4cc35e9a1f019eea004cd27ce703ba5a55a)
2014-03-03 16:08:30 -05:00
Tim Abbott
d75412764e Add Zulip ops apt key when installing new servers.
(imported from commit 5b8db30be24c08bc2fb4af548944776157e231dd)
2014-03-03 14:56:40 -05:00
Allen Rabinovich
2d0b9e2aa2 Make right side chevrons visible, lighten usernames, adjust stream list scrolling speed
(imported from commit 8068bdf1ae7fd817fda36d7e32ea94e850ab5675)
2014-03-01 15:11:45 -07:00
Zev Benjamin
db4770a577 [schema] Create new Message indices for development machines
This migration will do nothing on staging/prod since the indices already exist.
It is only for creating the indices in dev.

(imported from commit ac26a23641191ba73fbccc2eebc4a261ece6c624)
2014-03-01 12:41:45 -05:00
Steve Howell
0f96f5064e [schema] Add has_attachment/has_image/has_link to Message.
We will need to run these commands manually when deploying to staging:

    CREATE INDEX CONCURRENTLY "zerver_message_has_attachment" ON "zerver_message" ("has_attachment");
    CREATE INDEX CONCURRENTLY "zerver_message_has_image" ON "zerver_message" ("has_image");
    CREATE INDEX CONCURRENTLY "zerver_message_has_link" ON "zerver_message" ("has_link");

(imported from commit 84808dc6b1af887ddf784cb8a875ae462f4df985)
2014-03-01 12:41:00 -05:00
Zev Benjamin
0b29a2f53a migrate.py: Add function for conditionally creating an index
(imported from commit f0ca7cc83e334d4210d21d33afa2e0196172176e)
2014-03-01 12:33:41 -05:00
Zev Benjamin
230802ee22 migrate.py: Add multiple columns simultaneously
(imported from commit 6cd01fcce6a6e18ce57be6f4da1fd394120b1f99)
2014-03-01 12:33:41 -05:00
acrefoot
7a97d01719 Fix broken viewport.message_viewport_info() calculations
`#tab_bar_underpadding` overlaps some with `.message_header`,
so adding `#tab_bar_underpadding.bottom + .message_header.height`
gave us a nonsense message viewport top.

Doing the calculation this way is more robust, as long as:
1) `$(".floating_recipient").offset().top` continues to give us a sensical number
   and is the last element just before the top of the viewport.
2)  nothing appears between the composebox and viewport.

In this commit I also removed the other couple of places where the #tab_bar_underpadding
was being used as a viewport reference, that no longer makes sense.

(imported from commit c7f35e41309900c581d5e2329c1becf161d501d3)
2014-03-01 11:52:46 -05:00
Leo Franchi
3450d05858 Open link to boto project in new window
(imported from commit 7c36d4cd2bb8bff6c02261a2a5894965eb88e429)
2014-02-28 17:48:00 -05:00
Leo Franchi
de9d26126a Only cycle through stream elements when cycling through streams
(imported from commit 244d72e88e18cc49f32ecfada791f032140390f2)
2014-02-28 16:48:45 -05:00
Allen Rabinovich
ba0d3605ae Fix stream list scrollbar visibility
(imported from commit ef1f860ecd7f3ae908a69ac7c35a45d959505966)
2014-02-28 16:27:13 -05:00
Steve Howell
0983809e6f Fix URLs for stream/topic narrowing links in recipient bar.
(imported from commit 4e104cde912521dc360df1a32ce149a5082f9a67)
2014-02-28 16:27:13 -05:00
Steve Howell
6b200b3088 Fix broken link for "Link to this conversation".
(imported from commit bb07a1fe729c532cdc48eee63188b7b812fe07ff)
2014-02-28 16:27:12 -05:00
Leo Franchi
5807a44aee Activity ping handling during a reload should not error out
(imported from commit 63c9f935985cdd4f3d795191aae5aa8ab8bad02b)
2014-02-28 16:27:12 -05:00
Leo Franchi
dda8bf6d8a Don't error out if we somehow have a top message group but can't find a recipient row
(imported from commit 3b51f6a5e6e7998c33bf994316d5ba16e5cc0378)
2014-02-28 16:27:12 -05:00
Steve Howell
a27610f560 Make Realm.get_admin_users not do O(N) queries.
This commit makes it so that we don't individually query
auth_permission for every user on the realm during calls
to Realm.get_admin_users().  This should speed up page loads.

To apply this commit, we had to upgrade all of our servers
with this patch to django-guardian:

 https://github.com/lukaszb/django-guardian/pull/178#issuecomment-31049062

(imported from commit a1604bf573a5005c9abc128a680a7da6a20cabef)
2014-02-28 16:27:12 -05:00
Allen Rabinovich
dc15546ba3 Fix horizontal scroll on stream list
(imported from commit 2d28ea608c24e38b8cf58f3993976dcd67353831)
2014-02-27 23:15:55 -05:00
Allen Rabinovich
99036efa06 Disable keyboard scrolling in sidebar
(imported from commit eca509a90df175d21d85eb409c0db9c8fbb931ea)
2014-02-27 20:25:41 -05:00
Allen Rabinovich
a2d2438f03 Restyle pointer to make it visible at lower zoom levels
(imported from commit ef5f9e8878181350c823f796138fe652c9d14161)
2014-02-27 20:25:41 -05:00
Allen Rabinovich
8ea941e783 Fix bottom padding on stream list
(imported from commit 5f92b313919eadaa114da3a2fb1160f2eb3a30f5)
2014-02-27 20:25:41 -05:00
Allen Rabinovich
1eae686443 Add slim scrollbar to stream list
(imported from commit 58b64081db68fe9b1d2addcaece10167332d1a1b)
2014-02-27 20:25:41 -05:00
Steve Howell
f4764e58c6 Check Django block tags in check-templates.
(imported from commit a5d6336eeba63df365d3e59dce4d7f32aae637c7)
2014-02-27 20:25:40 -05:00
Steve Howell
5d0abd6f3f Add whitespace to django template tags.
(imported from commit 595328eab56d018319749234134e6b4e7ea0849f)
2014-02-27 20:25:40 -05:00
Steve Howell
98bc0b04c5 Clean up handling of HTML tags in check-templates.
(imported from commit 10f3ce97eecefcedc806d1a6a20ad230ebcf1f0f)
2014-02-27 20:25:40 -05:00
Steve Howell
a07299f1d6 Clean up while loop in check-templates.
(imported from commit 79c2cc2b1ced0fc80b0a1996fd9150b39e689a31)
2014-02-27 20:25:40 -05:00
Steve Howell
9da693c371 Simplify pulling out of tags in check-templates.
Before this change, the way we'd strip tags of punctuation
was just sort of messed up, because we'd strip the start tags
one way and strip the end tags another, and we had conditionals
for the different flavors of tags, instead of doing the stripping
when we already knew what flavor of tag we were dealing with.

(imported from commit 60c5ebd45e21b88bbfc98ff4b43dbbc6b32b38a1)
2014-02-27 20:25:39 -05:00
Jason Michalski
1788f5c576 Revert "Revert "Change out the gemoji emoji for android version""
This reverts commit 4d32b4ccf9a5134819a4d942699b4d97e2c0fd55.

(imported from commit 6aefec41f294ee83d19aebbfd9a99b2657e0ff83)
2014-02-27 20:25:39 -05:00
Luke Faraone
6a803a88c8 Return whether the user can be mobile-pushed in the presence endpoint
This allows clients to show an indication if users are on mobile or can
be reached via mobile.

(imported from commit 819c27a141f71dee32a97fd5c1ac405b039a5038)
2014-02-27 20:25:39 -05:00
Luke Faraone
f30a62e33c Use keyword arguments in UserPresence.to_presence_dict()
Also rename the function, which was previously called to_presense_dict.

This will let us be more flexible about adding additional values.

(imported from commit 323b7d2df53918928190c9ee9544b4599a5e2df3)
2014-02-27 20:25:38 -05:00
Luke Faraone
0ac73e4d73 Use a dict in presence_info rather than strings
This allows us to extend it to contain more details, as we will shortly.

(imported from commit 59b14592609810c5ac634a8237928ce029f33a83)
2014-02-27 20:25:38 -05:00
Steve Howell
61611a2dac Add zerver/lib/migrate.py
(imported from commit 612a791d05721fb633bb1992e5288adf951143c3)
2014-02-27 20:25:38 -05:00
Steve Howell
4bc50c3560 Rename NarrowBuilder.__call__ to add_term().
We also call the objects "builder" instead of "build."

(imported from commit aa3fcedc8eb97c21f29aa651cf1f6852ff311e7d)
2014-02-27 20:25:38 -05:00
Steve Howell
bf5ebf1d2d Check that handlebars tags are balanced in check-templates.
(imported from commit 4a36b874f5dab314cf5af5357bf0250d6fc1bd8b)
2014-02-27 20:25:37 -05:00
Steve Howell
f22665e710 Extract matching_tags() in check-templates.
(imported from commit bf54e656ba5f924298270c8e76b60faf78689099)
2014-02-27 20:25:37 -05:00
Steve Howell
7e49396fc5 Extract get_html_tag in check-templates.
(imported from commit 365a2bb4e9b2bf94f7b8e16a40fec0b461b64ab8)
2014-02-27 20:25:37 -05:00
Steve Howell
c7a9e08105 Extract check_our_files in check-templates.
(imported from commit 68049b19aacfb159a92e7142b9975a5376c0f9f5)
2014-02-27 20:25:37 -05:00
Steve Howell
c9140a6def Exclude muted streams in exclude_muting_conditions().
If we call exclude_muting_conditions() with a non-stream
narrow, it will now include a condition to exclude streams
that are not in your home view.  As of now, this code only
executes during testing, but it sets the stage for doing
better in:home queries on the back end.

(imported from commit bbd764bd0e9588a50e4a82c915e82a2c1b99d73e)
2014-02-27 20:25:37 -05:00
Steve Howell
5bb922200a Add test_exclude_muting_conditions() to test_messages
(imported from commit 6b6809f34af0b5802195ae0ac30352a020b871ec)
2014-02-27 20:25:36 -05:00
Steve Howell
b822c83b02 Avoid redundant query clauses for muted topics.
If we are already narrowing to a stream, then we can disregard
muted topics in all the other streams and create a simpler query
for the DB to execute.

(imported from commit 35a074a76eec99922034a381741355da3fdd5b39)
2014-02-27 20:25:36 -05:00
Steve Howell
fab6b0f7ae Handle non-existent streams in exclude_muting_conditions().
Due to the way we store muted topics, it is possible that a
muted topic stream name may no longer exist, and we need to
handle that case gracefully.

(imported from commit 4d18ec55e45213657a67e160848229678f212765)
2014-02-27 20:25:36 -05:00
Steve Howell
9d21787cd7 Extract exclude_muting_conditions() in messages.py
(imported from commit 97144097406377eb40383c7d1314c74dd713719c)
2014-02-27 20:25:35 -05:00
Steve Howell
f47a3c62e8 Add test_use_first_unread_anchor() test.
(imported from commit e2b4d30730725fd08e76868d9af6f36ddfd3b6f2)
2014-02-27 20:25:35 -05:00
Steve Howell
630187d91b Avoid glitches running single tests involving SqlAlchemy connections.
(imported from commit 90b34ead998e2daf9e73fff867c3efb78076f4e1)
2014-02-27 20:25:35 -05:00
Waseem Daher
243c327d0a Properly preview images from Dropbox photo albums.
Reported by jhurwitz (sorta).

(imported from commit 8ae4c5f7af86c5492842142b89be8cab1a2c3fae)
2014-02-27 20:25:35 -05:00
Leo Franchi
b80293c80d JIRA: Show all updated fields as long as one is not truthy
(imported from commit 543204b84a0b5625c4185b9ae32d5a3725cd9f9e)
2014-02-27 20:25:35 -05:00
Luke Faraone
e80c4f13b9 Don't include an "@" in mailname(5)
(imported from commit 84486373966c90d5fe2dd4af5966ae614628188f)
2014-02-27 20:25:34 -05:00
Allen Rabinovich
3fb3b564ae Make slow fade longer for unread markers
(imported from commit 728e977f1f128d4e9b3f5f602538b7b2caaa9303)
2014-02-27 20:25:34 -05:00
Leo Franchi
f605a7df22 Return an empty list instead of undefined when no groups are visible
(imported from commit 5a02b6b94acb20948c9959e9620df7fa5f945625)
2014-02-27 20:25:34 -05:00
Leo Franchi
63bcf98e71 Fade properly via groups when toggling fade on compose
(imported from commit 865c9daf8a267cfa65f7daceddff55a816b9c22c)
2014-02-27 20:25:34 -05:00
Leo Franchi
9275901277 Refactor viewport.visible_messages and add a viewport.visible_groups
(imported from commit 2cd29c41c1fb7ffc4c88673e81e638bbaad91f5f)
2014-02-27 20:25:34 -05:00
Leo Franchi
840ba90512 Show on-hover topic edits in message list
(imported from commit c2cd996c5e17b801e4e10b0a28451c0fb51c5e21)
2014-02-27 20:25:34 -05:00
Leo Franchi
b51ea69db0 Handle topic edits and rerender view if topics have changed
(imported from commit b59f6b532138d660e0acfb949b2eb223b5c5ed0e)
2014-02-27 20:25:33 -05:00
Luke Faraone
7658886b02 email_mirror: Use internal_send_message instead of the API
Previously, the email mirror queue worker used the API bindings to send
messages to Zulip, as if it were any other API client.

This is inefficient since we're running the worker inside the Django
context on a machine with database access; we can instead just use the
internal message-sending functions we use elsewhere. This also resolves
potential issues with SSL certificates, etc. that might occur when we
were previously making a HTTPS connection.

(imported from commit 6de8015829bec440f1af0199a2138828e86ed2a4)
2014-02-27 20:25:33 -05:00
Zev Benjamin
a547043831 Fix search highlighting for message content and topics
Previously topics weren't being highlighted at all and messages had their
highlighting persist across different narrows (because we were only checking
whether the message object had a match_content property, not whether it should
currently be used).

(imported from commit 44c91c6d5799dcdf765e19e1a17bd727ce80c918)
2014-02-27 20:25:33 -05:00
Zev Benjamin
865c57fa72 Allow our template partials to take additional named arguments
(imported from commit 20e7dae7b5d27ee34936d400394357fc31c8e628)
2014-02-27 20:25:32 -05:00
Luke Faraone
409bc7b657 Ship NOTICE for emoji and link to them from the web interface
(imported from commit d0020a3a0115f16540a256061078025fa1ae6526)
2014-02-27 20:25:32 -05:00
Leo Franchi
5aef8b8fad Maintain scroll position when removing selected message
(imported from commit 1021eac527e677fbcac46d0a7d44dd3244bb903e)
2014-02-27 20:25:32 -05:00
Jason Michalski
4a58241b17 Revert "Change out the gemoji emoji for android version"
This reverts commit 05a7245f7b52edf4f55e40d1467022d9f06d5792.

(imported from commit e2bb0346fc2913046e977d539326510fdcab73a5)
2014-02-27 20:25:32 -05:00
Leo Franchi
240050093b Preserve scroll when rerendering due to out-of-order messages
(imported from commit 9c339cbe8d5bbd75bbdf24a8f14da4f1556cc407)
2014-02-27 20:25:31 -05:00
Leo Franchi
f93ccd4df1 Enable local echo for all
(imported from commit 8c2e66009303b6937c7e0f1743293623e7404c3b)
2014-02-27 20:25:31 -05:00
Zev Benjamin
5dfd6eee2d Enable negated search for randomfish.org
(imported from commit 0a999aa18b47e1f021d7dc56f4ef5d4b0a8c8001)
2014-02-27 20:25:30 -05:00
Allen Rabinovich
ccfaee8412 Add left side color bar
(imported from commit cdba90d3a4e693838338b0a93cae38a741aa28c4)
2014-02-27 20:25:30 -05:00
Allen Rabinovich
efe8fe4650 Fix right sidebar offset to prevent it from overlapping the chevron
(imported from commit f5b979c30fa813ab5ac93382a68828415d7e0040)
2014-02-27 20:25:30 -05:00
Luke Faraone
f304b93b91 Quote "/"s in stream/topic names for digest emails
Previously, digest emails provided links to Zulip that didn't correctly
encode "/" if it occurred in a stream name or topic. By explicitly
specifying «safe=""», we can request that urllib.quote escape such
slashes.

Closes trac #2294.

(imported from commit 2e6334672969d4cf4032d2ea5dc80091af96d672)
2014-02-27 20:25:30 -05:00
acrefoot
7ebb3ec05d Fix message for PM outside current narrow
This resolve Trac #2270

(imported from commit ab814e8e50f48a53054c28f07579f65040edceb8)
2014-02-27 20:25:29 -05:00
Steve Howell
09958cbf66 s/Restore last draft?/Restore draft/ in compose box.
(imported from commit 6f15b35e4ced62628709ec039e477a8a3a16738e)
2014-02-27 20:25:29 -05:00
Leo Franchi
7fe74a9d2e Add a background color property to each message
(imported from commit add776a0814353650903258894e0db6fc8ec67b6)
2014-02-27 20:25:29 -05:00
Steve Howell
15f5884247 Focus textbox when editing PMs.
(imported from commit 152cb829779f808bf6ec65daa2cdc35da66e7e25)
2014-02-27 20:25:29 -05:00
Leo Franchi
dbb3bf6a4d Fade by groups when rerendering
(imported from commit 31f472bb87eaa03bf38dddcc696e843d93e68e08)
2014-02-27 20:25:28 -05:00
Leo Franchi
0e55e54bec Remove last_message class when manually splicing in new last message
(imported from commit d828cd56e797f3174c0a52240d673b708d894c33)
2014-02-27 20:25:28 -05:00
Leo Franchi
ffdfa203e8 Don't error out scrolling when there's nothing there
(imported from commit e2af794dafb93e3509c6fa5f28314ac8e21849b0)
2014-02-27 20:25:28 -05:00
Allen Rabinovich
13045f953f Fix casper tests
(imported from commit 9376ba39e827794e0c7bd2404c08d702596786a4)
2014-02-27 20:25:28 -05:00
Allen Rabinovich
3cd33c0fea Fix unread markers and selection border
(imported from commit 275f4f7d95c7842bfbfd5c47509b19275bba254e)
2014-02-27 20:25:28 -05:00
acrefoot
7390b6ec53 Use 'forced' when available to determine if it's a force-push
(imported from commit afbd1ed2efe2ce86ebd9639d514837211b7517b4)
2014-02-27 20:25:28 -05:00
Leo Franchi
1d601134ed Don't error out if we get an edit for a message that's out of view
(imported from commit 042cadc8657d048d0fd3a410af5adbbaeac7d92d)
2014-02-27 20:25:27 -05:00
Leo Franchi
5d013b78eb Show EDITED message on rerendered edited message
(imported from commit e06a951222597561a3e4dab7740fff00d95b2dd4)
2014-02-27 20:25:27 -05:00
Leo Franchi
cd16eb952c Keep selected message selected when re-rendering single message
(imported from commit 8f034dfe9037cb513506714fd9c369e22af7f83f)
2014-02-27 20:25:27 -05:00
Leo Franchi
54e8bb872c Use the dark color classes for recipient rows when needed
(imported from commit a77409964a185e6a8856e0577cc95bc78aa96e6d)
2014-02-27 20:25:27 -05:00
Leo Franchi
8ec1d9b552 [manual] Release desktop app 0.4.4
This requires a puppet apply on prod, as well as manually
updating the symlinks of Zulip-latest and Humbug-latest on
prod0

(imported from commit c5ef8cd0e2d156144531b35af9a8c5226f5bf750)
2014-02-27 20:25:26 -05:00
Steve Howell
71de0ac565 Add a test for rendering realm-specific emojis in JS.
(imported from commit 5909c02f9a7931f03d7131ae16b5fb70c74746aa)
2014-02-27 20:25:26 -05:00
Steve Howell
7f2f1ad533 Add test coverage for stream_data.home_view_stream_names.
As part of this, I also made test_basics() have a third
stream that makes false positives in the test less likely.

(imported from commit d5ba64ec9346741818e30abe9e9594788c339fab)
2014-02-27 20:25:26 -05:00
Jessica McKellar
f9d5a02710 Fix bug that hid digest email settings box for customers.
(imported from commit 6c1e3f53998eca0232fbfe66c62ab87b009bccd8)
2014-02-27 20:25:26 -05:00
Jason Michalski
5ad256fee7 Fix navigating away from the page in Firefox
When navigating away get_events will fail after we delete the event
queue before leaving the page. In that case we try to reload the page to
correct the problem. This happens before the page navigation is
complete, and then we reload zulip keeping the user captive. This was
only observed on on Firefox.

(imported from commit e001172e87a9f2ab7cf07a477e46b9d87752ac04)
2014-02-27 20:25:26 -05:00
Leo Franchi
fe826cdf2b Grab the message id from the FRB when narrowing
(imported from commit 5b33a1ef09b70bf4f244fe0305a3da3f1d027391)
2014-02-27 20:25:26 -05:00
Leo Franchi
0dbcdb94af Set the zid of the FRB parent to be a valid row id
(imported from commit 31c559270a1f848e11b45f5ebeea68eaf7385ce4)
2014-02-27 20:25:25 -05:00
Leo Franchi
d9bfef4848 message_list.view is a member not a function, do not try to call it
(imported from commit b1d609b5633a9ab42da7123a2d31a63d7627aeec)
2014-02-27 20:25:25 -05:00
Allen Rabinovich
1686d27633 Tweaks and changes to adjust for new message block markup
(imported from commit 78210c2b98976243ee1b516bd9400a3071dd8cd9)
2014-02-27 20:25:25 -05:00
Leo Franchi
f22885223f Remove message id list from group divs
(imported from commit 620a219b5e11db79bfea971fe40deb09173deb10)
2014-02-27 20:25:24 -05:00
Leo Franchi
305cf30c50 Render just one message when editing and updating
(imported from commit 5b28e96e9d410faf9b33a5b0a1b4423191e8de58)
2014-02-27 20:25:24 -05:00
Leo Franchi
b4e4a98de6 Split out single message template into a partial
(imported from commit 4670a5b5006d038ddbe94683cf2ea2c0be27f5ab)
2014-02-27 20:25:24 -05:00
Leo Franchi
7ebe3bf824 Add template unit tests for new message groups
(imported from commit 7e520630b5ae74850fcdd6ecccc114101f9feddb)
2014-02-27 20:25:24 -05:00
Leo Franchi
568c33f294 Render messages as groups of divs instead of individual rows
Now that we no longer use tables for our message list, we can
more logically group messages together.

(imported from commit 9923a092f91a45fe3ef06f2f00e23e4e3fb62a37)
2014-02-27 20:25:23 -05:00
Leo Franchi
748e5b6da6 Remove disabled summarization code
This experiment has been disabled for everyone for a while: if we
bring something like this back, it is not likely to be exactly the same,
and will be different enough to require a different implementation.

As it is, the summarization code was making a few code paths (rendering
especially) more complex, and is worth removing for simplicity's sake.

(imported from commit 6ac8cdc9f7077a5a1da01ab4268aba3db0bc43f8)
2014-02-27 20:25:23 -05:00
Leo Franchi
f128ff6d53 Remove firefox-specific table hack, as we're no longer using tables for messages
(imported from commit 0d4e171c11e77e4000a8bfe7cbb8fc13e827d54d)
2014-02-27 20:25:23 -05:00
Leo Franchi
174a62eb7c Remove requirement of no selected id to hide empty feed message
(imported from commit 10f4882a5f2def7e5b8567942758bb33007601d0)
2014-02-27 20:25:23 -05:00
Jason Michalski
22e6ab4028 Change out the gemoji emoji for android version
(imported from commit 6810746b991e597a668fca443189a16da93aa83c)
2014-02-27 20:25:22 -05:00
Jason Michalski
94db0466a7 Add scripts to extract emoji from the android fonts
(imported from commit 361d9570030a8b6a122c59b68b229c4f8382df32)
2014-02-27 20:25:22 -05:00
Steve Howell
ca92292550 Test people.update() more thoroughly.
(imported from commit 48b1a5af4f3849b7d21960181149dc99b74ba660)
2014-02-27 20:25:21 -05:00
Steve Howell
e16da5db45 Add test for people.get_rest_of_realm
(imported from commit 7cda63da29f7764e3932ce677bf3270adb6ea630)
2014-02-27 20:25:21 -05:00
Steve Howell
666252d749 Improve test coverage for get_topic_suggestions.
(imported from commit bba858e1f1f396f42d50e1e823ae0673d8013f53)
2014-02-27 20:25:21 -05:00
Steve Howell
ef92c345ea Test that "te" matches "Bob Terry" in search suggestions.
(imported from commit 777b7d554278170765e04fc9e1041826c509e8a2)
2014-02-27 20:25:21 -05:00
Steve Howell
75c3e91a15 Add test_stream_completion() to search_suggestion unit tests.
(imported from commit 84d1b1a7e0a667e3851b46e915a4f87d146013d4)
2014-02-27 20:25:20 -05:00
Luke Faraone
8075c6e5a8 Allow cycling between streams with shift+{A,D}
Closes trac #2273.

(imported from commit 858ffd47aa6dbb372d426fe94b860dfe1c1cce34)
2014-02-20 13:27:43 -05:00
Steve Howell
2ca0015c0a Cover more variations of narrowing in test_describe()
(imported from commit 145e9f624ea460c62a62f3da2d8e328642c5e2d6)
2014-02-20 11:38:51 -05:00
Steve Howell
55a862cc23 Test that narrow_stream is excluded from filter.public_operators()
(imported from commit 11c38d7108243f1496262a2cce982ec583c41894)
2014-02-20 11:38:51 -05:00
Steve Howell
c729965b69 Test negated topic searches in Filter.unparse
(imported from commit 0e1e74b25b7eb1874b93dd7d62e50563caff1ebe)
2014-02-20 11:38:51 -05:00
Steve Howell
b67d976809 Add test for parsing negated searches.
(imported from commit 91f79aa9cfdf939f7249c67a37d4420203c2ac63)
2014-02-20 11:38:51 -05:00
Steve Howell
3a9bdec149 Fix false positives in assert_same_operators in filter tests.
(imported from commit 8d15ec1ce113fabafbe791fb1068e4921508abeb)
2014-02-20 11:38:50 -05:00
Steve Howell
47b877357d Fix test to actually test Filter with default parameters.
(imported from commit 55b4557c8742bd2f1c8b1aa1e99a487d581fcfc4)
2014-02-20 11:38:50 -05:00
Steve Howell
1c4dcda639 Add test for in-home search when in our special narrow mode.
(imported from commit e6bc9fbd7b87377c7ed1d42e84a9b5cd369bb4fe)
2014-02-20 11:38:50 -05:00
Steve Howell
187796c3d4 Remove transitional defensive code in filter.js
(imported from commit b28877e8b187e3b019635b7b52a7d0a157466ce0)
2014-02-20 11:38:50 -05:00
Leo Franchi
38a4011a52 Return the realm domain if the requesting client requests it
(imported from commit c8e6e388460931076ae3d12b0c5a5dde46b39ffa)
2014-02-20 10:57:35 -05:00
Steve Howell
5631e7e624 Remove transitional defensive code in hashchange.js
(imported from commit b02de9a51426339f3fdbe74fb61b89f5dd4ce8d4)
2014-02-19 16:20:29 -05:00
Steve Howell
2a5dd139c8 Add node tests for hashchange.js
(imported from commit 20309e13dfea28400341e30a42e8f775479de773)
2014-02-19 16:19:16 -05:00
Steve Howell
2dd3776bc1 Consider .user-list-filter in right sidebar calculations.
(imported from commit f94100ba78d5756f20729ab6d752bc48af68ea3c)
2014-02-19 15:16:37 -05:00
Steve Howell
da874f8ec6 Add is:alerted to search help.
(imported from commit 0c545fb35af0040047fcf53c560941feee2da9ad)
2014-02-19 13:16:00 -05:00
Leo Franchi
07140e7f11 Don't overwrite already reified people
(imported from commit ab82e5b6b8bedfbd39e7c36892c0b401796a5fdb)
2014-02-19 12:49:39 -05:00
Steve Howell
2ce57fa5b9 Make sure Group PMs show in right sidebar.
If you have a lot more individual users in your realm than group
PMs in your recent history, we were squeezing out the Group PMS.
We now max out the ratio for any sub-section in the right sidebar,
as well as bumping up the min.

(imported from commit f7c44367f2a518d27406993cb6358cc96d1aae92)
2014-02-19 12:45:49 -05:00
Zev Benjamin
1a6929d9ae Handle get_old_messages case where num_before = 0 and num_after = 0 and a narrow is specified
Previously, we assumed that num_before or num_after would be always be non-zero
after adjustment for the anchor.  However, we don't adjust num_before or
num_after when a narrow is specified.

(imported from commit 9239fef140e109b11bdfbeef42e9fbed78660ad1)
2014-02-19 12:24:17 -05:00
Steve Howell
8ce5404777 Describe negated search terms correctly.
This changes Filter.describe and Filter.operator_to_prefix
to handle negated terms correctly.

(imported from commit 673c0d3a5a77784e95772c14e12534ad2daecda2)
2014-02-19 11:05:31 -05:00
Steve Howell
8611cc3977 Extract 'verb' variable in Filter functions.
Extract 'verb' in Filter.operator_to_prefix() and
Filter.describe().  This doesn't change any functionality;
it is designed to make a subsequent change have a less
noisy diff.

(imported from commit e9c4b6edc498d88ec1783ccdba079d980def9438)
2014-02-19 11:05:31 -05:00
Steve Howell
e645574b14 Add more test coverage to Filter.describe()
(imported from commit 9249af23e19b307f2ae168227aa73bba56b1a991)
2014-02-19 11:05:30 -05:00
Steve Howell
44564274a1 Move methods from search_suggestion to filter.
The methods describe() and operator_to_prefix() are
now in filter.js.  They seem like they eventually
may be useful outside the scope of search suggestions,
and they seem to go hand in hand with other Filter
responsibilities.

(imported from commit 55f14c3ee848febb2e7c8c6a27afd690569b4e08)
2014-02-19 11:05:30 -05:00
Jessica McKellar
f0c20d8acb nagios: give digest emails even more processing time before alerting.
(imported from commit 057511c22af39d147e4c4c499fee5a3fb7392786)
2014-02-18 16:07:31 -05:00
Jason Michalski
0244b50f0b Split bot deactivation from user deactivation
(imported from commit 153a870b244e040e3b5976f639866dbace5563f6)
2014-02-18 15:09:22 -05:00
Jason Michalski
d177f49a96 Change the create bot API to use rest_dispatch
(imported from commit 0fac290be2ed04178c4df866f5bc958441b2d320)
2014-02-18 15:09:20 -05:00
Jason Michalski
9d973ff106 Change get_bots API to use rest_dispatch
(imported from commit 921895dd636ba118a0f57e60a7bcb9dca1c7c605)
2014-02-18 15:09:19 -05:00
Allen Rabinovich
7822be5cd9 Fix failing stream sidebar node test
(imported from commit 3187a8f34389bf1f0b37e80edec9fb56f7281306)
2014-02-18 12:50:32 -07:00
Allen Rabinovich
d0572f50fb Miscellaneous style fixes for narrow window mode
(imported from commit f0a33be1640b2cb8810a0e7af52f453421cf0fe4)
2014-02-18 12:50:32 -07:00
Allen Rabinovich
b00ebd1bdf Miscellaneous fixes to message pane redesign
(imported from commit 8cedb21cb3a520dd9a28c943e047e8f73f410cae)
2014-02-18 12:50:32 -07:00
Allen Rabinovich
cff698d210 Restyle unread markers
(imported from commit 70a363cb50eebdd0bd2f11ab56074e46301117b3)
2014-02-18 12:50:32 -07:00
Allen Rabinovich
56f1c023ab Redesign elements in left sidebar
(imported from commit 37ae516325a4bd4db7a9e45e7862af6fee3af46e)
2014-02-18 12:50:32 -07:00
Allen Rabinovich
cdd43baf5d Add sticky class and an extra recipient bar wrapper
(imported from commit 17724a9e31d5baa5a011ead6d521dd7a4e6fe0e2)
2014-02-18 12:50:32 -07:00
Allen Rabinovich
b0d768b16b Visual adjustments for redesign
(imported from commit 79ab506f15671ae2c3d7c6d06213f24125eca603)
2014-02-18 12:50:32 -07:00
Allen Rabinovich
01a04c3169 Add offsets to fixed elements based on the width of the browser scrollbar.
(imported from commit 2026725165dead381d0b99181ef84a67a5bd6626)
2014-02-18 12:50:31 -07:00
acrefoot
8af170a3c3 update old messages' stream-color text class
(imported from commit 998611bd5b4e25985be73c9262a5c1e772f87ce1)
2014-02-18 12:50:31 -07:00
Jason Michalski
320c2b8eaf Fix casper tests for redesign
Commit "ecf0eb85 Redesign styles for message pane" removed the
right_part class, updates the tests to not use it.

(imported from commit 277eb3748913895b13ab7bdca11e668033c9f9b3)
2014-02-18 12:50:31 -07:00
Steve Howell
de8509e40d Fix broken template test.
(imported from commit a5d935ab84fd16d5fb83ff25fd773b251486c5cd)
2014-02-18 12:50:31 -07:00
Allen Rabinovich
dc71961dd9 Fix showing stream names on dark background
(imported from commit 82185ac2717b380e81656630d34f377094d16c38)
2014-02-18 12:50:31 -07:00
Allen Rabinovich
de65bb8194 Move the header and its menus to the top z-index
(imported from commit bbbc1f0f3868782959b13c0585435ca02300f9cb)
2014-02-18 12:50:31 -07:00
Allen Rabinovich
4c4cd1ed8e Fix top notification display to appear above the floating recipient bar
(imported from commit 0a5915af3589db09ee2bc294afced0a21352fde2)
2014-02-18 12:50:31 -07:00
Allen Rabinovich
da3ac9ae1b Implement new unread marker style as background for timestamp
(imported from commit e7782d98216f77f6a018c4c01e88aa57eb05144e)
2014-02-18 12:50:31 -07:00
Allen Rabinovich
48476fcbc5 Code cleanup: remove commented code and console logs
(imported from commit 20058b87775653f2d526c2d3249549402bc36807)
2014-02-18 12:50:30 -07:00
Allen Rabinovich
2c56e692a2 Fix floating recepient bar hiding when switching to settings pages
(imported from commit 9a643075197a53e84df196c3dcc1ce04766d3d4e)
2014-02-18 12:50:30 -07:00
Allen Rabinovich
235baf5187 Fix showing the private message floating recipient bar
(imported from commit 1ee76153dfe72627cbe43ea07b746407e5461da7)
2014-02-18 12:50:30 -07:00
Allen Rabinovich
9dd8779a3a Fix stream color change logic
(imported from commit 45dbc57bf28d6b4536fe7683b4a9ce1331d3d072)
2014-02-18 12:50:30 -07:00
Allen Rabinovich
9d68048d1d Fix edited message squashing against the timestamp
(imported from commit c3d39accc75930841ea1795d8df65d39f02574b6)
2014-02-18 12:50:30 -07:00
Allen Rabinovich
78a3da7fbe Fix issues with message editing and status message layouts
(imported from commit 3ec5c6ccf6c20a6c102075887b6ff36afc613bdd)
2014-02-18 12:50:30 -07:00
Allen Rabinovich
25331d8bb2 Adjust dividing line darkness, compose pane width
(imported from commit 5a0b59a5a967eb2e26291e9892ad89413b8fdd61)
2014-02-18 12:50:29 -07:00
Allen Rabinovich
ee3cb60e3c Redesign styles for message pane
(imported from commit 394249d58f1cc3b976b432bbc421b99510e7fff9)
2014-02-18 12:50:29 -07:00
Allen Rabinovich
8f90baf1eb Remove borders around messageboxes
(imported from commit 7ffaf256773daa2c2d79a6043c6e252e283fbaa9)
2014-02-18 12:50:29 -07:00
Allen Rabinovich
34f9cf3aa6 Restyle subject editing form
(imported from commit f2093939fa8069b73e7c785a4dd835eab4c825cd)
2014-02-18 12:50:29 -07:00
Allen Rabinovich
dbdc0a9721 Switch message pane headers to new design
(imported from commit f640641553779450f9d9d15e5586ef38e068367b)
2014-02-18 12:50:29 -07:00
Allen Rabinovich
e7e2f3a79c Modify crumbbar style to look like an arrowbar
Also:
  * Change fixed element positioning and fix bugs
  * Move settings dropdown back to the right and add left padding to left sidebar

(imported from commit fcf903b59617687f94618a01ce7544b69f408130)
2014-02-18 12:50:29 -07:00
Allen Rabinovich
29250a6692 Move crumbbar to header and change visual appearance
(imported from commit 435e3b46b615f6c496be10b7d170ed3e4201787d)
2014-02-18 12:50:29 -07:00
Steve Howell
8bae4d746d Remove unused json_to_list function.
(imported from commit 9da59ee4edd3c569f798710267db5400b9abdb30)
2014-02-18 14:24:04 -05:00
Steve Howell
4bc76b2d6d Handle more types of data in extract_recipients.
We now allow the list of recipients to be sent as a
comma-delimited string with optional JSON encoding.

(imported from commit e928b037bbd258348eb5b2ecca486d0bb77f593e)
2014-02-18 14:24:04 -05:00
Steve Howell
6edb758136 Add test_extract_recipients.
(imported from commit 13a5d1287fd489664c7f667d5b75a513f5f744c1)
2014-02-18 14:24:03 -05:00
Steve Howell
f1ee2c6503 Put "Link to this conversation" lower in the message menu.
(imported from commit 73d75ac40f097c161f7168a5590c069c1b9e0641)
2014-02-18 13:19:39 -05:00
Steve Howell
bbfd33185c Remove narrowing options from message chevron menu.
Remove the options to narrow by topic/person from the menu,
because there are better ways to do this in the UI, and
remove the time travel option, because the "Link to this
conversation" achieves mostly the same effect.

(imported from commit b7e0cfe64c0760e5a7bf7a8c9c05ed1a5b747300)
2014-02-18 13:19:39 -05:00
Steve Howell
580b6949cc Remove reply-to-person-only option from message chevron menu.
(imported from commit 469ebc9b01ee60eb8c0a673099e0dc735ea95a0e)
2014-02-18 13:19:39 -05:00
Steve Howell
64ff916ca2 Be concise in popover menus.
Say Edit/Reply/Collapse/etc. and omit phrases like "this message".

(imported from commit bcf0a8690683c1e0d54b7a6a58fe78b787271357)
2014-02-18 13:19:38 -05:00
Steve Howell
14281de262 Fix brittle layout for "Keyboard shortcuts" help.
Adding one row to the Navigation table made the
Keyboard shortcuts dialog look ridiculous, and it
was caused by a design based around float-left-ing
that broke down when the size of the "Navigation" box
was bigger than the "Composing messages" box.

Now we use a div to enclose the top two boxes in
the modal.

(imported from commit 90288ec288d4cf3d50ed7f5bcb48c8bb3d033f19)
2014-02-18 13:04:36 -05:00
Steve Howell
2c6d7e8e18 Support q hotkey to Search people.
(imported from commit eafaf5900461e2df52de9ddbdc49823bf6d9e403)
2014-02-18 13:04:36 -05:00
Steve Howell
2d09036466 Have ESC blur Search people if it is empty.
(imported from commit d816c8b24cabfbea964fec9cb043f8a00c05f205)
2014-02-18 13:04:35 -05:00
Steve Howell
ebce82b136 Eliminate json_to_dict and use check_dict instead.
All usages of json_to_dict were replaced with the check_dict
validator.  The check_dict validations can eventually be
extended to validate the keys and values of incoming data,
but now we just use check_dict([]) in all the places where
we had json_to_dict, which means we aren't checking for any
specific keys; we are just making sure it's a dictionary.

(imported from commit fc5add9a7ef149dfac2a9a6d9a153799c4c0c24d)
2014-02-18 13:02:08 -05:00
Steve Howell
3d04f5f738 Use check_list instead of json_to_list.
(imported from commit 9ead12bc2a4744b94a747ca27054124aacde7ae4)
2014-02-18 13:02:08 -05:00
Steve Howell
8b58d8574b Use check_bool instead of json_to_bool.
(imported from commit 52eb892a92e293d6ecb854c51bd7bd32355206c9)
2014-02-18 13:02:08 -05:00
Jessica McKellar
6c4295ed5b Fix broken Django templates on confirmation error page.
(imported from commit 7720fae5e31c8e4e3b5d71e42233eaf0be26115e)
2014-02-18 11:32:23 -05:00
Jason Michalski
fa285fd1a9 Use case insensitive matching when linkifying tweets
(imported from commit c8a897f05a79a2b23998ffe186c77a9f7af4ae7f)
2014-02-15 15:33:22 -05:00
Leo Franchi
54e24a5765 Disable push notifications regardless of idle status for zulip.com
(imported from commit a1a1d551b7bf1423ecb31cf6a230f59c888a8a82)
2014-02-14 13:35:27 -05:00
Steve Howell
0b0b9b9379 Remove custom code for customer14.invalid
(imported from commit efdc02e02c0dbdd29a09002897a294b5e820530f)
2014-02-14 11:15:50 -05:00
Luke Faraone
c33eeeee23 Open a PM from the peoplesearch list on <enter>
Closes trac #2274

(imported from commit 3238abe37b82a994769eebacbd5fced37fca9609)
2014-02-14 09:55:10 -05:00
Luke Faraone
89eef10d44 Match alert words inside markup.
We now will match an alert word even if it is used at the boundry of
bolding, backtick escaping, or caret quoting.

Closes trac #2186.

(imported from commit 984bc63eb621772c95a01ca5c5bfeb190767f71f)
2014-02-13 17:14:54 -05:00
Luke Faraone
4ebc4a4ef1 Expand characters allowed after an alertword.
We now support .';[ before a word and ';]! after.

Closes trac #2283.

(imported from commit b3e3cb3d8d49a8e74d0b6a108c5ec73e9d9b5f32)
2014-02-13 17:14:53 -05:00
Tim Abbott
d7e4429bb7 Revert "Add adjustments for browsers with fixed scrollbar"
This reverts commit 462a3eb5e6b83f9d8091b83e3f8dc458236938ed.

We're reverting this to see if it is the cause of our recent CSS
performance issues.

(imported from commit 6a0b041cfcb6770bbfda0d354444bad2d64459ab)
2014-02-13 16:41:03 -05:00
Tim Abbott
36e2929ee2 Revert "Add radix arguments to parseInt calls"
This reverts commit fd77a988f1aa5bbdf430fbbb710dc9774fa85aaa.

(imported from commit 3865250797dd2ae8ebc9d26f491b0decf1786e21)
2014-02-13 16:41:02 -05:00
Leo Franchi
acec697fe7 Report unnarrow times as well as narrow times
(imported from commit b3a889aa11dc112508c5a1d213f68e5223a879fc)
2014-02-13 14:45:22 -05:00
Steve Howell
91445035bc Add NarrowBuilder support for negated search conditions.
(imported from commit cdc426e342a6d735d321d78b6753ca5ad7c79c6f)
2014-02-13 14:14:25 -05:00
Steve Howell
fb27cbcd01 Handle negated streams in ok_to_include_history.
(imported from commit 0a049364e1d14f45db9f8e9aa5392039a01231eb)
2014-02-13 14:14:25 -05:00
Steve Howell
11ba6a17ab Extract ok_to_include_history() method in messages.py.
(imported from commit a88f5455bf658a8c52c92e7f0bedc301a605020b)
2014-02-13 14:14:25 -05:00
Steve Howell
aa90e265c2 Handle negated terms in operands/has_operand/has_operator.
For the Filter helper functions above, we generally want to
ignore negated search terms, since their existence should
really only impact filter predicates and nothing else on the
JS side.  The exception is search, where even the existence
of a negated search needs to be noted to know that we can't
apply a filter locally.

(imported from commit 8bbb410a85fefed549d359e4c779a134ad830c11)
2014-02-13 14:14:25 -05:00
Steve Howell
76ff3a526c Set negated flag explicity to false in JS code.
For negated search terms, we weren't explicitly setting
"negated" to false when callers left it undefined, which was
mostly fine, since undefined is falsey, but it is better to
define it explicitly for debugging/testing purposes.

(imported from commit 68a2790b510d17caed8ca11c38188545d1dcc347)
2014-02-13 14:14:24 -05:00
Steve Howell
2fb7c0059d Support negated searches on staging.
Behind a feature flag you can now do searches like this:

    -pm-with:othello@example.com is:private

The "-" in front of "pm-with" tells us to exclude messages
with Othello from our search.  We support "-" in front of
all operators, although the behavior for "-search:" and
and "-near:" doesn't really change in this commit.

Note that the filtering out of "negated" predicates only
happens on the client side in this commit.  On the server
side we ignore negated predicates and send back a superset
of the results.

(imported from commit 6cdeaf32f2d493fbbb838630f0da3da880b1ca18)
2014-02-13 14:14:24 -05:00
Zev Benjamin
41e3a89398 [manual] puppet: Puppetize Munin
To deploy this, the zulip_internal::base and zulip_internal::munin classes must
be added to nagios.zulip.net.

(imported from commit 50d6a4ed19fcc9c62c7104977d69043bf5b9bbf9)
2014-02-13 13:26:40 -05:00
Waseem Daher
98737a012e Properly prepopulate realm name on admin page.
Also, don't call it that.

(imported from commit baacd95be5b01373aa9423071ca72d917480e341)
2014-02-13 13:18:18 -05:00
Jason Michalski
044e3ced4f Fix how the hash URL is build for IE support
IE sometimes returns the pathname without a leading slash. Also
location.origin is not supported and must be build manually.

(imported from commit fb64478aeaac0f17d31021b7c370ff56781b48d1)
2014-02-13 12:39:24 -05:00
Leo Franchi
e0efae4d59 Alias ZulipDesktop client to website
(imported from commit 91e549bbc67b9d9f5edf35522b608aa397547edd)
2014-02-13 08:28:08 -05:00
Waseem Daher
cf13874c9d Change audible notification to a "knock" sound.
Sound is public-domain, from:
http://www.freesound.org/people/Vidsyn/sounds/113619/

(imported from commit e2f6f891f30bbb11496ef725f09587967022dd97)
2014-02-12 17:09:39 -05:00
Steve Howell
f4db89c7e9 Supported negated terms in filter predicates (JS).
(imported from commit b50527620b5b451b4d6e0dc073de4036fe2b7e1f)
2014-02-12 16:58:08 -05:00
Steve Howell
90bb689e13 Extract "cond" local var in NarrowBuilder methods.
This commit doesn't change any functionality, and it is
designed to make diffs for upcoming changes related to
negated conditions a bit easier to read.  This diff
looks a bit noiser than it really is due to some
reindentation of continuation lines.

(imported from commit 64c1cba98faa4bad4eaad122dd3de119caa880c0)
2014-02-12 16:58:07 -05:00
Jason Michalski
dd345bdece Make sure the hash we change to always starts with a #
(imported from commit b27d4a3b9b89b2576d4b1339d55d54ba338a576d)
2014-02-12 16:30:07 -05:00
Jessica McKellar
3a6df13360 Don't fade messages on different topics but the same stream.
(imported from commit 1bc2d49b346619609e73794d237faf2352b974b3)
2014-02-12 16:26:57 -05:00
Zev Benjamin
25d461c8f5 Exclude messages on muted topics when finding the first unread message in a narrow
(imported from commit 3151c401f689cc77e53cf34ffc49c7fd7d0a771a)
2014-02-12 16:23:34 -05:00
Leo Franchi
2efaf75b25 Release desktop app v0.4.3
(imported from commit 13f5b79ce483db22cfa136a1318eadc4d04eb746)
2014-02-12 16:18:34 -05:00
Tim Abbott
19dcc3f385 Disable centering narrows around first unread message on server.
(imported from commit 11b17c2874370d63528e2c9e978eb605da8005e4)
2014-02-12 15:34:33 -05:00
Jason Michalski
bd9cccffce Use pushState where supported to change the URL hash
This this removed one forced relayout of the page on unnarrow. This
saves about 100ms for me.

(imported from commit 0755f425abbe3d99b8a99765549a5bbf3c620b9a)
2014-02-12 15:19:10 -05:00
Tim Abbott
fcb8c106b1 Fix saving of pointer on server-initiated reload when narrowed.
Previously, we saved the current_msg_list selected id and then
restored it as the home_msg_list selected id, which could result in
the home view loading to the wrong place.

This takes some already bad code and makes it even more in need of
refactoring, but it does fix a pressing bug.  We should definitely
refactor both:

* the top of narrow.js
* the save/restore code in reload.js

after this, though.

(imported from commit bb2040219e4f545ba90bb04a696996cec2831484)
2014-02-12 14:40:38 -05:00
Tim Abbott
f4c514fbf3 hashchange: Fix indentation on main switch statement.
(imported from commit 1420cc2513e1bf6b80c8e52a6c0d3d66e82a5a1d)
2014-02-12 14:40:38 -05:00
Leo Franchi
eaa777b612 Use feature detection for bootstrap typeahead key handling
(imported from commit 1ce443d3e61920bf5842b31263141d4f175a6514)
2014-02-12 14:31:56 -05:00
Jason Michalski
2530009123 Use optparse for command line argument parsing
optparse was already being the interface change was conflicting with it.

(imported from commit abdb153484a98a46b21fa77cc6deb00afd615720)
2014-02-12 14:03:58 -05:00
Allen Rabinovich
15da5628a9 Add radix arguments to parseInt calls
(imported from commit fd77a988f1aa5bbdf430fbbb710dc9774fa85aaa)
2014-02-12 11:24:27 -07:00
Jason Michalski
97d4f2b009 Allow passing a bind interface to run-dev.py
This makes it simpler to test between two VMs by allowing you to bind to
non localhost interfaces.

(imported from commit f70755533b52ff8c49fd916941d2210fb8c33b47)
2014-02-12 11:59:45 -05:00
Jason Michalski
f31b61ea5b Pass the client's Host header to django as X-Forwarded-Host
This allows Django to build correct redirects to hostnames other than
localhost.

(imported from commit 886b345f29fc03518cedd93ecbcea0be251f3230)
2014-02-12 11:59:45 -05:00
Leo Franchi
502852541b Enable local echo for customer15.invalid redux
(imported from commit 88f13b58cfc8b68dc439138cc62aea3ff72868f1)
2014-02-12 11:53:50 -05:00
Allen Rabinovich
addfcbfc30 Add adjustments for browsers with fixed scrollbar
(imported from commit 462a3eb5e6b83f9d8091b83e3f8dc458236938ed)
2014-02-12 10:47:54 -05:00
Leo Franchi
c63f881518 Fix inverted boolean check for local messages in topic propagation
(imported from commit 2daf7c0c8729a785c3a1105803cbaed31f32128e)
2014-02-12 10:08:19 -05:00
1036 changed files with 24773 additions and 58641 deletions

2
.gitattributes vendored
View File

@@ -15,6 +15,6 @@
/zproject/test_settings.py export-ignore
/zerver/fixtures export-ignore
/zerver/tests.py export-ignore
/zerver/tests export-ignore
/frontend_tests export-ignore
/node_modules export-ignore
/humbug export-ignore

11
.gitignore vendored
View File

@@ -7,7 +7,7 @@
/prod-static
/errors/*
*.sw[po]
.DS_Store
*.DS_Store
event_queues.pickle
stats/
zerver/fixtures/available-migrations
@@ -26,3 +26,12 @@ manage.log
.kateproject.d/
.kateproject
*.kate-swp
event_queues.json
.vagrant
/zproject/dev-secrets.conf
static/js/bundle.js
static/third/gemoji/
static/third/zxcvbn/
tools/emoji_dump/bitmaps/
tools/emoji_dump/*.ttx
node_modules

22
.travis.yml Normal file
View File

@@ -0,0 +1,22 @@
before_install:
- nvm install 0.10
install:
- tools/travis/setup-$TEST_SUITE
cache:
- apt: false
env:
- TEST_SUITE=frontend
- TEST_SUITE=backend
- TEST_SUITE=production
- TEST_SUITE=py3k
language: python
python:
- "2.7"
# command to run tests
script:
- ./tools/travis/$TEST_SUITE
sudo: required
services:
- docker
addons:
postgresql: "9.3"

203
LICENSE
View File

@@ -1,5 +1,202 @@
Copyright <20> 2012-2013 Zulip, Inc.
This software is licensed under the Zulip Enterprise License Agreement.
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
Zulip can be reached at support@zulip.com.
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

363
README.dev.md Normal file
View File

@@ -0,0 +1,363 @@
Installing the Zulip Development environment
============================================
You will need a machine with at least 2GB of RAM available (see
https://github.com/zulip/zulip/issues/32 for a plan for how to
dramatically reduce this requirement).
Start by cloning this repository: `git clone https://github.com/zulip/zulip.git`
Using Vagrant
-------------
This is the recommended approach for all platforms, and will install
the Zulip development environment inside a VM or container and works
on any platform that supports Vagrant.
The best performing way to run the Zulip development environment is
using an LXC container on a Linux host, but we support other platforms
such as Mac via Virtualbox (but everything will be 2-3x slower).
* If your host is Ubuntu 15.04 or newer, you can install and configure
the LXC Vagrant provider directly using apt:
```
sudo apt-get install vagrant lxc lxc-templates cgroup-lite redir
vagrant plugin install vagrant-lxc
```
* If your host is Ubuntu 14.04, you will need to [download a newer
version of Vagrant](https://www.vagrantup.com/downloads.html), and
then do the following:
```
sudo apt-get install lxc lxc-templates cgroup-lite redir
sudo dpkg -i vagrant*.deb # in directory where you downloaded vagrant
vagrant plugin install vagrant-lxc
```
* For other Linux hosts with a kernel above 3.12, [follow the Vagrant
LXC installation
instructions](https://github.com/fgrehm/vagrant-lxc) to get Vagrant
with LXC for your platform.
* If your host is OS X or older Linux, [download VirtualBox](https://www.virtualbox.org/wiki/Downloads),
[download Vagrant](https://www.vagrantup.com/downloads.html), and install them both.
* If you're on OS X and have VMWare, it should be possible to patch
Vagrantfile to use the VMWare vagrant provider which should perform
much better than Virtualbox. Patches to do this by default if
VMWare is available are welcome!
* On Windows: You can use Vagrant and Virtualbox/VMWare on Windows
with Cygwin, similar to the Mac setup. Be sure to create your git
clone using `git clone https://github.com/zulip/zulip.git -c
core.autocrlf=false` to avoid Windows line endings being added to
files (this causes weird errors).
Once that's done, simply change to your zulip directory and run
`vagrant up` in your terminal to install the development server. This
will take a long time on the first run because Vagrant needs to
download the Ubuntu Trusty base image, but later you can run `vagrant
destroy` and then `vagrant up` again to rebuild the environment and it
will be much faster.
Once that finishes, you can run the development server as follows:
```
vagrant ssh -- -L9991:localhost:9991
# Now inside the container
cd /srv/zulip
source /srv/zulip-venv/bin/activate
./tools/run-dev.py --interface=''
```
To get shell access to the virtual machine running the server to run
lint, management commands, etc., use `vagrant ssh`.
(A small note on tools/run-dev.py: the `--interface=''` option will make
the development server listen on all network interfaces. While this
is correct for the Vagrant guest sitting behind a NAT, you probably
don't want to use that option when using run-dev.py in other environments).
At this point you should [read about using the development environment](https://github.com/zulip/zulip/blob/master/README.dev.md#using-the-development-environment).
Using provision.py without Vagrant
----------------------------------
If you'd like to install a Zulip development environment on a server
that's already running Ubuntu 14.04 Trusty, you can do that by just
running:
```
sudo apt-get update
sudo apt-get install -y python-pbs
python /srv/zulip/provision.py
cd /srv/zulip
source /srv/zulip-venv/bin/activate
./tools/run-dev.py
```
Note that there is no supported uninstallation process without Vagrant
(with Vagrant, you can just do `vagrant destroy` to clean up the
development environment).
By hand
-------
If you really want to install everything by hand, the below
instructions should work.
Install the following non-Python dependencies:
* libffi-dev — needed for some Python extensions
* postgresql 9.1 or later — our database (also install development headers)
* memcached (and headers)
* rabbitmq-server
* libldap2-dev
* python-dev
* redis-server — rate limiting
* tsearch-extras — better text search
* libfreetype6-dev - needed before you pip install Pillow to properly generate emoji PNGs
### On Debian or Ubuntu systems:
```
sudo apt-get install libffi-dev memcached rabbitmq-server libldap2-dev python-dev redis-server postgresql-server-dev-all libmemcached-dev libfreetype6-dev
# If on 12.04 or wheezy:
sudo apt-get install postgresql-9.1
wget https://dl.dropboxusercontent.com/u/283158365/zuliposs/postgresql-9.1-tsearch-extras_0.1.2_amd64.deb
sudo dpkg -i postgresql-9.1-tsearch-extras_0.1.2_amd64.deb
# If on 14.04:
sudo apt-get install postgresql-9.3
wget https://dl.dropboxusercontent.com/u/283158365/zuliposs/postgresql-9.3-tsearch-extras_0.1.2_amd64.deb
sudo dpkg -i postgresql-9.3-tsearch-extras_0.1.2_amd64.deb
# If on 15.04 or jessie:
sudo apt-get install postgresql-9.4
wget https://dl.dropboxusercontent.com/u/283158365/zuliposs/postgresql-9.4-tsearch-extras_0.1_amd64.deb
sudo dpkg -i postgresql-9.4-tsearch-extras_0.1_amd64.deb
```
Now continue with the "All systems" instructions below.
### On Fedora 22 (experimental):
These instructions are experimental and may have bugs; patches welcome!
```
sudo dnf install libffi-devel memcached rabbitmq-server openldap-devel python-devel redis postgresql-server postgresql-devel postgresql libmemcached-devel freetype-devel
```
Now continue with the Common to Fedora/CentOS instructions below.
### On CentOS 7 Core (experimental):
These instructions are experimental and may have bugs; patches welcome!
```
# Add user zulip to the system (not necessary if you configured zulip as the administrator
# user during the install process of CentOS 7).
useradd zulip
# Create a password for zulip user
passwd zulip
# Allow zulip to sudo
visudo
# Add this line after line `root ALL=(ALL) ALL`
zulip ALL=(ALL) ALL
# Switch to zulip user
su zulip
# Enable EPEL 7 repo so we can install rabbitmq-server, redis and other dependencies
sudo yum install https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
# Install dependencies
sudo yum install libffi-devel memcached rabbitmq-server openldap-devel python-devel redis postgresql-server \
postgresql-devel postgresql libmemcached-devel wget python-pip openssl-devel freetype-devel libjpeg-turbo-devel \
zlib-devel nodejs
# We need these packages to compile tsearch-extras
sudo yum groupinstall "Development Tools"
# clone Zulip's git repo and cd into it
cd && git clone https://github.com/zulip/zulip && cd zulip/
## NEEDS TESTING: The next few DB setup items may not be required at all.
# Initialize the postgres db
sudo postgresql-setup initdb
# Edit the postgres settings:
sudo vi /var/lib/pgsql/data/pg_hba.conf
# Change these lines:
host all all 127.0.0.1/32 ident
host all all ::1/128 ident
# to this:
host all all 127.0.0.1/32 md5
host all all ::1/128 md5
```
Now continue with the Common to Fedora/CentOS instructions below.
### Common to Fedora/CentOS instructions
```
# Build and install postgres tsearch-extras module
wget https://launchpad.net/~tabbott/+archive/ubuntu/zulip/+files/tsearch-extras_0.1.3.tar.gz
tar xvzf tsearch-extras_0.1.3.tar.gz
cd ts2
make
sudo make install
# Hack around missing dictionary files -- need to fix this to get
# the proper dictionaries from what in debian is the hunspell-en-us package.
sudo touch /usr/share/pgsql/tsearch_data/english.stop
sudo touch /usr/share/pgsql/tsearch_data/en_us.dict
sudo touch /usr/share/pgsql/tsearch_data/en_us.affix
# Edit the postgres settings:
sudo vi /var/lib/pgsql/data/pg_hba.conf
# Add this line before the first uncommented line to enable password auth:
host all all 127.0.0.1/32 md5
# Start the services
sudo systemctl start redis memcached rabbitmq-server postgresql
# Enable automatic service startup after the system startup
sudo systemctl enable redis rabbitmq-server memcached postgresql
```
Finally continue with the All Systems instructions below.
### All Systems:
```
pip install -r requirements.txt
./tools/download-zxcvbn
./tools/emoji_dump/build_emoji
./scripts/setup/generate_secrets.py -d
sudo cp ./puppet/zulip/files/postgresql/zulip_english.stop /usr/share/postgresql/9.3/tsearch_data/
./scripts/setup/configure-rabbitmq
./tools/postgres-init-dev-db
./tools/do-destroy-rebuild-database
./tools/postgres-init-test-db
./tools/do-destroy-rebuild-test-database
```
To start the development server:
```
./tools/run-dev.py
```
… and visit [http://localhost:9991/](http://localhost:9991/).
Using the Development Environment
=================================
Once the development environment is running, you can visit
<http://localhost:9991/> in your browser. By default, the development
server homepage just shows a list of the users that exist on the
server and you can login as any of them by just clicking on a user.
This setup saves time for the common case where you want to test
something other than the login process; to test the login process
you'll want to change AUTHENTICATION_BACKENDS in the not-PRODUCTION
case of `zproject/settings.py` from zproject.backends.DevAuthBackend
to use the auth method(s) you'd like to test.
While developing, it's helpful to watch the `run-dev.py` console
output, which will show any errors your Zulip development server
encounters.
When you make a change, here's a guide for what you need to do in
order to see your change take effect in Development:
* If you change Javascript or CSS, you'll just need to reload the
browser window to see changes take effect.
* If you change Python code used by the the main Django/Tornado server
processes, these services are run on top of Django's [manage.py
runserver](https://docs.djangoproject.com/en/1.8/ref/django-admin/#runserver-port-or-address-port),
which will automatically restart the Zulip Django and Tornado servers
whenever you save changes to Python code. You can watch this happen
in the `run-dev.py` console to make sure the backend has reloaded.
* The Python queue workers don't automatically restart when you save
changes (or when they stop running), so you will want to ctrl-C and
then restart `run-dev.py` manually if you are testing changes to the
queue workers or if a queue worker has crashed.
* If you change the database schema, you'll need to use the standard
Django migrations process to create and then run your migrations; see
the [new feature
tutorial](http://zulip.readthedocs.org/en/latest/new-feature-tutorial.html)
for an example. Additionally you should check out the [detailed
testing docs](http://zulip.readthedocs.org/en/latest/testing.html) for
how to run the tests properly after doing a migration.
(In production, everything runs under supervisord and thus will
restart if it crashes, and `upgrade-zulip` will take care of running
migrations and then cleanly restaring the server for you).
Running the test suite
======================
For more details, check out the [detailed testing
docs](http://zulip.readthedocs.org/en/latest/testing.html).
To run all the tests, do this:
```
./tools/test-all
```
For the Vagrant environment, you'll want to first enter the environment:
```
vagrant ssh
source /srv/zulip-venv/bin/activate
cd /srv/zulip
```
This runs the linter (`tools/lint-all`) plus all of our test suites;
they can all be run separately (just read `tools/test-all` to see
them). You can also run individual tests which can save you a lot of
time debugging a test failure, e.g.:
```
./tools/lint-all # Runs all the linters in parallel
./tools/test-backend zerver.test_bugdown.BugdownTest.test_inline_youtube
./tools/test-js-with-casper 10-navigation.js
./tools/test-js-with-node # Runs all node tests but is very fast
```
The above setup instructions include the first-time setup of test
databases, but you may need to rebuild the test database occasionally
if you're working on new database migrations. To do this, run:
```
./tools/postgres-init-test-db
./tools/do-destroy-rebuild-test-database
```
Possible testing issues
=======================
- When running the test suite, if you get an error like this:
```
sqlalchemy.exc.ProgrammingError: (ProgrammingError) function ts_match_locs_array(unknown, text, tsquery) does not exist
LINE 2: ...ECT message_id, flags, subject, rendered_content, ts_match_l...
^
```
… then you need to install tsearch-extras, described
above. Afterwards, re-run the `init*-db` and the
`do-destroy-rebuild*-database` scripts.
- When building the development environment using Vagrant and the LXC provider, if you encounter permissions errors, you may need to `chown -R 1000:$(whoami) /path/to/zulip` on the host before running `vagrant up` in order to ensure that the synced directory has the correct owner during provision. This issue will arise if you run `id username` on the host where `username` is the user running Vagrant and the output is anything but 1000.
This seems to be caused by Vagrant behavior; more information can be found here https://github.com/fgrehm/vagrant-lxc/wiki/FAQ#help-my-shared-folders-have-the-wrong-owner

149
README.md Normal file
View File

@@ -0,0 +1,149 @@
Zulip
=====
Zulip is a powerful, open source group chat application. Written in
Python and using the Django framework, Zulip supports both private
messaging and group chats via conversation streams.
Zulip also supports fast search, drag-and-drop file uploads, image
previews, group private messages, audible notifications,
missed-message emails, desktop apps, and much more.
Further information on the Zulip project and its features can be found
at https://www.zulip.org.
Installing the Zulip Development environment
============================================
The Zulip development environment is the recommened option for folks
interested in trying out Zulip. This is documented in
[README.dev.md](README.dev.md).
Running Zulip in production
===========================
Zulip in production only supports Ubuntu 14.04 right now, but work is
ongoing on adding support for additional platforms. The installation
process is documented in https://zulip.org/server.html and in more
detail in [README.prod.md](README.prod.md).
Contributing to Zulip
=====================
Zulip welcomes all forms of contributions! The page documents the
Zulip development process.
* **Pull requests**. Before a pull request can be merged, you need to to sign the [Dropbox
Contributor License Agreement](https://opensource.dropbox.com/cla/).
Also, please skim our [commit message style
guidelines](http://zulip.readthedocs.org/en/latest/code-style.html#commit-messages).
* **Testing**. The Zulip automated tests all run automatically when
you submit a pull request, but you can also run them all in your
development environment following the instructions in the [testing
section](https://github.com/zulip/zulip#running-the-test-suite) below.
* **Developer Documentation**. Zulip has a growing collection of
developer documentation on [Read The Docs](https://zulip.readthedocs.org/).
Recommended reading for new contributors includes the
[directory structure](http://zulip.readthedocs.org/en/latest/directory-structure.html) and
[new feature tutorial](http://zulip.readthedocs.org/en/latest/new-feature-tutorial.html).
* **Mailing list and bug tracker** Zulip has a [development discussion
mailing list](https://groups.google.com/forum/#!forum/zulip-devel) and
uses [GitHub issues](https://github.com/zulip/zulip/issues). Feel
free to send any questions or suggestions of areas where you'd love to
see more documentation to the list! Please report any security issues
you discover to support@zulip.com.
* **App codebases** This repository is for the Zulip server and web app; the
[desktop](https://github.com/zulip/zulip-desktop),
[Android](https://github.com/zulip/zulip-android), and
[iOS](https://github.com/zulip/zulip-ios) apps are separate
repositories.
How to get involved with contributing to Zulip
==============================================
First, subscribe to the Zulip [development discussion mailing list](https://groups.google.com/forum/#!forum/zulip-devel).
The Zulip project uses a system of labels in our [issue
tracker](https://github.com/zulip/zulip/issues) to make it easy to
find a project if you don't have your own project idea in mind or want
to get some experience with working on Zulip before embarking on a
larger project you have in mind:
* [Bite Size](https://github.com/zulip/zulip/labels/bite%20size):
Smaller projects that could be a great first contribution.
* [Integrations](https://github.com/zulip/zulip/labels/integrations).
Integrate Zulip with another piece of software and contribute it
back to the community! Writing an integration can be a great
started project. There's some brief documentation on the best way
to write integrations at https://github.com/zulip/zulip/issues/70.
* [Documentation](https://github.com/zulip/zulip/labels/documentation).
The Zulip project loves contributions of new documentation.
* [Help Wanted](https://github.com/zulip/zulip/labels/help%20wanted):
A broader list of projects that nobody is currently working on.
* [Platform support](https://github.com/zulip/zulip/labels/Platform%20support).
These are open issues about making it possible to install Zulip on a wider
range of platforms.
* [Bugs](https://github.com/zulip/zulip/labels/bug). Open bugs.
* [Feature requests](https://github.com/zulip/zulip/labels/enhancement).
Browsing this list can be a great way to find feature ideas to implement that
other Zulip users are excited about.
If you're excited about helping with an open issue, just post on the
conversation thread that you're working on it. You're encouraged to
ask questions on how to best implement or debug your changes -- the
Zulip maintainers are excited to answer questions to help you stay
unblocked and working efficiently.
We also welcome suggestions of features that you feel would be
valuable or changes that you feel would make Zulip a better open
source project, and are happy to support you in adding new features or
other user experience improvements to Zulip.
If you have a new feature you'd like to add, we recommend you start by
opening a GitHub issue about the feature idea explaining the problem
that you're hoping to solve and that you're excited to work on it. A
Zulip maintainer will usually reply within a day with feedback on the
idea, notes on any important issues or concerns, and and often tips on
how to implement or test it. Please feel free to ping the thread if
you don't hear a response from the maintainers -- we try to be very
responsive so this usually means we missed your message.
For significant changes to the visual design, user experience, data
model, or architecture, we highly recommend posting a mockup,
screenshot, or description of what you have in mind to zulip-devel@ to
get broad feedback before you spend too much time on implementation
details.
Finally, before implementing a larger feature, we highly recommend
looking at the new feature tutorial and coding style guidelines on
ReadTheDocs.
Feedback on how to make this development process more efficient, fun,
and friendly to new contributors is very welcome! Just shoot an email
to the Zulip Developers list with your thoughts.
License
=======
Copyright 2011-2015 Dropbox, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
The software includes some works released by third parties under other
free and open source licenses. Those works are redistributed under the
license terms under which the works were received. For more details,
see the ``THIRDPARTY`` file included with this distribution.

510
README.prod.md Normal file
View File

@@ -0,0 +1,510 @@
Zulip in production
===================
This documents the process for installing Zulip in a production environment.
Note that if you just want to play around with Zulip and see what it
looks like, it is easier to install it in a development environment
following the instructions in README.dev, since then you don't need to
worry about setting up SSL certificates and an authentication mechanism.
Recommended requirements:
* Server running Ubuntu Trusty
* At least 2 CPUs for production use with 100+ users
* At least 4GB of RAM for production use with 100+ users. We **strongly
recommend against installing with less than 2GB of RAM**, as you will
likely experience OOM issues. In the future we expect Zulip's RAM
requirements to decrease to support smaller installations (see
https://github.com/zulip/zulip/issues/32).
* At least 10GB of free disk for production use (more may be required
if you intend to store uploaded files locally rather than in S3
and your team uses that feature extensively)
* Outgoing HTTP(S) access to the public Internet.
* SSL Certificate for the host you're putting this on
(e.g. zulip.example.com). If you just want to see what
Zulip looks like, we recommend installing the development
environment detailed in README.md as that is easier to setup.
* Email credentials Zulip can use to send outgoing emails to users
(e.g. email address confirmation emails during the signup process,
missed message notifications, password reminders if you're not using
SSO, etc.).
Installing Zulip in production
==============================
These instructions should be followed as root.
(1) Install the SSL certificates for your machine to
`/etc/ssl/private/zulip.key` and `/etc/ssl/certs/zulip.combined-chain.crt`.
If you don't know how to generate an SSL certificate, you, you can
do the following to generate a self-signed certificate:
```
apt-get install openssl
openssl genrsa -des3 -passout pass:x -out server.pass.key 4096
openssl rsa -passin pass:x -in server.pass.key -out zulip.key
rm server.pass.key
openssl req -new -key zulip.key -out server.csr
openssl x509 -req -days 365 -in server.csr -signkey zulip.key -out zulip.combined-chain.crt
rm server.csr
cp zulip.key /etc/ssl/private/zulip.key
cp zulip.combined-chain.crt /etc/ssl/certs/zulip.combined-chain.crt
```
You will eventually want to get a properly signed certificate (and
note that at present the Zulip desktop app doesn't support
self-signed certificates), but this will let you finish the
installation process.
(2) Download [the latest built server tarball](https://www.zulip.com/dist/releases/zulip-server-latest.tar.gz)
and unpack it to `/root/zulip`, e.g.
```
wget https://www.zulip.com/dist/releases/zulip-server-latest.tar.gz
tar -xf zulip-server-latest.tar.gz
mv zulip-server-1.3.6 /root/zulip
```
(3) Run
```
/root/zulip/scripts/setup/install
```
This may take a while to run, since it will install a large number of
packages via apt.
(4) Configure the Zulip server instance by filling in the settings in
`/etc/zulip/settings.py`. Be sure to fill in all the mandatory
settings, enable at least one authentication mechanism, and do the
configuration required for that authentication mechanism to work.
See the section on "Authentication" below for more detail on
configuring authentication mechanisms.
(5) Run
```
su zulip -c /home/zulip/deployments/current/scripts/setup/initialize-database
```
This will report an error if you did not fill in all the mandatory
settings from `/etc/zulip/settings.py`. Once this completes
successfully, the main installation process will be complete, and if
you are planning on using password authentication, you should be able
to visit the URL for your server and register for an account.
(6) Subscribe to [the Zulip announcements Google Group](https://groups.google.com/forum/#!forum/zulip-announce)
to get announcements about new releases, security issues, etc.
Authentication and logging into Zulip the first time
====================================================
(As you read and follow the instructions in this section, if you run
into trouble, check out the troubleshooting advice in the next major
section.)
Once you've finished installing Zulip, configuring your settings.py
file, and initializing the database, it's time to login to your new
installation. By default, initialize-database creates 1 realm that
you can join, the `ADMIN_DOMAIN` realm (defined in
`/etc/zulip/settings.py`).
The `ADMIN_DOMAIN` realm is by default configured with the following settings:
* `restricted_to_domain=True`: Only people with emails ending with @ADMIN_DOMAIN can join.
* `invite_required=False`: An invitation is not required to join the realm.
* `invite_by_admin_only=False`: You don't need to be an admin user to invite other users.
* `mandatory_topics=False`: Users are not required to specify a topic when sending messages.
If you would like to change these settings, you can do so using the
Django management python shell (as the zulip user):
```
cd /home/zulip/deployments/current
./manage.py shell
from zerver.models import *
r = get_realm(settings.ADMIN_DOMAIN)
r.restricted_to_domain=False # Now anyone anywhere can login
r.save() # save to the database
```
If you realize you set `ADMIN_DOMAIN` wrong, in addition to fixing the
value in settings.py, you will also want to do a similar manage.py
process to set `r.domain = "newexample.com"`. If you've already
changed `ADMIN_DOMAIN` in settings.py, you can use
`Realm.objects.all()` in the management shell to find the list of
realms and pass the domain of the realm that is not "zulip.com" to
`get_realm`.
Depending what authentication backend you're planning to use, you will
need to do some additional setup documented in the `settings.py` template:
* For Google authentication, you need to follow the configuration
instructions around `GOOGLE_OAUTH2_CLIENT_ID` and `GOOGLE_CLIENT_ID`.
* For Email authentication, you will need to follow the configuration
instructions around outgoing SMTP from Django.
You should be able to login now. If you get an error, check
`/var/log/zulip/errors.log` for a traceback, and consult the next
section for advice on how to debug. If you aren't able to figure it
out, email zulip-help@googlegroups.com with the traceback and we'll
try to help you out!
You will likely want to make your own user account an admin user,
which you can do via the following management command:
```
./manage.py knight username@example.com -f
```
Now that you are an administrator, you will have a special
"Administration" tab linked to from the upper-right gear menu in the
Zulip app that lets you deactivate other users, manage streams, change
the Realm settings you may have edited using manage.py shell above,
etc.
You can also use `manage.py knight` with the
`--permission=api_super_user` argument to create API super users,
which are needed to mirror messages to streams from other users for
the IRC and Jabber mirroring integrations (see
`bots/irc-mirror.py` and `bots/jabber_mirror.py` for some detail on these).
There are a large number of useful management commands under
`zerver/manangement/commands/`; you can also see them listed using
`./manage.py` with no arguments.
One such command worth highlighting because it's a valuable feature
with no UI in the Administration page is `./manage.py realm_filters`,
which allows you to configure certain patterns in messages to be
automatically linkified, e.g. whenever someone mentions "T1234" it
could be auto-linkified to ticket 1234 in your team's Trac instance.
Checking Zulip is healthy and debugging the services it depends on
==================================================================
You can check if the zulip application is running using:
```
supervisorctl status
```
And checking for errors in the Zulip errors logs under
`/var/log/zulip/`. That contains one log file for each service, plus
`errors.log` (has all errors), `server.log` (logs from the Django and
Tornado servers), and `workers.log` (combined logs from the queue
workers).
After you change configuration in `/etc/zulip/settings.py` or fix a
misconfiguration, you will often want to restart the Zulip application.
You can restart Zulip using:
```
supervisorctl restart all
```
Similarly, you can stop Zulip using:
```
supervisorctl stop all
```
The Zulip application uses several major services to store and cache
data, queue messages, and otherwise support the Zulip application:
* postgresql
* rabbitmq-server
* nginx
* redis
* memcached
If one of these services is not installed or functioning correctly,
Zulip will not work. Below we detail some common configuration
problems and how to resolve them:
* An AMQPConnectionError traceback or error running rabbitmqctl
usually means that RabbitMQ is not running; to fix this, try:
```
service rabbitmq-server restart
```
If RabbitMQ fails to start, the problem is often that you are using
a virtual machine with broken DNS configuration; you can often
correct this by configuring `/etc/hosts` properly.
* If your browser reports no webserver is running, that is likely
because nginx is not configured properly and thus failed to start.
nginx will fail to start if you configured SSL incorrectly or did
not provide SSL certificates. To fix this, configure them properly
and then run:
```
service nginx restart
```
If you run into additional problems, [please report
them](https://github.com/zulip/zulip/issues) so that we can update
these lists! The Zulip installation scripts logs its full output to
`/var/log/zulip/install.log`, so please include the context for any
tracebacks from that log.
Making your Zulip instance awesome
==================================
Once you've got Zulip setup, you'll likely want to configure it the
way you like. There are four big things to focus on:
(1) Integrations. We recommend setting up integrations for the major
tools that your team works with. For example, if you're a software
development team, you may want to start with integrations for your
version control, issue tracker, CI system, and monitoring tools.
Spend time configuring these integrations to be how you like them --
if an integration is spammy, you may want to change it to not send
messages that nobody cares about (E.g. for the zulip.com trac
integration, some teams find they only want notifications when new
tickets are opened, commented on, or closed, and not every time
someone edits the metadata).
If Zulip doesn't have an integration you want, you can add your own!
Most integrations are very easy to write, and even more complex
integrations usually take less than a day's work to build. We very
much appreciate contributions of new integrations; there is a brief
draft integration writing guide [here](https://github.com/zulip/zulip/issues/70).
It can often be valuable to integrate your own internal processes to
send notifications into Zulip; e.g. notifications of new customer
signups, new error reports, or daily reports on the team's key
metrics; this can often spawn discussions in response to the data.
(2) Streams and Topics. If it feels like a stream has too much
traffic about a topic only of interest to some of the subscribers,
consider adding or renaming streams until you feel like your team is
working productively.
Second, most users are not used to topics. It can require a bit of
time for everyone to get used to topics and start benefitting from
them, but usually once a team is using them well, everyone ends up
enthusiastic about how much topics make life easier. Some tips on
using topics:
* When replying to an existing conversation thread, just click on the
message, or navigate to it with the arrow keys and hit "r" or
"enter" to reply on the same topic
* When you start a new conversation topic, even if it's related to the
previous conversation, type a new topic in the compose box
* You can edit topics to fix a thread that's already been started,
which can be helpful when onboarding new batches of users to the platform.
Third, setting default streams for new users is a great way to get
new users involved in conversations before they've accustomed
themselves with joining streams on their own. You can use the
[`set_default_streams`](https://github.com/zulip/zulip/blob/master/zerver/management/commands/set_default_streams.py)
command to set default streams for users within a realm:
```
python manage.py set_default_streams --domain=example.com --streams=foo,bar,...
```
(3) Notification settings. Zulip gives you a great deal of control
over which messages trigger desktop notifications; you can configure
these extensively in the `/#settings` page (get there from the gear
menu). If you find the desktop notifications annoying, consider
changing the settings to only trigger desktop notifications when you
receive a PM or are @-mentioned.
(4) The mobile and desktop apps. Currently, the Zulip Desktop app
only supports talking to servers with a properly signed SSL
certificate, so you may find that you get a blank screen when you
connect to a Zulip server using a self-signed certificate.
The Zulip iOS and Android apps in their respective stores don't yet
support talking to non-zulip.com servers; the iOS app is waiting on
Apple's app store review, while the Android app is waiting on someone
to do the small project of adding a field to specify what Zulip server
to talk to.
These issues will likely all be addressed in the coming weeks; make
sure to join the zulip-announce@googlegroups.com list so that you can
receive the announcements when these become available.
(5) All the other features: Hotkeys, emoji, search filters,
@-mentions, etc. Zulip has lots of great features, make sure your
team knows they exist and how to use them effectively.
(6) Enjoy your Zulip installation! If you discover things that you
wish had been documented, please contribute documentation suggestions
either via a GitHub issue or pull request; we love even small
contributions, and we'd love to make the Zulip documentation cover
everything anyone might want to know about running Zulip in
production.
Maintaining and upgrading Zulip in production
=============================================
We recommend reading this entire section before doing your first
upgrade.
* To upgrade to a new version of the zulip server, download the
appropriate release tarball from
https://www.zulip.com/dist/releases/ to a path readable by the zulip
user (e.g. /home/zulip), and then run as root:
```
/home/zulip/deployments/current/scripts/upgrade-zulip zulip-server-VERSION.tar.gz
```
Be sure to download to a path readable by the Zulip user (see
https://github.com/zulip/zulip/issues/208 for details on this
issue) but then run the upgrade as root.
The upgrade process will shut down the service, run `apt-get
upgrade`, a puppet apply, and any database migrations, and then
bring the service back up. This will result in some brief downtime
for the service, which should be under 30 seconds unless there is an
expensive transition involved. Unless you have tested the upgrade
in advance, we recommend doing upgrades at off hours.
You can create your own release tarballs from a copy of zulip.git
repository using `tools/build-release-tarball`.
* **Warning**: If you have modified configuration files installed by
Zulip (e.g. the nginx configuration), the Zulip upgrade process will
overwrite your configuration when it does the `puppet apply`. You
can test whether this will happen assuming no upstream changes to
the configuration using `scripts/zulip-puppet-apply` (without the
`-f` option), which will do a test puppet run and output and changes
it would make. Using this list, you can save a copy of any files
that you've modified, do the upgrade, and then restore your
configuration. If you need to do this, please report the issue so
that we can make the Zulip puppet configuration flexible enough to
handle your setup.
* The Zulip upgrade script automatically logs output to
/var/log/zulip/upgrade.log; please use those logs to include output
that shows all errors in any bug reports.
* The Zulip upgrade process works by creating a new deployment under
/home/zulip/deployments/ containing a complete copy of the Zulip
server code, and then moving the symlinks at
`/home/zulip/deployments/current` and /root/zulip` as part of the
upgrade process. This means that if the new version isn't working,
you can quickly downgrade to the old version by using
`/home/zulip/deployments/<date>/scripts/restart-server` to return to
a previous version that you've deployed (the version is specified
via the path to the copy of `restart-server` you call).
* To update your settings, simply edit `/etc/zulip/settings.py` and then
run `/home/zulip/deployments/current/scripts/restart-server` to
restart the server
* You are responsible for running `apt-get upgrade` on your system on
a regular basis to ensure that it is up to date with the latest
security patches.
* To use the Zulip API with your Zulip server, you will need to use the
API endpoint of e.g. `https://zulip.example.com/api`. Our Python
API example scripts support this via the
`--site=https://zulip.example.com` argument. The API bindings
support it via putting `site=https://zulip.example.com` in your
.zuliprc.
Every Zulip integration supports this sort of argument (or e.g. a
`ZULIP_SITE` variable in a zuliprc file or the environment), but this
is not yet documented for some of the integrations (the included
integration documentation on `/integrations` will properly document
how to do this for most integrations). Pull requests welcome to
document this for those integrations that don't discuss this!
* Similarly, you will need to instruct your users to specify the URL
for your Zulip server when using the Zulip desktop and mobile apps.
* As a measure to mitigate the impact of potential memory leaks in one
of the Zulip daemons, the service automatically restarts itself
every Sunday early morning. See `/etc/cron.d/restart-zulip` for the
precise configuration.
Remote User SSO Authentication
==============================
Zulip supports integrating with a corporate Single-Sign-On solution.
There are a few ways to do it, but this section documents how to
configure Zulip to use an SSO solution that best supports Apache and
will set the `REMOTE_USER` variable:
(0) Check that `/etc/zulip/settings.py` has
`zproject.backends.ZulipRemoteUserBackend` as the only enabled value
in the `AUTHENTICATION_BACKENDS` list, and that `SSO_APPEND_DOMAIN` is
correct set depending on whether your SSO system uses email addresses
or just usernames in `REMOTE_USER`.
Make sure that you've restarted the Zulip server since making this
configuration change.
(1) Edit `/etc/zulip/zulip.conf` and change the `puppet_classes` line to read:
```
puppet_classes = zulip::voyager, zulip::apache_sso
```
(2) As root, run `/home/zulip/deployments/current/scripts/zulip-puppet-apply`
to install our SSO integration.
(3) To configure our SSO integration, edit
`/etc/apache2/sites-available/zulip-sso.example` and fill in the
configuration required for your SSO service to set `REMOTE_USER` and
place your completed configuration file at `/etc/apache2/sites-available/zulip-sso`
(4) Run `a2ensite zulip-sso` to enable the Apache integration site.
Now you should be able to visit `https://zulip.example.com/` and
login via the SSO solution.
### Troubleshooting Remote User SSO
This system is a little finicky to networking setup (e.g. common
issues have to do with /etc/hosts not mapping settings.EXTERNAL_HOST
to the Apache listening on 127.0.0.1/localhost, for example). It can
often help while debugging to temporarily change the Apache config in
/etc/apache2/sites-available/zulip-sso to listen on all interfaces
rather than just 127.0.0.1 as you debug this. It can also be helpful
to change /etc/nginx/zulip-include/app.d/external-sso.conf to
proxy_pass to a more explicit URL possibly not over HTTPS when
debugging. The following log files can be helpful when debugging this
setup:
* /var/log/zulip/{errors.log,server.log} (the usual places)
* /var/log/nginx/access.log (nginx access logs)
* /var/log/apache2/zulip_auth_access.log (you may want to change
LogLevel to "debug" in the apache config file to make this more
verbose)
Here's a summary of how the remote user SSO system works assuming
you're using HTTP basic auth; this summary should help with
understanding what's going on as you try to debug:
* Since you've configured /etc/zulip/settings.py to only define the
zproject.backends.ZulipRemoteUserBackend, zproject/settings.py
configures /accounts/login/sso as HOME_NOT_LOGGED_IN, which makes
`https://zulip.example.com/` aka the homepage for the main Zulip
Django app running behind nginx redirect to /accounts/login/sso if
you're not logged in.
* nginx proxies requests to /accounts/login/sso/ to an Apache instance
listening on localhost:8888 apache via the config in
/etc/nginx/zulip-include/app.d/external-sso.conf (using the upstream
localhost:8888 defined in /etc/nginx/zulip-include/upstreams).
* The Apache zulip-sso site which you've enabled listens on
localhost:8888 and presents the htpasswd dialogue; you provide
correct login information and the request reaches a second Zulip
Django app instance that is running behind Apache with with
REMOTE_USER set. That request is served by
`zerver.views.remote_user_sso`, which just checks the REMOTE_USER
variable and either logs in (sets a cookie) or registers the new
user (depending whether they have an account).
* After succeeding, that redirects the user back to / on port 443
(hosted by nginx); the main Zulip Django app sees the cookie and
proceeds to load the site homepage with them logged in (just as if
they'd logged in normally via username/password).
Again, most issues with this setup tend to be subtle issues with the
hostname/DNS side of the configuration. Suggestions for how to
improve this SSO setup documentation are very welcome!

570
THIRDPARTY Normal file
View File

@@ -0,0 +1,570 @@
Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Upstream-Name: Zulip
Upstream-Contact: Zulip Development Discussion <zulip-devel@googlegroups.com>
Source: https://zulip.org/
Comment:
Unless otherwise noted, the Zulip software is distributed under the Apache
License, Version 2.0. The software includes some works released by third
parties under other free and open source licenses. Those works are
redistributed under the license terms under which the works were received.
.
While Dropbox has sought to provide complete and accurate licensing
information for each FOSS package, Dropbox does not represent or warrant
that the licensing information provided herein is correct or error-free.
Recipients of the Zulip software should investigate the identified FOSS
packages to confirm the accuracy of the licensing information provided.
Recipients are also encouraged to notify Dropbox of any inaccurate
information or errors found in these notices.
Files: *
Copyright: 2011-2015 Dropbox, Inc.
License: Apache-2
Files: api/*
Copyright: 2012-2014 Dropbox, Inc
License: Expat
Files: api/integrations/perforce/git_p4.py
Copyright: 2007 Simon Hausmann <simon@lst.de>,
2007 Trolltech ASA
License: Expat
Comment: https://raw.github.com/git/git/34022ba/git-p4.py
Files: bots/jabber_mirror_backend.py
Copyright: 2013 Permabit, Inc., 2013-2014 Dropbox, Inc.
License: Expat
Files: confirmation/*
Copyright: 2008, Jarek Zgoda <jarek.zgoda@gmail.com>
License: BSD-3-Clause
Files: puppet/apt/*
Copyright: 2011, Evolving Web Inc.
License: Expat
Files: puppet/common/*
Copyright: 2007, David Schmitt
License: BSD-3-Clause
Comment: https://github.com/DavidS/puppet-common
Distribution includes a file `lib/puppet/parser/functions/ip_to_cron.rb` which
we removed due to unclear license
Files: puppet/stdlib/*
Copyright: 2011, Krzysztof Wilczynski
2011, Puppet Labs Inc
License: Apache-2.0
File: puppet/zulip_internal/files/mediawiki/Auth_remoteuser.php
Copyright: 2006 Otheus Shelling
2007 Rusty Burchfield
2009 James Kinsman
2010 Daniel Thomas
2010 Ian Ward Comfort
License: GPL-2.0
Comment: Not linked.
Files: puppet/zulip_internal/files/nagios_plugins/check_debian_packages
Copyright: 2005 Francesc Guasch
License: GPL-2.0
Comment: Not linked.
Files: puppet/zulip_internal/files/nagios_plugins/check_postgres.pl
Copyright: 2007-2015 Greg Sabino Mullane
License: BSD-2-Clause
Files: puppet/zulip_internal/files/nagios_plugins/check_website_response.sh
Copyright: 2011 Chris Freeman
License: GPL-2.0
Files: puppet/zulip_internal/files/trac/cgi-bin/
Copyright: 2003-2009 Edgewall Software
2003-2004 Jonas Borgström <jonas@edgewall.com>
License: BSD-3-Clause
Files: puppet/zulip_internal/files/pagerduty_nagios.pl
Copyright: 2011, PagerDuty, Inc.
License: BSD-3-Clause
Files: puppet/zulip_internal/files/zulip-ec2-configure-interfaces
Copyright: 2013, Dropbox, Inc.
License: Expat
Files: static/audio/zulip.*
Copyright: 2011 Vidsyn
License: CC-0-1.0
Files: static/styles/thirdparty-fonts.css
Copyright: 2012-2013 Dave Gandy
License: Expat
Files: static/third/fontawesome/*
Copyright: 2012-2013 Dave Gandy
License: SIL-OFL-1.1
Files: static/third/bootstrap/bootstrap-btn.css
Copyright: 2011-2014 Twitter, Inc
License: Expat
Files: static/third/bootstrap/css/bootstrap-responsive.css static/third/bootstrap/css/bootstrap.css
Copyright: 2012 Twitter, Inc
License: Apache-2.0
Comment: The software has been modified.
Files: static/third/bootstrap/js/bootstrap.js
Copyright: 2012 Twitter, Inc
License: Apache-2.0
Comment: The software has been modified.
Files: static/third/bootstrap-notify/*
Copyright: 2013 Nijiko Yonskai
2012 Goodybag, Inc.
2012 Twitter, Inc
License: Apache-2.0
Comment: The software has been modified.
Files: static/third/gemoji/images/emoji/unicode/* tools/emoji_dump/*.ttf
Copyright: Google, Inc.
License: Apache-2.0
Comment: These are actually Noto Emoji, not gemoji.
Files: static/third/html5-formdata/formdata.js
Copyright: 2010 François de Metz
License: Expat
Comment: See https://github.com/francois2metz/html5-formdata
Files: src/zulip/static/third/jquery/*
Copyright: 2011, John Resig
2011, The Dojo Foundation
License: Expat
Files: static/third/jquery-autosize/jquery.autosize.js
Copyright: 2013 Jack Moore
License: Expat
Files: static/third/jquery-caret/*
Copyright: 2010 C.F., Wong
License: Expat
Files: static/third/jquery-filedrop/jquery.filedrop.js
Copyright: Resopollution
License: Expat
Files: static/third/jquery-form/jquery.form.js
Copyright: M. Alsup
License: Expat or GPL-2.0
Files: static/third/jquery-idle/jquery.idle.js
Copyright: 2011-2013 Henrique Boaventura
License: Expat
Comment: The software has been modified.
Files: static/third/jquery-mousewheel/jquery.mousewheel.js
Copyright: 2011 Brandon Aaron
License: Expat
Files: static/third/jquery-perfect-scrollbar/*
Copyright: 2012 HyeonJe Jun
License: Expat
Files: static/third/jquery-throttle-debounce/*
Copyright: 2010 "Cowboy" Ben Alman
License: Expat or GPL
Files: static/third/jquery-validate/*
Copyright: 2006 - 2011 Jörn Zaefferer
License: Expat
Files: src/zulip/static/third/lazyload/*
Copyright: 2011 Ryan Grove
License: Expat
Files: static/third/marked/*
Copyright: 2011-2013, Christopher Jeffrey
License: Expat
Files: static/third/sockjs/sockjs-0.3.4.js
Copyright: 2011-2012 VMware, Inc.
2012 Douglas Crockford
License: Expat and public-domain
Files: static/third/sorttable/sorttable.js
Copyright: 2007 Stuart Langridge
License: X11
Files: static/third/sourcesans/*
Copyright: 2010, 2012, 2014 Adobe Systems Incorporated
License: SIL-OFL-1.1
Files: static/third/spectrum/*
Copyright: 2013 Brian Grinstead
License: Expat
Files: static/third/spin/spin.js
Copyright: 2011-2013 Felix Gnass
License: Expat
Files: static/third/underscore/underscore.js
Copyright: 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
License: Expat
Comment: https://github.com/jashkenas/underscore/blob/master/LICENSE
Files: static/third/winchan/*
Copyright: 2012 Lloyd Hilaiel
License: Expat
Comment: https://github.com/mozilla/winchan
Files: static/third/xdate/*
Copyright: 2010 C. F., Wong
License: Expat
Files: static/third/zocial/*
Copyright: Sam Collins
License: Expat
Files: tools/inject-messages/othello
Copyright: Shakespeare
License: public-domain
Files: tools/jslint/jslint.js
Copyright: 2002 Douglas Crockford
License: XXX-good-not-evil
Files: tools/python-proxy
Copyright: 2009 F.bio Domingues
License: Expat
Files: tools/review
Copyright: 2010 Ksplice, Inc.
License: Apache-2.0
Files: zerver/lib/bugdown/codehilite.py zerver/lib/bugdown/fenced_code.py
Copyright: 2006-2008 Waylan Limberg
License: BSD-3-Clause
Comment: https://pypi.python.org/pypi/Markdown
Files: zerver/lib/ccache.py
Copyright: 2013 David Benjamin and Alan Huang
License: Expat
Files: frontend_tests/casperjs/*
Copyright: 2011-2012 Nicolas Perriault
Joyent, Inc. and other Node contributors
License: Expat
Files: frontend_tests/casperjs/modules/vendors/*
Copyright: 2011, Jeremy Ashkenas
License: Expat
License: Apache-2.0
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
.
http://www.apache.org/licenses/LICENSE-2.0
.
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
.
On Debian systems, the full text of the Apache License version 2 can
be found in /usr/share/common-licenses/Apache-2.0.
License: BSD-2-clause
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice(s), this list of conditions and the following disclaimer
unmodified other than the allowable addition of one or more
copyright notices.
2. Redistributions in binary form must reproduce the above copyright
notice(s), this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
License: BSD-3-Clause
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
.
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
.
3. Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
License: CC-0-1.0
Creative Commons CC0 1.0 Universal
CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN
ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS INFORMATION
ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES REGARDING THE
USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED HEREUNDER, AND
DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM THE USE OF THIS DOCUMENT
OR THE INFORMATION OR WORKS PROVIDED HEREUNDER.
.
Statement of Purpose
.
The laws of most jurisdictions throughout the world automatically confer
exclusive Copyright and Related Rights (defined below) upon the creator
and subsequent owner(s) (each and all, an "owner") of an original work
of authorship and/or a database (each, a "Work").
.
Certain owners wish to permanently relinquish those rights to a Work for
the purpose of contributing to a commons of creative, cultural and
scientific works ("Commons") that the public can reliably and without
fear of later claims of infringement build upon, modify, incorporate in
other works, reuse and redistribute as freely as possible in any form
whatsoever and for any purposes, including without limitation commercial
purposes. These owners may contribute to the Commons to promote the
ideal of a free culture and the further production of creative, cultural
and scientific works, or to gain reputation or greater distribution for
their Work in part through the use and efforts of others.
.
For these and/or other purposes and motivations, and without any
expectation of additional consideration or compensation, the person
associating CC0 with a Work (the "Affirmer"), to the extent that he or
she is an owner of Copyright and Related Rights in the Work, voluntarily
elects to apply CC0 to the Work and publicly distribute the Work under
its terms, with knowledge of his or her Copyright and Related Rights in
the Work and the meaning and intended legal effect of CC0 on those
rights.
.
1. Copyright and Related Rights. A Work made available under CC0 may be
protected by copyright and related or neighboring rights ("Copyright and
Related Rights"). Copyright and Related Rights include, but are not
limited to, the following:
.
i. the right to reproduce, adapt, distribute, perform, display,
communicate, and translate a Work;
.
ii. moral rights retained by the original author(s) and/or performer(s);
.
iii. publicity and privacy rights pertaining to a person's image or
likeness depicted in a Work;
.
iv. rights protecting against unfair competition in regards to a Work,
subject to the limitations in paragraph 4(a), below;
.
v. rights protecting the extraction, dissemination, use and reuse of
data in a Work;
.
vi. database rights (such as those arising under Directive 96/9/EC of
the European Parliament and of the Council of 11 March 1996 on the legal
protection of databases, and under any national implementation thereof,
including any amended or successor version of such directive); and
.
vii. other similar, equivalent or corresponding rights throughout the
world based on applicable law or treaty, and any national
implementations thereof.
.
2. Waiver. To the greatest extent permitted by, but not in contravention
of, applicable law, Affirmer hereby overtly, fully, permanently,
irrevocably and unconditionally waives, abandons, and surrenders all of
Affirmer's Copyright and Related Rights and associated claims and causes
of action, whether now known or unknown (including existing as well as
future claims and causes of action), in the Work (i) in all territories
worldwide, (ii) for the maximum duration provided by applicable law or
treaty (including future time extensions), (iii) in any current or
future medium and for any number of copies, and (iv) for any purpose
whatsoever, including without limitation commercial, advertising or
promotional purposes (the "Waiver"). Affirmer makes the Waiver for the
benefit of each member of the public at large and to the detriment of
Affirmer's heirs and successors, fully intending that such Waiver shall
not be subject to revocation, rescission, cancellation, termination, or
any other legal or equitable action to disrupt the quiet enjoyment of
the Work by the public as contemplated by Affirmer's express Statement
of Purpose.
.
3. Public License Fallback. Should any part of the Waiver for any reason
be judged legally invalid or ineffective under applicable law, then the
Waiver shall be preserved to the maximum extent permitted taking into
account Affirmer's express Statement of Purpose. In addition, to the
extent the Waiver is so judged Affirmer hereby grants to each affected
person a royalty-free, non transferable, non sublicensable, non
exclusive, irrevocable and unconditional license to exercise Affirmer's
Copyright and Related Rights in the Work (i) in all territories
worldwide, (ii) for the maximum duration provided by applicable law or
treaty (including future time extensions), (iii) in any current or
future medium and for any number of copies, and (iv) for any purpose
whatsoever, including without limitation commercial, advertising or
promotional purposes (the "License"). The License shall be deemed
effective as of the date CC0 was applied by Affirmer to the Work. Should
any part of the License for any reason be judged legally invalid or
ineffective under applicable law, such partial invalidity or
ineffectiveness shall not invalidate the remainder of the License, and
in such case Affirmer hereby affirms that he or she will not (i)
exercise any of his or her remaining Copyright and Related Rights in the
Work or (ii) assert any associated claims and causes of action with
respect to the Work, in either case contrary to Affirmer's express
Statement of Purpose.
.
4. Limitations and Disclaimers.
.
a. No trademark or patent rights held by Affirmer are waived, abandoned,
surrendered, licensed or otherwise affected by this document.
.
b. Affirmer offers the Work as-is and makes no representations or
warranties of any kind concerning the Work, express, implied, statutory
or otherwise, including without limitation warranties of title,
merchantability, fitness for a particular purpose, non infringement, or
the absence of latent or other defects, accuracy, or the present or
absence of errors, whether or not discoverable, all to the greatest
extent permissible under applicable law.
.
c. Affirmer disclaims responsibility for clearing rights of other
persons that may apply to the Work or any use thereof, including without
limitation any person's Copyright and Related Rights in the Work.
Further, Affirmer disclaims responsibility for obtaining any necessary
consents, permissions or other rights required for any use of the Work.
.
d. Affirmer understands and acknowledges that Creative Commons is not a
party to this document and has no duty or obligation with respect to
this CC0 or use of the Work.
License: Expat
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
.
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
License: GPL-2.0
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2, dated June, 1991.
.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
.
On Debian systems, the complete text of the GNU General Public License
can be found in /usr/share/common-licenses/GPL-2 file.
License: SIL-OFL-1.1
---------------------------------------------------------------------------
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
---------------------------------------------------------------------------
.
PREAMBLE
.
The goals of the Open Font License (OFL) are to stimulate worldwide development
of collaborative font projects, to support the font creation efforts of academic
and linguistic communities, and to provide a free and open framework in which
fonts may be shared and improved in partnership with others.
.
The OFL allows the licensed fonts to be used, studied, modified and redistributed
freely as long as they are not sold by themselves. The fonts, including any
derivative works, can be bundled, embedded, redistributed and/or sold with any
software provided that any reserved names are not used by derivative works. The
fonts and derivatives, however, cannot be released under any other type of license.
The requirement for fonts to remain under this license does not apply to any
document created using the fonts or their derivatives.
.
DEFINITIONS
.
"Font Software" refers to the set of files released by the Copyright Holder(s) under
this license and clearly marked as such. This may include source files, build
scripts and documentation.
.
"Reserved Font Name" refers to any names specified as such after the copyright
statement(s).
.
"Original Version" refers to the collection of Font Software components as
distributed by the Copyright Holder(s).
.
"Modified Version" refers to any derivative made by adding to, deleting, or
substituting -- in part or in whole -- any of the components of the Original Version,
by changing formats or by porting the Font Software to a new environment.
.
"Author" refers to any designer, engineer, programmer, technical writer or other
person who contributed to the Font Software.
.
PERMISSION & CONDITIONS
.
Permission is hereby granted, free of charge, to any person obtaining a copy of the
Font Software, to use, study, copy, merge, embed, modify, redistribute, and sell
modified and unmodified copies of the Font Software, subject to the following
conditions:
.
1) Neither the Font Software nor any of its individual components, in Original or
Modified Versions, may be sold by itself.
.
2) Original or Modified Versions of the Font Software may be bundled, redistributed
and/or sold with any software, provided that each copy contains the above copyright
notice and this license. These can be included either as stand-alone text files,
human-readable headers or in the appropriate machine-readable metadata fields within
text or binary files as long as those fields can be easily viewed by the user.
.
3) No Modified Version of the Font Software may use the Reserved Font Name(s) unless
explicit written permission is granted by the corresponding Copyright Holder. This
restriction only applies to the primary font name as presented to the users.
.
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font Software shall
not be used to promote, endorse or advertise any Modified Version, except to
acknowledge the contribution(s) of the Copyright Holder(s) and the Author(s) or with
their explicit written permission.
.
5) The Font Software, modified or unmodified, in part or in whole, must be distributed
entirely under this license, and must not be distributed under any other license. The
requirement for fonts to remain under this license does not apply to any document
created using the Font Software.
.
TERMINATION
.
This license becomes null and void if any of the above conditions are not met.
.
DISCLAIMER
.
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER
RIGHT. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR
INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE.

34
Vagrantfile vendored Normal file
View File

@@ -0,0 +1,34 @@
# -*- mode: ruby -*-
VAGRANTFILE_API_VERSION = "2"
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
# For LXC. VirtualBox hosts use a different box, described below.
config.vm.box = "fgrehm/trusty64-lxc"
# The Zulip development environment runs on 9991 on the guest.
config.vm.network "forwarded_port", guest: 9991, host: 9991, host_ip: "127.0.0.1"
config.vm.synced_folder ".", "/vagrant", disabled: true
config.vm.synced_folder ".", "/srv/zulip"
config.vm.provider "virtualbox" do |vb, override|
override.vm.box = "ubuntu/trusty64"
# 2GiB seemed reasonable here. The VM OOMs with only 1024MiB.
vb.memory = 2048
end
$provision_script = <<SCRIPT
set -x
set -e
sudo apt-get update
sudo apt-get install -y python-pbs
python /srv/zulip/provision.py
SCRIPT
config.vm.provision "shell",
# We want provision.py to be run with the permissions of the vagrant user.
privileged: false,
inline: $provision_script
end

View File

@@ -1,4 +1,5 @@
from __future__ import absolute_import
from __future__ import print_function
from django.core.management.base import BaseCommand

View File

@@ -1,4 +1,5 @@
from __future__ import absolute_import
from __future__ import print_function
import datetime
import pytz
@@ -19,6 +20,6 @@ class Command(BaseCommand):
date = datetime.datetime.now() - datetime.timedelta(days=1)
else:
date = datetime.datetime.strptime(options["date"], "%Y-%m-%d")
print "Activity data for", date
print activity_averages_during_day(date)
print "Please note that the total registered user count is a total for today"
print("Activity data for", date)
print(activity_averages_during_day(date))
print("Please note that the total registered user count is a total for today")

View File

@@ -1,4 +1,5 @@
from __future__ import absolute_import
from __future__ import print_function
from optparse import make_option
from django.core.management.base import BaseCommand
@@ -63,7 +64,7 @@ def compute_stats(log_level):
logging.info("Top %6s | %s%%" % (size, round(top_percents[size], 1)))
grand_total = sum(total_counts.values())
print grand_total
print(grand_total)
logging.info("%15s | %s" % ("Client", "Percentage"))
for client in total_counts.keys():
logging.info("%15s | %s%%" % (client, round(100. * total_counts[client] / grand_total, 1)))

View File

@@ -1,4 +1,5 @@
from __future__ import absolute_import
from __future__ import print_function
from zerver.lib.statistics import seconds_usage_between
@@ -16,7 +17,7 @@ def analyze_activity(options):
if options["realm"]:
user_profile_query = user_profile_query.filter(realm__domain=options["realm"])
print "Per-user online duration:\n"
print("Per-user online duration:\n")
total_duration = datetime.timedelta(0)
for user_profile in user_profile_query:
duration = seconds_usage_between(user_profile, day_start, day_end)
@@ -25,11 +26,11 @@ def analyze_activity(options):
continue
total_duration += duration
print "%-*s%s" % (37, user_profile.email, duration, )
print("%-*s%s" % (37, user_profile.email, duration, ))
print "\nTotal Duration: %s" % (total_duration,)
print "\nTotal Duration in minutes: %s" % (total_duration.total_seconds() / 60.,)
print "Total Duration amortized to a month: %s" % (total_duration.total_seconds() * 30. / 60.,)
print("\nTotal Duration: %s" % (total_duration,))
print("\nTotal Duration in minutes: %s" % (total_duration.total_seconds() / 60.,))
print("Total Duration amortized to a month: %s" % (total_duration.total_seconds() * 30. / 60.,))
class Command(BaseCommand):
help = """Report analytics of user activity on a per-user and realm basis.
@@ -42,7 +43,7 @@ It will correctly not count server-initiated reloads in the activity statistics.
The duration flag can be used to control how many days to show usage duration for
Usage: python manage.py analyze_user_activity [--realm=zulip.com] [--date=2013-09-10] [--duration=1]
Usage: python2.7 manage.py analyze_user_activity [--realm=zulip.com] [--date=2013-09-10] [--duration=1]
By default, if no date is selected 2013-09-10 is used. If no realm is provided, information
is shown for all realms"""

View File

@@ -1,4 +1,5 @@
from __future__ import absolute_import
from __future__ import print_function
from django.core.management.base import BaseCommand
from django.db.models import Count
@@ -13,9 +14,13 @@ class Command(BaseCommand):
Usage examples:
python manage.py client_activity
python manage.py client_activity zulip.com
python manage.py client_activity jesstess@zulip.com"""
python2.7 manage.py client_activity
python2.7 manage.py client_activity zulip.com
python2.7 manage.py client_activity jesstess@zulip.com"""
def add_arguments(self, parser):
parser.add_argument('arg', metavar='<arg>', type=str, nargs='?', default=None,
help="realm or user to estimate client activity for")
def compute_activity(self, user_activity_objects):
# Report data from the past week.
@@ -44,26 +49,27 @@ python manage.py client_activity jesstess@zulip.com"""
counts.sort()
for count in counts:
print "%25s %15d" % (count[1], count[0])
print "Total:", total
print("%25s %15d" % (count[1], count[0]))
print("Total:", total)
def handle(self, *args, **options):
if len(args) == 0:
if options['arg'] is None:
# Report global activity.
self.compute_activity(UserActivity.objects.all())
elif len(args) == 1:
else:
arg = options['arg']
try:
# Report activity for a user.
user_profile = get_user_profile_by_email(args[0])
user_profile = get_user_profile_by_email(arg)
self.compute_activity(UserActivity.objects.filter(
user_profile=user_profile))
except UserProfile.DoesNotExist:
try:
# Report activity for a realm.
realm = get_realm(args[0])
realm = get_realm(arg)
self.compute_activity(UserActivity.objects.filter(
user_profile__realm=realm))
except Realm.DoesNotExist:
print "Unknown user or domain %s" % (args[0],)
print("Unknown user or domain %s" % (arg,))
exit(1)

View File

@@ -1,4 +1,5 @@
from __future__ import absolute_import
from __future__ import print_function
import datetime
import pytz
@@ -6,7 +7,7 @@ import pytz
from django.core.management.base import BaseCommand
from django.db.models import Count
from zerver.models import UserProfile, Realm, Stream, Message, Recipient, UserActivity, \
Subscription, UserMessage
Subscription, UserMessage, get_realm
MOBILE_CLIENT_LIST = ["Android", "ios"]
HUMAN_CLIENT_LIST = MOBILE_CLIENT_LIST + ["website"]
@@ -16,6 +17,10 @@ human_messages = Message.objects.filter(sending_client__name__in=HUMAN_CLIENT_LI
class Command(BaseCommand):
help = "Generate statistics on realm activity."
def add_arguments(self, parser):
parser.add_argument('realms', metavar='<realm>', type=str, nargs='*',
help="realm to generate statistics for")
def active_users(self, realm):
# Has been active (on the website, for now) in the last 7 days.
activity_cutoff = datetime.datetime.now(tz=pytz.utc) - datetime.timedelta(days=7)
@@ -61,52 +66,51 @@ class Command(BaseCommand):
fraction = 0.0
else:
fraction = numerator / float(denominator)
print "%.2f%% of" % (fraction * 100,), text
print("%.2f%% of" % (fraction * 100,), text)
def handle(self, *args, **options):
if args:
if options['realms']:
try:
realms = [Realm.objects.get(domain=domain) for domain in args]
except Realm.DoesNotExist, e:
print e
realms = [get_realm(domain) for domain in options['realms']]
except Realm.DoesNotExist as e:
print(e)
exit(1)
else:
realms = Realm.objects.all()
for realm in realms:
print realm.domain
print(realm.domain)
user_profiles = UserProfile.objects.filter(realm=realm, is_active=True)
active_users = self.active_users(realm)
num_active = len(active_users)
print "%d active users (%d total)" % (num_active, len(user_profiles))
print("%d active users (%d total)" % (num_active, len(user_profiles)))
streams = Stream.objects.filter(realm=realm).extra(
tables=['zerver_subscription', 'zerver_recipient'],
where=['zerver_subscription.recipient_id = zerver_recipient.id',
'zerver_recipient.type = 2',
'zerver_recipient.type_id = zerver_stream.id',
'zerver_subscription.active = true']).annotate(count=Count("name"))
print "%d streams" % (streams.count(),)
print("%d streams" % (streams.count(),))
for days_ago in (1, 7, 30):
print "In last %d days, users sent:" % (days_ago,)
print("In last %d days, users sent:" % (days_ago,))
sender_quantities = [self.messages_sent_by(user, days_ago) for user in user_profiles]
for quantity in sorted(sender_quantities, reverse=True):
print quantity,
print ""
print(quantity, end=' ')
print("")
print "%d stream messages" % (self.stream_messages(realm, days_ago),)
print "%d one-on-one private messages" % (self.private_messages(realm, days_ago),)
print "%d messages sent via the API" % (self.api_messages(realm, days_ago),)
print "%d group private messages" % (self.group_private_messages(realm, days_ago),)
print("%d stream messages" % (self.stream_messages(realm, days_ago),))
print("%d one-on-one private messages" % (self.private_messages(realm, days_ago),))
print("%d messages sent via the API" % (self.api_messages(realm, days_ago),))
print("%d group private messages" % (self.group_private_messages(realm, days_ago),))
num_notifications_enabled = len(filter(lambda x: x.enable_desktop_notifications == True,
active_users))
num_notifications_enabled = len([x for x in active_users if x.enable_desktop_notifications == True])
self.report_percentage(num_notifications_enabled, num_active,
"active users have desktop notifications enabled")
num_enter_sends = len(filter(lambda x: x.enter_sends, active_users))
num_enter_sends = len([x for x in active_users if x.enter_sends])
self.report_percentage(num_enter_sends, num_active,
"active users have enter-sends")
@@ -120,8 +124,8 @@ class Command(BaseCommand):
starrers = UserMessage.objects.filter(user_profile__in=user_profiles,
flags=UserMessage.flags.starred).values(
"user_profile").annotate(count=Count("user_profile"))
print "%d users have starred %d messages" % (
len(starrers), sum([elt["count"] for elt in starrers]))
print("%d users have starred %d messages" % (
len(starrers), sum([elt["count"] for elt in starrers])))
active_user_subs = Subscription.objects.filter(
user_profile__in=user_profiles, active=True)
@@ -129,20 +133,20 @@ class Command(BaseCommand):
# Streams not in home view
non_home_view = active_user_subs.filter(in_home_view=False).values(
"user_profile").annotate(count=Count("user_profile"))
print "%d users have %d streams not in home view" % (
len(non_home_view), sum([elt["count"] for elt in non_home_view]))
print("%d users have %d streams not in home view" % (
len(non_home_view), sum([elt["count"] for elt in non_home_view])))
# Code block markup
markup_messages = human_messages.filter(
sender__realm=realm, content__contains="~~~").values(
"sender").annotate(count=Count("sender"))
print "%d users have used code block markup on %s messages" % (
len(markup_messages), sum([elt["count"] for elt in markup_messages]))
print("%d users have used code block markup on %s messages" % (
len(markup_messages), sum([elt["count"] for elt in markup_messages])))
# Notifications for stream messages
notifications = active_user_subs.filter(notifications=True).values(
"user_profile").annotate(count=Count("user_profile"))
print "%d users receive desktop notifications for %d streams" % (
len(notifications), sum([elt["count"] for elt in notifications]))
print("%d users receive desktop notifications for %d streams" % (
len(notifications), sum([elt["count"] for elt in notifications])))
print ""
print("")

View File

@@ -1,36 +1,41 @@
from __future__ import absolute_import
from __future__ import print_function
from django.core.management.base import BaseCommand
from django.db.models import Q
from zerver.models import Realm, Stream, Message, Subscription, Recipient
from zerver.models import Realm, Stream, Message, Subscription, Recipient, get_realm
class Command(BaseCommand):
help = "Generate statistics on the streams for a realm."
def add_arguments(self, parser):
parser.add_argument('realms', metavar='<realm>', type=str, nargs='*',
help="realm to generate statistics for")
def handle(self, *args, **options):
if args:
if options['realms']:
try:
realms = [Realm.objects.get(domain=domain) for domain in args]
except Realm.DoesNotExist, e:
print e
realms = [get_realm(domain) for domain in options['realms']]
except Realm.DoesNotExist as e:
print(e)
exit(1)
else:
realms = Realm.objects.all()
for realm in realms:
print realm.domain
print "------------"
print "%25s %15s %10s" % ("stream", "subscribers", "messages")
print(realm.domain)
print("------------")
print("%25s %15s %10s" % ("stream", "subscribers", "messages"))
streams = Stream.objects.filter(realm=realm).exclude(Q(name__istartswith="tutorial-"))
invite_only_count = 0
for stream in streams:
if stream.invite_only:
invite_only_count += 1
continue
print "%25s" % (stream.name,),
print("%25s" % (stream.name,), end=' ')
recipient = Recipient.objects.filter(type=Recipient.STREAM, type_id=stream.id)
print "%10d" % (len(Subscription.objects.filter(recipient=recipient, active=True)),),
print("%10d" % (len(Subscription.objects.filter(recipient=recipient, active=True)),), end=' ')
num_messages = len(Message.objects.filter(recipient=recipient))
print "%12d" % (num_messages,)
print "%d invite-only streams" % (invite_only_count,)
print ""
print("%12d" % (num_messages,))
print("%d invite-only streams" % (invite_only_count,))
print("")

View File

@@ -1,37 +1,43 @@
from __future__ import absolute_import
from __future__ import print_function
import datetime
import pytz
from django.core.management.base import BaseCommand
from zerver.models import UserProfile, Realm, Stream, Message
from zerver.models import UserProfile, Realm, Stream, Message, get_realm
from six.moves import range
class Command(BaseCommand):
help = "Generate statistics on user activity."
def add_arguments(self, parser):
parser.add_argument('realms', metavar='<realm>', type=str, nargs='*',
help="realm to generate statistics for")
def messages_sent_by(self, user, week):
start = datetime.datetime.now(tz=pytz.utc) - datetime.timedelta(days=(week + 1)*7)
end = datetime.datetime.now(tz=pytz.utc) - datetime.timedelta(days=week*7)
return Message.objects.filter(sender=user, pub_date__gt=start, pub_date__lte=end).count()
def handle(self, *args, **options):
if args:
if options['realms']:
try:
realms = [Realm.objects.get(domain=domain) for domain in args]
except Realm.DoesNotExist, e:
print e
realms = [get_realm(domain) for domain in options['realms']]
except Realm.DoesNotExist as e:
print(e)
exit(1)
else:
realms = Realm.objects.all()
for realm in realms:
print realm.domain
print(realm.domain)
user_profiles = UserProfile.objects.filter(realm=realm, is_active=True)
print "%d users" % (len(user_profiles),)
print "%d streams" % (len(Stream.objects.filter(realm=realm)),)
print("%d users" % (len(user_profiles),))
print("%d streams" % (len(Stream.objects.filter(realm=realm)),))
for user_profile in user_profiles:
print "%35s" % (user_profile.email,),
print("%35s" % (user_profile.email,), end=' ')
for week in range(10):
print "%5d" % (self.messages_sent_by(user_profile, week)),
print ""
print("%5d" % (self.messages_sent_by(user_profile, week)), end=' ')
print("")

View File

@@ -1,3 +1,4 @@
from __future__ import absolute_import
from django.db import connection
from django.template import RequestContext, loader
from django.utils.html import mark_safe
@@ -15,6 +16,10 @@ import itertools
import time
import re
import pytz
from six.moves import filter
from six.moves import map
from six.moves import range
from six.moves import zip
eastern_tz = pytz.timezone('US/Eastern')
def make_table(title, cols, rows, has_row_class=False):
@@ -22,7 +27,7 @@ def make_table(title, cols, rows, has_row_class=False):
if not has_row_class:
def fix_row(row):
return dict(cells=row, row_class=None)
rows = map(fix_row, rows)
rows = list(map(fix_row, rows))
data = dict(title=title, cols=cols, rows=rows)
@@ -37,7 +42,7 @@ def dictfetchall(cursor):
"Returns all rows from a cursor as a dict"
desc = cursor.description
return [
dict(zip([col[0] for col in desc], row))
dict(list(zip([col[0] for col in desc], row)))
for row in cursor.fetchall()
]
@@ -172,9 +177,7 @@ def realm_summary_table(realm_minutes):
GROUP BY realm_id
) at_risk_counts
ON at_risk_counts.realm_id = realm.id
WHERE
realm.domain not in ('customer4.invalid', 'wdaher.com')
AND EXISTS (
WHERE EXISTS (
SELECT *
FROM zerver_useractivity ua
JOIN zerver_userprofile up
@@ -226,14 +229,9 @@ def realm_summary_table(realm_minutes):
# Count active sites
def meets_goal(row):
# The wdaher.com realm doesn't count toward company goals for
# obvious reasons, and customer4.invalid is essentially a dup
# for users.customer4.invalid.
if row['domain'] in ['customer4.invalid', 'wdaher.com']:
return False
return row['active_user_count'] >= 5
num_active_sites = len(filter(meets_goal, rows))
num_active_sites = len(list(filter(meets_goal, rows)))
# create totals
total_active_user_count = 0
@@ -382,7 +380,7 @@ def ad_hoc_queries():
cursor = connection.cursor()
cursor.execute(query)
rows = cursor.fetchall()
rows = map(list, rows)
rows = list(map(list, rows))
cursor.close()
def fix_rows(i, fixup_func):
@@ -616,7 +614,7 @@ def raw_user_activity_table(records):
format_date_for_activity_reports(record.last_visit)
]
rows = map(row, records)
rows = list(map(row, records))
title = 'Raw Data'
return make_table(title, cols, rows)
@@ -823,7 +821,7 @@ def get_realm_activity(request, realm):
all_user_records = {}
try:
admins = Realm.objects.get(domain=realm).get_admin_users()
admins = get_realm(realm).get_admin_users()
except Realm.DoesNotExist:
return HttpResponseNotFound("Realm %s does not exist" % (realm,))

View File

@@ -30,15 +30,25 @@ file is as follows:
[api]
key=<api key from the web interface>
email=<your email address>
site=<your Zulip server's URI>
insecure=<true or false, true means do not verify the server certificate>
cert_bundle=<path to a file containing CA or server certificates to trust>
If you are using Zulip Enterprise, you should also add
If omitted, these settings have the following defaults:
site=<your Zulip Enterprise server's URI>
site=https://api.zulip.com
insecure=false
cert_bundle=<the default CA bundle trusted by Python>
Alternatively, you may explicitly use "--user" and "--api-key" in our
examples, which is especially useful if you are running several bots
which share a home directory. There is also a "--site" option for
setting the Zulip Enterprise server on the command line.
which share a home directory.
The command line equivalents for other configuration options are:
--site=<your Zulip server's URI>
--insecure
--cert-bundle=<file>
You can obtain your Zulip API key, create bots, and manage bots all
from your Zulip [settings page](https://zulip.com/#settings).
@@ -104,3 +114,46 @@ Alternatively, if you don't want to use your ~/.zuliprc file:
--api-key a0b1c2d3e4f5a6b7c8d9e0f1a2b3c4d5 \
hamlet@example.com cordelia@example.com -m \
"Conscience doth make cowards of us all."
#### Working with an untrusted server certificate
If your server has either a self-signed certificate, or a certificate signed
by a CA that you don't wish to globally trust then by default the API will
fail with an SSL verification error.
You can add `insecure=true` to your .zuliprc file.
[api]
site=https://zulip.example.com
insecure=true
This disables verification of the server certificate, so connections are
encrypted but unauthenticated. This is not secure, but may be good enough
for a development environment.
You can explicitly trust the server certificate using `cert_bundle=<filename>`
in your .zuliprc file.
[api]
site=https://zulip.example.com
cert_bundle=/home/bots/certs/zulip.example.com.crt
You can also explicitly trust a different set of Certificate Authorities from
the default bundle that is trusted by Python. For example to trust a company
internal CA.
[api]
site=https://zulip.example.com
cert_bundle=/home/bots/certs/example.com.ca-bundle
Save the server certificate (or the CA certificate) in its own file,
converting to PEM format first if necessary.
Verify that the certificate you have saved is the same as the one on the
server.
The `cert_bundle` option trusts the server / CA certificate only for
interaction with the zulip site, and is relatively secure.
Note that a certificate bundle is merely one or more certificates combined
into a single file.

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python2.7
# -*- coding: utf-8 -*-
# zulip-send -- Sends a message to the specified recipients.

View File

@@ -1,4 +1,4 @@
#!/usr/bin/python
#!/usr/bin/env python2.7
# -*- coding: utf-8 -*-
# Copyright © 2012-2014 Zulip, Inc.

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python2.7
# -*- coding: utf-8 -*-
# Copyright © 2012 Zulip, Inc.

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python2.7
# -*- coding: utf-8 -*-
# Copyright © 2012 Zulip, Inc.

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python2.7
# -*- coding: utf-8 -*-
# Copyright © 2014 Zulip, Inc.

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python2.7
# -*- coding: utf-8 -*-
# Copyright © 2012 Zulip, Inc.
@@ -29,7 +29,7 @@ usage = """list-subscriptions --user=<bot's email address> --api-key=<bot's api
Prints out a list of the user's subscriptions.
Example: list-subscriptions --user=tabbott@zulip.com --api-key=a0b1c2d3e4f5a6b7c8d9e0f1a2b3c4d5
Example: list-subscriptions --user=username@example.com --api-key=a0b1c2d3e4f5a6b7c8d9e0f1a2b3c4d5
You can omit --user and --api-key arguments if you have a properly set up ~/.zuliprc
"""

51
api/examples/print-events Executable file
View File

@@ -0,0 +1,51 @@
#!/usr/bin/env python2.7
# -*- coding: utf-8 -*-
# Copyright © 2012 Zulip, Inc.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
import sys
import os
import optparse
usage = """print-events --user=<bot's email address> --api-key=<bot's api key> [options]
Prints out certain events received by the indicated bot or user matching the filter below.
Example: print-events --user=username@example.com --api-key=a0b1c2d3e4f5a6b7c8d9e0f1a2b3c4d5
You can omit --user and --api-key arguments if you have a properly set up ~/.zuliprc
"""
sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
import zulip
parser = optparse.OptionParser(usage=usage)
parser.add_option_group(zulip.generate_option_group(parser))
(options, args) = parser.parse_args()
client = zulip.init_from_options(options)
def print_event(event):
print event
# This is a blocking call, and will continuously poll for new events
# Note also the filter here is messages to the stream Denmark; if you
# don't specify event_types it'll print all events.
client.call_on_each_event(print_event, event_types=["message"], narrow=[["stream", "Denmark"]])

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python2.7
# -*- coding: utf-8 -*-
# Copyright © 2012 Zulip, Inc.
@@ -29,7 +29,7 @@ usage = """print-messages --user=<bot's email address> --api-key=<bot's api key>
Prints out each message received by the indicated bot or user.
Example: print-messages --user=tabbott@zulip.com --api-key=a0b1c2d3e4f5a6b7c8d9e0f1a2b3c4d5
Example: print-messages --user=username@example.com --api-key=a0b1c2d3e4f5a6b7c8d9e0f1a2b3c4d5
You can omit --user and --api-key arguments if you have a properly set up ~/.zuliprc
"""

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python2.7
# -*- coding: utf-8 -*-
# Copyright © 2012 Zulip, Inc.
@@ -29,7 +29,7 @@ usage = """print-next-message --user=<bot's email address> --api-key=<bot's api
Prints out the next message received by the user.
Example: print-next-messages --user=tabbott@zulip.com --api-key=a0b1c2d3e4f5a6b7c8d9e0f1a2b3c4d5
Example: print-next-messages --user=username@example.com --api-key=a0b1c2d3e4f5a6b7c8d9e0f1a2b3c4d5
You can omit --user and --api-key arguments if you have a properly set up ~/.zuliprc
"""

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python2.7
# -*- coding: utf-8 -*-
# Copyright © 2012 Zulip, Inc.

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python2.7
# -*- coding: utf-8 -*-
# Copyright © 2012 Zulip, Inc.
@@ -29,8 +29,8 @@ usage = """subscribe --user=<bot's email address> --api-key=<bot's api key> [opt
Ensures the user is subscribed to the listed streams.
Examples: subscribe --user=tabbott@zulip.com --api-key=a0b1c2d3e4f5a6b7c8d9e0f1a2b3c4d5 --streams=foo
subscribe --user=tabbott@zulip.com --api-key=a0b1c2d3e4f5a6b7c8d9e0f1a2b3c4d5 --streams='foo bar'
Examples: subscribe --user=username@example.com --api-key=a0b1c2d3e4f5a6b7c8d9e0f1a2b3c4d5 --streams=foo
subscribe --user=username@example.com --api-key=a0b1c2d3e4f5a6b7c8d9e0f1a2b3c4d5 --streams='foo bar'
You can omit --user and --api-key arguments if you have a properly set up ~/.zuliprc
"""

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python2.7
# -*- coding: utf-8 -*-
# Copyright © 2012 Zulip, Inc.
@@ -29,8 +29,8 @@ usage = """unsubscribe --user=<bot's email address> --api-key=<bot's api key> [
Ensures the user is not subscribed to the listed streams.
Examples: unsubscribe --user=tabbott@zulip.com --api-key=a0b1c2d3e4f5a6b7c8d9e0f1a2b3c4d5 --streams=foo
unsubscribe --user=tabbott@zulip.com --api-key=a0b1c2d3e4f5a6b7c8d9e0f1a2b3c4d5 --streams='foo bar'
Examples: unsubscribe --user=username@example.com --api-key=a0b1c2d3e4f5a6b7c8d9e0f1a2b3c4d5 --streams=foo
unsubscribe --user=username@example.com --api-key=a0b1c2d3e4f5a6b7c8d9e0f1a2b3c4d5 --streams='foo bar'
You can omit --user and --api-key arguments if you have a properly set up ~/.zuliprc
"""

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python2.7
# -*- coding: utf-8 -*-
#
# Copyright © 2014 Zulip, Inc.
@@ -38,7 +38,7 @@ ZULIP_STREAM_NAME = "asana"
### OPTIONAL CONFIGURATION ###
# Set to None for logging to stdout when testing, and to a file for
# logging when deployed.
# logging in production.
#LOG_FILE = "/var/tmp/zulip_asana.log"
LOG_FILE = None
@@ -49,7 +49,7 @@ RESUME_FILE = "/var/tmp/zulip_asana.state"
# When initially started, how many hours of messages to include.
ASANA_INITIAL_HISTORY_HOURS = 1
# If you're using Zulip Enterprise, set this to your Zulip Enterprise server
# Set this to your Zulip API server URI
ZULIP_SITE = "https://api.zulip.com"
# If properly installed, the Zulip API should be in your import

21
api/integrations/asana/zulip_asana_mirror Normal file → Executable file
View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python2.7
# -*- coding: utf-8 -*-
#
# Asana integration for Zulip
@@ -22,11 +22,17 @@
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
#
# The "zulip_asana_mirror" script is run continuously, possibly on a work computer
# or preferably on a server.
#
# When restarted, it will attempt to pick up where it left off.
#
# python-dateutil is a dependency for this script.
import base64
from datetime import datetime, timedelta
import dateutil.parser
import dateutil.tz
import json
import logging
import os
@@ -34,6 +40,15 @@ import time
import urllib2
import sys
try:
import dateutil.parser
import dateutil.tz
except ImportError, e:
print >>sys.stderr, e
print >>sys.stderr, "Please install the python-dateutil package."
exit(1)
sys.path.insert(0, os.path.dirname(__file__))
import zulip_asana_config as config
VERSION = "0.9"

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python2.7
# -*- coding: utf-8 -*-
#
# Copyright © 2014 Zulip, Inc.
@@ -41,7 +41,7 @@ ZULIP_STREAM_NAME = "basecamp"
## path, but if not, set a custom path below
ZULIP_API_PATH = None
# If you're using Zulip Enterprise, set this to your Zulip Enterprise server
# Set this to your Zulip API server URI
ZULIP_SITE = "https://api.zulip.com"
# If you wish to log to a file rather than stdout/stderr,

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python2.7
# -*- coding: utf-8 -*-
#
# Zulip mirror of Basecamp activity
@@ -49,7 +49,7 @@ client = zulip.Client(
site=config.ZULIP_SITE,
api_key=config.ZULIP_API_KEY,
client="ZulipBasecamp/" + VERSION)
user_agent = "Basecamp To Zulip Mirroring script (support@zulip.com)"
user_agent = "Basecamp To Zulip Mirroring script (zulip-devel@googlegroups.com)"
htmlParser = HTMLParser()
# find some form of JSON loader/dumper, with a preference order for speed.

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python2.7
# -*- coding: utf-8 -*-
#
# Copyright © 2014 Zulip, Inc.
@@ -50,7 +50,7 @@ ZULIP_TICKETS_STREAM_NAME = "tickets"
# path, but if not, set a custom path below
ZULIP_API_PATH = None
# If you're using Zulip Enterprise, set this to your Zulip Enterprise server
# Set this to your Zulip API server URI
ZULIP_SITE = "https://api.zulip.com"
# If you wish to log to a file rather than stdout/stderr,

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python2.7
# -*- coding: utf-8 -*-
#
# Zulip mirror of Codebase HQ activity
@@ -22,12 +22,12 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
#
# The "codebase-mirror.py" script is run continuously, possibly on a work computer
# or preferably on a server.
# The "zulip_codebase_mirror" script is run continuously, possibly on a work
# computer or preferably on a server.
#
# When restarted, it will attempt to pick up where it left off.
#
# You may need to install the python-requests library, as well as python-dateutil
# python-dateutil is a dependency for this script.
import requests
import logging
@@ -37,7 +37,13 @@ import os
from datetime import datetime, timedelta
import dateutil.parser
try:
import dateutil.parser
except ImportError, e:
print >>sys.stderr, e
print >>sys.stderr, "Please install the python-dateutil package."
exit(1)
sys.path.insert(0, os.path.dirname(__file__))
import zulip_codebase_config as config
@@ -52,7 +58,7 @@ client = zulip.Client(
site=config.ZULIP_SITE,
api_key=config.ZULIP_API_KEY,
client="ZulipCodebase/" + VERSION)
user_agent = "Codebase To Zulip Mirroring script (support@zulip.com)"
user_agent = "Codebase To Zulip Mirroring script (zulip-devel@googlegroups.com)"
# find some form of JSON loader/dumper, with a preference order for speed.
json_implementations = ['ujson', 'cjson', 'simplejson', 'json']

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python2.7
# -*- coding: utf-8 -*-
#
# Zulip notification post-receive hook.

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python2.7
# -*- coding: utf-8 -*-
#
# Copyright © 2014 Zulip, Inc.
@@ -61,5 +61,5 @@ def format_commit_message(author, subject, commit_id):
## path, but if not, set a custom path below
ZULIP_API_PATH = None
# If you're using Zulip Enterprise, set this to your Zulip Enterprise server
# Set this to your Zulip server's API URI
ZULIP_SITE = "https://api.zulip.com"

View File

@@ -1,8 +1,8 @@
#!/usr/bin/env python
#!/usr/bin/env python2.7
# -*- coding: utf-8 -*-
#
# Zulip hook for Mercurial changeset pushes.
# Copyright © 2012-2014 Zulip, Inc.
# Copyright © 2012-2014 Zulip, Inc.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
@@ -25,8 +25,10 @@
#
# This hook is called when changesets are pushed to the master repository (ie
# `hg push`). See https://zulip.com/integrations for installation instructions.
from __future__ import absolute_import
import zulip
from six.moves import range
VERSION = "0.9"

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python2.7
import optparse
import zulip

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python2.7
# -*- coding: utf-8 -*-
#
# Copyright © 2012-2014 Zulip, Inc.
@@ -33,6 +33,7 @@ For example:
1234 //depot/security/src/
'''
from __future__ import print_function
import os
import sys
@@ -59,12 +60,12 @@ try:
changelist = int(sys.argv[1])
changeroot = sys.argv[2]
except IndexError:
print >> sys.stderr, "Wrong number of arguments.\n\n",
print >> sys.stderr, __doc__
print("Wrong number of arguments.\n\n", end=' ', file=sys.stderr)
print(__doc__, file=sys.stderr)
sys.exit(-1)
except ValueError:
print >> sys.stderr, "First argument must be an integer.\n\n",
print >> sys.stderr, __doc__
print("First argument must be an integer.\n\n", end=' ', file=sys.stderr)
print(__doc__, file=sys.stderr)
sys.exit(-1)
metadata = git_p4.p4_describe(changelist)

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python2.7
# -*- coding: utf-8 -*-
#
# Copyright © 2014 Zulip, Inc.

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python2.7
# -*- coding: utf-8 -*-
#
# RSS integration for Zulip
@@ -136,7 +136,7 @@ def strip_tags(html):
def compute_entry_hash(entry):
entry_time = entry.get("published", entry.get("updated"))
entry_id = entry.get("id", entry.get("link"))
return hashlib.md5(entry_id + entry_time).hexdigest()
return hashlib.md5(entry_id + str(entry_time)).hexdigest()
def elide_subject(subject):
MAX_TOPIC_LENGTH = 60
@@ -184,7 +184,7 @@ for feed_url in feed_urls:
entry_hash = compute_entry_hash(entry)
# An entry has either been published or updated.
entry_time = entry.get("published_parsed", entry.get("updated_parsed"))
if (time.time() - calendar.timegm(entry_time)) > OLDNESS_THRESHOLD * 60 * 60 * 24:
if entry_time is not None and (time.time() - calendar.timegm(entry_time)) > OLDNESS_THRESHOLD * 60 * 60 * 24:
# As a safeguard against misbehaving feeds, don't try to process
# entries older than some threshold.
continue

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python2.7
# -*- coding: utf-8 -*-
#
# Zulip notification post-commit hook.

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python2.7
# -*- coding: utf-8 -*-
#
# Copyright © 2014 Zulip, Inc.
@@ -53,5 +53,5 @@ def commit_notice_destination(path, commit):
## path, but if not, set a custom path below
ZULIP_API_PATH = None
# If you're using Zulip Enterprise, set this to your Zulip Enterprise server
# Set this to your Zulip server's API URI
ZULIP_SITE = "https://api.zulip.com"

View File

@@ -107,8 +107,8 @@ class ZulipPlugin(Component):
field_changes = []
for key in old_values.keys():
if key == "description":
content += '- Changed %s from %s to %s' % (key, markdown_block(old_values.get(key)),
markdown_block(ticket.values.get(key)))
content += '- Changed %s from %s\n\nto %s' % (key, markdown_block(old_values.get(key)),
markdown_block(ticket.values.get(key)))
elif old_values.get(key) == "":
field_changes.append('%s: => **%s**' % (key, ticket.values.get(key)))
elif ticket.values.get(key) == "":

View File

@@ -47,5 +47,5 @@ TRAC_NOTIFY_FIELDS = ["description", "summary", "resolution", "comment", "owner"
## path, but if not, set a custom path below
ZULIP_API_PATH = None
# If you're using Zulip Enterprise, set this to your Zulip Enterprise server
# Set this to your Zulip API server URI
ZULIP_SITE = "https://api.zulip.com"

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python2.7
# -*- coding: utf-8 -*-
#
# Twitter integration for Zulip
@@ -126,9 +126,9 @@ except ConfigParser.NoOptionError:
user_id = options.twitter_id
client = zulip.Client(
email=options.email,
api_key=options.api_key,
site=options.site,
email=options.zulip_email,
api_key=options.zulip_api_key,
site=options.zulip_site,
client="ZulipTwitter/" + VERSION,
verbose=True)

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python2.7
# -*- coding: utf-8 -*-
#
# Twitter search integration for Zulip

View File

@@ -1,6 +1,7 @@
#!/usr/bin/env python
#!/usr/bin/env python2.7
# -*- coding: utf-8 -*-
from __future__ import print_function
import os
import sys
@@ -9,8 +10,8 @@ import itertools
def version():
version_py = os.path.join(os.path.dirname(__file__), "zulip", "__init__.py")
with open(version_py) as in_handle:
version_line = itertools.dropwhile(lambda x: not x.startswith("__version__"),
in_handle).next()
version_line = next(itertools.dropwhile(lambda x: not x.startswith("__version__"),
in_handle))
version = version_line.split('=')[-1].strip().replace('"', '')
return version
@@ -26,7 +27,7 @@ package_info = dict(
version=version(),
description='Bindings for the Zulip message API',
author='Zulip, Inc.',
author_email='support@zulip.com',
author_email='zulip-devel@googlegroups.com',
classifiers=[
'Development Status :: 3 - Alpha',
'Environment :: Web Environment',
@@ -60,13 +61,13 @@ except ImportError:
try:
import simplejson
except ImportError:
print >>sys.stderr, "simplejson is not installed"
print("simplejson is not installed", file=sys.stderr)
sys.exit(1)
try:
import requests
assert(LooseVersion(requests.__version__) >= LooseVersion('0.12.1'))
except (ImportError, AssertionError):
print >>sys.stderr, "requests >=0.12.1 is not installed"
print("requests >=0.12.1 is not installed", file=sys.stderr)
sys.exit(1)

View File

@@ -20,6 +20,8 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
from __future__ import print_function
from __future__ import absolute_import
import simplejson
import requests
import time
@@ -29,14 +31,19 @@ import sys
import os
import optparse
import platform
import urllib
import random
from distutils.version import LooseVersion
from ConfigParser import SafeConfigParser
from six.moves.configparser import SafeConfigParser
import logging
import six
__version__ = "0.2.4"
logger = logging.getLogger(__name__)
# Check that we have a recent enough version
# Older versions don't provide the 'json' attribute on responses.
assert(LooseVersion(requests.__version__) >= LooseVersion('0.12.1'))
@@ -45,55 +52,117 @@ requests_json_is_function = callable(requests.Response.json)
API_VERSTRING = "v1/"
class CountingBackoff(object):
def __init__(self, maximum_retries=10, timeout_success_equivalent=None):
self.number_of_retries = 0
self.maximum_retries = maximum_retries
self.timeout_success_equivalent = timeout_success_equivalent
self.last_attempt_time = 0
def keep_going(self):
self._check_success_timeout()
return self.number_of_retries < self.maximum_retries
def succeed(self):
self.number_of_retries = 0
self.last_attempt_time = time.time()
def fail(self):
self._check_success_timeout()
self.number_of_retries = min(self.number_of_retries + 1,
self.maximum_retries)
self.last_attempt_time = time.time()
def _check_success_timeout(self):
if (self.timeout_success_equivalent is not None
and self.last_attempt_time != 0
and time.time() - self.last_attempt_time > self.timeout_success_equivalent):
self.number_of_retries = 0
class RandomExponentialBackoff(CountingBackoff):
def fail(self):
super(RandomExponentialBackoff, self).fail()
# Exponential growth with ratio sqrt(2); compute random delay
# between x and 2x where x is growing exponentially
delay_scale = int(2 ** (self.number_of_retries / 2.0 - 1)) + 1
delay = delay_scale + random.randint(1, delay_scale)
message = "Sleeping for %ss [max %s] before retrying." % (delay, delay_scale * 2)
try:
logger.warning(message)
except NameError:
print(message)
time.sleep(delay)
def _default_client():
return "ZulipPython/" + __version__
def generate_option_group(parser):
group = optparse.OptionGroup(parser, 'API configuration')
group.add_option('--site',
help="Zulip Enterprise server URI (if using Zulip Enterprise)",
def generate_option_group(parser, prefix=''):
group = optparse.OptionGroup(parser, 'Zulip API configuration')
group.add_option('--%ssite' % (prefix,),
dest="zulip_site",
help="Zulip server URI",
default=None)
group.add_option('--api-key',
group.add_option('--%sapi-key' % (prefix,),
dest="zulip_api_key",
action='store')
group.add_option('--user',
dest='email',
group.add_option('--%suser' % (prefix,),
dest='zulip_email',
help='Email address of the calling bot or user.')
group.add_option('--config-file',
group.add_option('--%sconfig-file' % (prefix,),
action='store',
dest="zulip_config_file",
help='Location of an ini file containing the\nabove information. (default ~/.zuliprc)')
group.add_option('-v', '--verbose',
action='store_true',
help='Provide detailed output.')
group.add_option('--client',
group.add_option('--%sclient' % (prefix,),
action='store',
default=None,
dest="zulip_client",
help=optparse.SUPPRESS_HELP)
group.add_option('--insecure',
action='store_true',
dest='insecure',
help='''Do not verify the server certificate.
The https connection will not be secure.''')
group.add_option('--cert-bundle',
action='store',
dest='cert_bundle',
help='''Specify a file containing either the
server certificate, or a set of trusted
CA certificates. This will be used to
verify the server's identity. All
certificates should be PEM encoded.''')
return group
def init_from_options(options, client=None):
if options.client is not None:
client = options.client
if options.zulip_client is not None:
client = options.zulip_client
elif client is None:
client = _default_client()
return Client(email=options.email, api_key=options.api_key,
config_file=options.config_file, verbose=options.verbose,
site=options.site, client=client)
return Client(email=options.zulip_email, api_key=options.zulip_api_key,
config_file=options.zulip_config_file, verbose=options.verbose,
site=options.zulip_site, client=client,
cert_bundle=options.cert_bundle, insecure=options.insecure)
def get_default_config_filename():
config_file = os.path.join(os.environ["HOME"], ".zuliprc")
if (not os.path.exists(config_file) and
os.path.exists(os.path.join(os.environ["HOME"], ".humbugrc"))):
raise RuntimeError("The Zulip API configuration file is now ~/.zuliprc; please run:\n\n mv ~/.humbugrc ~/.zuliprc\n")
return config_file
class Client(object):
def __init__(self, email=None, api_key=None, config_file=None,
verbose=False, retry_on_errors=True,
site=None, client=None):
site=None, client=None,
cert_bundle=None, insecure=None):
if client is None:
client = _default_client()
if None in (api_key, email):
if config_file is None:
config_file = os.path.join(os.environ["HOME"], ".zuliprc")
if (not os.path.exists(config_file) and
os.path.exists(os.path.join(os.environ["HOME"], ".humbugrc"))):
raise RuntimeError("The Zulip API configuration file is now ~/.zuliprc; please run:\n\n mv ~/.humbugrc ~/.zuliprc\n")
if not os.path.exists(config_file):
raise RuntimeError("api_key or email not specified and %s does not exist"
% (config_file,))
if config_file is None:
config_file = get_default_config_filename()
if os.path.exists(config_file):
config = SafeConfigParser()
with file(config_file, 'r') as f:
config.readfp(f, config_file)
@@ -103,6 +172,22 @@ class Client(object):
email = config.get("api", "email")
if site is None and config.has_option("api", "site"):
site = config.get("api", "site")
if cert_bundle is None and config.has_option("api", "cert_bundle"):
cert_bundle = config.get("api", "cert_bundle")
if insecure is None and config.has_option("api", "insecure"):
# Be quite strict about what is accepted so that users don't
# disable security unintentionally.
insecure_setting = config.get("api", "insecure").lower()
if insecure_setting == "true":
insecure = True
elif insecure_setting == "false":
insecure = False
else:
raise RuntimeError("insecure is set to '%s', it must be 'true' or 'false' if it is used in %s"
% (insecure_setting, config_file))
elif None in (api_key, email):
raise RuntimeError("api_key or email not specified and %s does not exist"
% (config_file,))
self.api_key = api_key
self.email = email
@@ -122,9 +207,27 @@ class Client(object):
self.retry_on_errors = retry_on_errors
self.client_name = client
if insecure:
self.tls_verification=False
elif cert_bundle is not None:
if not os.path.isfile(cert_bundle):
raise RuntimeError("tls bundle '%s' does not exist"
%(cert_bundle,))
self.tls_verification=cert_bundle
else:
# Default behavior: verify against system CA certificates
self.tls_verification=True
def get_user_agent(self):
vendor = platform.system()
vendor_version = platform.release()
vendor = ''
vendor_version = ''
try:
vendor = platform.system()
vendor_version = platform.release()
except IOError:
# If the calling process is handling SIGCHLD, platform.system() can
# fail with an IOError. See http://bugs.python.org/issue9127
pass
if vendor == "Linux":
vendor, vendor_version, dummy = platform.linux_distribution()
@@ -143,7 +246,7 @@ class Client(object):
request = {}
for (key, val) in orig_request.iteritems():
if not (isinstance(val, str) or isinstance(val, unicode)):
if not (isinstance(val, str) or isinstance(val, six.text_type)):
request[key] = simplejson.dumps(val)
else:
request[key] = val
@@ -173,9 +276,9 @@ class Client(object):
def end_error_retry(succeeded):
if query_state["had_error_retry"] and self.verbose:
if succeeded:
print "Success!"
print("Success!")
else:
print "Failed!"
print("Failed!")
while True:
try:
@@ -189,7 +292,7 @@ class Client(object):
urlparse.urljoin(self.base_url, url),
auth=requests.auth.HTTPBasicAuth(self.email,
self.api_key),
verify=True, timeout=90,
verify=self.tls_verification, timeout=90,
headers={"User-agent": self.get_user_agent()},
**kwargs)
@@ -241,13 +344,17 @@ class Client(object):
@classmethod
def _register(cls, name, url=None, make_request=(lambda request={}: request),
method="POST", **query_kwargs):
method="POST", computed_url=None, **query_kwargs):
if url is None:
url = name
def call(self, *args, **kwargs):
request = make_request(*args, **kwargs)
return self.do_api_query(request, API_VERSTRING + url, method=method, **query_kwargs)
call.func_name = name
if computed_url is not None:
req_url = computed_url(request)
else:
req_url = url
return self.do_api_query(request, API_VERSTRING + req_url, method=method, **query_kwargs)
call.__name__ = name
setattr(cls, name, call)
def call_on_each_event(self, callback, event_types=None, narrow=[]):
@@ -260,7 +367,7 @@ class Client(object):
if 'error' in res.get('result'):
if self.verbose:
print "Server returned error:\n%s" % res['msg']
print("Server returned error:\n%s" % res['msg'])
time.sleep(1)
else:
return (res['queue_id'], res['last_event_id'])
@@ -274,13 +381,13 @@ class Client(object):
if 'error' in res.get('result'):
if res["result"] == "http-error":
if self.verbose:
print "HTTP error fetching events -- probably a server restart"
print("HTTP error fetching events -- probably a server restart")
elif res["result"] == "connection-error":
if self.verbose:
print "Connection error fetching events -- probably server is temporarily down?"
print("Connection error fetching events -- probably server is temporarily down?")
else:
if self.verbose:
print "Server returned error:\n%s" % res["msg"]
print("Server returned error:\n%s" % res["msg"])
if res["msg"].startswith("Bad event queue id:"):
# Our event queue went away, probably because
# we were asleep or the server restarted
@@ -352,6 +459,7 @@ Client._register('update_message', method='PATCH', url='messages', make_request=
Client._register('get_messages', method='GET', url='messages/latest', longpolling=True)
Client._register('get_events', url='events', method='GET', longpolling=True, make_request=(lambda **kwargs: kwargs))
Client._register('register', make_request=_mk_events)
Client._register('export', method='GET', url='export')
Client._register('deregister', url="events", method="DELETE", make_request=_mk_deregister)
Client._register('get_profile', method='GET', url='users/me')
Client._register('get_streams', method='GET', url='streams', make_request=_kwargs_to_dict)
@@ -359,5 +467,8 @@ Client._register('get_members', method='GET', url='users')
Client._register('list_subscriptions', method='GET', url='users/me/subscriptions')
Client._register('add_subscriptions', url='users/me/subscriptions', make_request=_mk_subs)
Client._register('remove_subscriptions', method='PATCH', url='users/me/subscriptions', make_request=_mk_rm_subs)
Client._register('get_subscribers', method='GET',
computed_url=lambda request: 'streams/%s/members' % (urllib.quote(request['stream'], safe=''),),
make_request=_kwargs_to_dict)
Client._register('render_message', method='GET', url='messages/render')
Client._register('create_user', method='POST', url='users')

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python2.7
import xml.etree.ElementTree as ET
import subprocess

202
assets/zulip-emoji/NOTICE Normal file
View File

@@ -0,0 +1,202 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

13
assets/zulip-emoji/README Normal file
View File

@@ -0,0 +1,13 @@
This directory contains images adapted from the Noto project. For more detail
about Noto, please refer to:
https://code.google.com/p/noto/
These images were generated from the git repository at
<https://android.googlesource.com/platform/external/noto-fonts> as of
90372d894b5d9c9f2a111315d2eb3b8de1979ee4
and
<https://android.googlesource.com/platform/frameworks/base> at
07912f876c8639f811b06831465c14c4a3b17663.

View File

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python2.7
from __future__ import absolute_import
import os

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python2.7
import sys
import logging
import os

View File

@@ -11,5 +11,5 @@ ZULIP_DIR=/home/zulip/deployments/current
STATE_DIR=/var/lib/nagios_state
STATE_FILE=$STATE_DIR/check-rabbitmq-consumers-$queue
$ZULIP_DIR/bots/check-rabbitmq-consumers --queue=$queue &> ${STATE_FILE}-tmp;
mv ${STATE_FILE}-tmp $STATE_FILE
"$ZULIP_DIR/bots/check-rabbitmq-consumers" "--queue=$queue" &> "${STATE_FILE}-tmp";
mv "${STATE_FILE}-tmp" "$STATE_FILE"

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python2.7
import sys
import time
import optparse

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python2.7
import sys
import time

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python2.7
import sys
import re
@@ -6,8 +6,14 @@ import time
import os
import subprocess
WARN_THRESHOLD = 10
CRIT_THRESHOLD = 50
WARN_THRESHOLD_DEFAULT = 10
WARN_THRESHOLD = {
'missedmessage_emails': 45,
}
CRIT_THRESHOLD_DEFAULT = 50
CRIT_THRESHOLD = {
'missedmessage_emails': 70,
}
states = {
0: "OK",
@@ -33,10 +39,10 @@ for line in output.split("\n"):
queue = m.group(1)
count = int(m.group(2))
this_status = 0
if count > CRIT_THRESHOLD:
if count > CRIT_THRESHOLD.get(queue, CRIT_THRESHOLD_DEFAULT):
this_status = 2
warn_queues.append(queue)
elif count > WARN_THRESHOLD:
elif count > WARN_THRESHOLD.get(queue, WARN_THRESHOLD_DEFAULT):
this_status = max(status, 1)
warn_queues.append(queue)
@@ -50,7 +56,7 @@ now_struct = time.gmtime(now)
# While we are sending digest emails, at 11am each weekday, the mail queues can
# get backed up; don't alert on those.
if not set(warn_queues) - set(("missedmessage_emails", "digest_emails")) and \
now_struct.tm_hour == 16 and now_struct.tm_min < 15:
now_struct.tm_hour == 15 and now_struct.tm_min < 25:
status = 0
print("%s|%s|%s|processing digests, not alerting on elevated mail queues" % (
now, status, states[status]))

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python2.7
import time
def nagios_from_file(results_file):

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python2.7
import sys
import time
import datetime
@@ -47,7 +47,7 @@ parser.add_option_group(zulip.generate_option_group(parser))
(options, args) = parser.parse_args()
if not (options.user and options.calendar):
if not (options.zulip_email and options.calendar):
parser.error('You must specify --user and --calendar')
try:

View File

@@ -1,4 +1,4 @@
#! /usr/bin/env python
#! /usr/bin/env python2.7
#
# EXPERIMENTAL
# IRC <=> Zulip mirroring bot
@@ -6,15 +6,18 @@
# Setup: First, you need to install python-irc version 8.5.3
# (https://bitbucket.org/jaraco/irc)
from __future__ import print_function
import irc.bot
import irc.strings
from irc.client import ip_numstr_to_quad, ip_quad_to_numstr
import zulip
import optparse
IRC_DOMAIN = "irc.example.com"
def zulip_sender(sender_string):
nick = sender_string.split("!")[0]
return nick + "@irc.zulip.com"
return nick + "@" + IRC_DOMAIN
class IRCBot(irc.bot.SingleServerIRCBot):
def __init__(self, channel, nickname, server, port=6667):
@@ -47,33 +50,33 @@ class IRCBot(irc.bot.SingleServerIRCBot):
def on_privmsg(self, c, e):
content = e.arguments[0]
sender = zulip_sender(e.source)
if sender.endswith("_zulip@irc.zulip.com"):
if sender.endswith("_zulip@" + IRC_DOMAIN):
return
# Forward the PM to Zulip
print zulip_client.send_message({
print(zulip_client.send_message({
"sender": sender,
"type": "private",
"to": "tabbott@zulip.com",
"to": "username@example.com",
"content": content,
})
}))
def on_pubmsg(self, c, e):
content = e.arguments[0]
stream = e.target
sender = zulip_sender(e.source)
if sender.endswith("_zulip@irc.zulip.com"):
if sender.endswith("_zulip@" + IRC_DOMAIN):
return
# Forward the stream message to Zulip
print zulip_client.send_message({
print(zulip_client.send_message({
"forged": "yes",
"sender": sender,
"type": "stream",
"to": stream,
"subject": "IRC",
"content": content,
})
}))
def on_dccmsg(self, c, e):
c.privmsg("You said: " + e.arguments[0])
@@ -90,12 +93,12 @@ class IRCBot(irc.bot.SingleServerIRCBot):
return
self.dcc_connect(address, port)
usage = """python irc-mirror.py --server=IRC_SERVER --channel=<CHANNEL> --nick-prefix=<NICK> [optional args]
usage = """python2.7 irc-mirror.py --server=IRC_SERVER --channel=<CHANNEL> --nick-prefix=<NICK> [optional args]
Example:
python irc-mirror.py --irc-server=127.0.0.1 --channel='#test' --nick-prefix=tabbott
--site=https://staging.zulip.com --user=irc-bot@zulip.com
python2.7 irc-mirror.py --irc-server=127.0.0.1 --channel='#test' --nick-prefix=username
--site=https://zulip.example.com --user=irc-bot@example.com
--api-key=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Note that "_zulip" will be automatically appended to the IRC nick provided

60
bots/jabber_mirror.py Executable file
View File

@@ -0,0 +1,60 @@
#!/usr/bin/env python2.7
# Copyright (C) 2014 Zulip, Inc.
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation files
# (the "Software"), to deal in the Software without restriction,
# including without limitation the rights to use, copy, modify, merge,
# publish, distribute, sublicense, and/or sell copies of the Software,
# and to permit persons to whom the Software is furnished to do so,
# subject to the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
from __future__ import print_function
import sys
import subprocess
import os
import traceback
import signal
from zulip import RandomExponentialBackoff
def die(signal, frame):
# We actually want to exit, so run os._exit (so as not to be caught and restarted)
os._exit(1)
signal.signal(signal.SIGINT, die)
args = [os.path.join(os.path.dirname(sys.argv[0]), "jabber_mirror_backend.py")]
args.extend(sys.argv[1:])
backoff = RandomExponentialBackoff(timeout_success_equivalent=300)
while backoff.keep_going():
print("Starting Jabber mirroring bot")
try:
ret = subprocess.call(args)
except:
traceback.print_exc()
else:
if ret == 2:
# Don't try again on initial configuration errors
sys.exit(ret)
backoff.fail()
print("")
print("")
print("ERROR: The Jabber mirroring bot is unable to continue mirroring Jabber.")
print("Please contact zulip-devel@googlegroups.com if you need assistance.")
print("")
sys.exit(1)

445
bots/jabber_mirror_backend.py Executable file
View File

@@ -0,0 +1,445 @@
#!/usr/bin/env python2.7
#
# Copyright (C) 2013 Permabit, Inc.
# Copyright (C) 2013--2014 Zulip, Inc.
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation files
# (the "Software"), to deal in the Software without restriction,
# including without limitation the rights to use, copy, modify, merge,
# publish, distribute, sublicense, and/or sell copies of the Software,
# and to permit persons to whom the Software is furnished to do so,
# subject to the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
# The following is a table showing which kinds of messages are handled by the
# mirror in each mode:
#
# Message origin/type --> | Jabber | Zulip
# Mode/sender-, +-----+----+--------+----
# V | MUC | PM | stream | PM
# --------------+-------------+-----+----+--------+----
# | other sender| | x | |
# personal mode +-------------+-----+----+--------+----
# | self sender | | x | x | x
# ------------- +-------------+-----+----+--------+----
# | other sender| x | | |
# public mode +-------------+-----+----+--------+----
# | self sender | | | |
import logging
import threading
import optparse
from sleekxmpp import ClientXMPP, InvalidJID, JID
from sleekxmpp.exceptions import IqError, IqTimeout
from six.moves.configparser import SafeConfigParser
import os, sys, zulip, getpass
import re
__version__ = "1.1"
def room_to_stream(room):
return room + "/xmpp"
def stream_to_room(stream):
return stream.lower().rpartition("/xmpp")[0]
def jid_to_zulip(jid):
suffix = ''
if not jid.username.endswith("-bot"):
suffix = options.zulip_email_suffix
return "%s%s@%s" % (jid.username, suffix, options.zulip_domain)
def zulip_to_jid(email, jabber_domain):
jid = JID(email, domain=jabber_domain)
if (options.zulip_email_suffix
and options.zulip_email_suffix in jid.username
and not jid.username.endswith("-bot")):
jid.username = jid.username.rpartition(options.zulip_email_suffix)[0]
return jid
class JabberToZulipBot(ClientXMPP):
def __init__(self, jid, password, rooms):
if jid.resource:
self.nick = jid.resource
else:
self.nick = jid.username
jid.resource = "zulip"
ClientXMPP.__init__(self, jid, password)
self.rooms = set()
self.rooms_to_join = rooms
self.add_event_handler("session_start", self.session_start)
self.add_event_handler("message", self.message)
self.zulip = None
self.use_ipv6 = False
self.register_plugin('xep_0045') # Jabber chatrooms
self.register_plugin('xep_0199') # XMPP Ping
def set_zulip_client(self, client):
self.zulip = client
def session_start(self, event):
self.get_roster()
self.send_presence()
for room in self.rooms_to_join:
self.join_muc(room)
def join_muc(self, room):
if room in self.rooms:
return
logging.debug("Joining " + room)
self.rooms.add(room)
muc_jid = JID(local=room, domain=options.conference_domain)
xep0045 = self.plugin['xep_0045']
try:
xep0045.joinMUC(muc_jid, self.nick, wait=True)
except InvalidJID:
logging.error("Could not join room: " + str(muc_jid))
return
# Configure the room. Really, we should only do this if the room is
# newly created.
form = None
try:
form = xep0045.getRoomConfig(muc_jid)
except ValueError:
pass
if form:
xep0045.configureRoom(muc_jid, form)
else:
logging.error("Could not configure room: " + str(muc_jid))
def leave_muc(self, room):
if room not in self.rooms:
return
logging.debug("Leaving " + room)
self.rooms.remove(room)
muc_jid = JID(local=room, domain=options.conference_domain)
self.plugin['xep_0045'].leaveMUC(muc_jid, self.nick)
def message(self, msg):
try:
if msg["type"] == "groupchat":
return self.group(msg)
elif msg["type"] == "chat":
return self.private(msg)
else:
logging.warning("Got unexpected message type")
logging.warning(msg)
except Exception:
logging.exception("Error forwarding Jabber => Zulip")
def private(self, msg):
if options.mode == 'public' or msg['thread'] == u'\u1FFFE':
return
sender = jid_to_zulip(msg["from"])
recipient = jid_to_zulip(msg["to"])
zulip_message = dict(
sender = sender,
type = "private",
to = recipient,
content = msg["body"],
)
ret = self.zulip.client.send_message(zulip_message)
if ret.get("result") != "success":
logging.error(ret)
def group(self, msg):
if options.mode == 'personal' or msg["thread"] == u'\u1FFFE':
return
subject = msg["subject"]
if len(subject) == 0:
subject = "(no topic)"
stream = room_to_stream(msg['from'].local)
sender_nick = msg.get_mucnick()
if not sender_nick:
# Messages from the room itself have no nickname. We should not try
# to mirror these
return
jid = self.nickname_to_jid(msg.get_mucroom(), sender_nick)
sender = jid_to_zulip(jid)
zulip_message = dict(
forged = "yes",
sender = sender,
type = "stream",
subject = subject,
to = stream,
content = msg["body"],
)
ret = self.zulip.client.send_message(zulip_message)
if ret.get("result") != "success":
logging.error(ret)
def nickname_to_jid(self, room, nick):
jid = self.plugin['xep_0045'].getJidProperty(room, nick, "jid")
if (jid is None or jid == ''):
return JID(local=nick.replace(' ', ''), domain=self.boundjid.domain)
else:
return jid
class ZulipToJabberBot(object):
def __init__(self, zulip_client):
self.client = zulip_client
self.jabber = None
def set_jabber_client(self, client):
self.jabber = client
def process_event(self, event):
if event['type'] == 'message':
message = event["message"]
if message['sender_email'] != self.client.email:
return
try:
if message['type'] == 'stream':
self.stream_message(message)
elif message['type'] == 'private':
self.private_message(message)
except:
logging.exception("Exception forwarding Zulip => Jabber")
elif event['type'] == 'subscription':
self.process_subscription(event)
elif event['type'] == 'stream':
self.process_stream(event)
def stream_message(self, msg):
stream = msg['display_recipient']
if not stream.endswith("/xmpp"):
return
room = stream_to_room(stream)
jabber_recipient = JID(local=room, domain=options.conference_domain)
outgoing = self.jabber.make_message(
mto = jabber_recipient,
mbody = msg['content'],
mtype = 'groupchat')
outgoing['thread'] = u'\u1FFFE'
outgoing.send()
def private_message(self, msg):
for recipient in msg['display_recipient']:
if recipient["email"] == self.client.email:
continue
if not recipient["is_mirror_dummy"]:
continue
recip_email = recipient['email']
jabber_recipient = zulip_to_jid(recip_email, self.jabber.boundjid.domain)
outgoing = self.jabber.make_message(
mto = jabber_recipient,
mbody = msg['content'],
mtype = 'chat')
outgoing['thread'] = u'\u1FFFE'
outgoing.send()
def process_subscription(self, event):
if event['op'] == 'add':
streams = [s['name'].lower() for s in event['subscriptions']]
streams = [s for s in streams if s.endswith("/xmpp")]
for stream in streams:
self.jabber.join_muc(stream_to_room(stream))
if event['op'] == 'remove':
streams = [s['name'].lower() for s in event['subscriptions']]
streams = [s for s in streams if s.endswith("/xmpp")]
for stream in streams:
self.jabber.leave_muc(stream_to_room(stream))
def process_stream(self, event):
if event['op'] == 'occupy':
streams = [s['name'].lower() for s in event['streams']]
streams = [s for s in streams if s.endswith("/xmpp")]
for stream in streams:
self.jabber.join_muc(stream_to_room(stream))
if event['op'] == 'vacate':
streams = [s['name'].lower() for s in event['streams']]
streams = [s for s in streams if s.endswith("/xmpp")]
for stream in streams:
self.jabber.leave_muc(stream_to_room(stream))
def get_rooms(zulip):
def get_stream_infos(key, method):
ret = method()
if ret.get("result") != "success":
logging.error(ret)
sys.exit("Could not get initial list of Zulip %s" % (key,))
return ret[key]
if options.mode == 'public':
stream_infos = get_stream_infos("streams", zulip.client.get_streams)
else:
stream_infos = get_stream_infos("subscriptions", zulip.client.list_subscriptions)
rooms = []
for stream_info in stream_infos:
stream = stream_info['name']
if stream.endswith("/xmpp"):
rooms.append(stream_to_room(stream))
return rooms
def config_error(msg):
sys.stderr.write("%s\n" % (msg,))
sys.exit(2)
if __name__ == '__main__':
parser = optparse.OptionParser(epilog=
'''Most general and Jabber configuration options may also be specified in the
zulip configuration file under the jabber_mirror section (exceptions are noted
in their help sections). Keys have the same name as options with hyphens
replaced with underscores. Zulip configuration options go in the api section,
as normal.'''.replace("\n", " ")
)
parser.add_option('--mode',
default=None,
action='store',
help= \
'''Which mode to run in. Valid options are "personal" and "public". In
"personal" mode, the mirror uses an individual users' credentials and mirrors
all messages they send on Zulip to Jabber and all private Jabber messages to
Zulip. In "public" mode, the mirror uses the credentials for a dedicated mirror
user and mirrors messages sent to Jabber rooms to Zulip. Defaults to
"personal"'''.replace("\n", " "))
parser.add_option('--zulip-email-suffix',
default=None,
action='store',
help= \
'''Add the specified suffix to the local part of email addresses constructed
from JIDs and nicks before sending requests to the Zulip server, and remove the
suffix before sending requests to the Jabber server. For example, specifying
"+foo" will cause messages that are sent to the "bar" room by nickname "qux" to
be mirrored to the "bar/xmpp" stream in Zulip by user "qux+foo@example.com". This
option does not affect login credentials.'''.replace("\n", " "))
parser.add_option('-d', '--debug',
help='set logging to DEBUG. Can not be set via config file.',
action='store_const',
dest='log_level',
const=logging.DEBUG,
default=logging.INFO)
jabber_group = optparse.OptionGroup(parser, "Jabber configuration")
jabber_group.add_option('--jid',
default=None,
action='store',
help="Your Jabber JID. If a resource is specified, "
+ "it will be used as the nickname when joining MUCs. "
+ "Specifying the nickname is mostly useful if you want "
+ "to run the public mirror from a regular user instead of "
+ "from a dedicated account.")
jabber_group.add_option('--jabber-password',
default=None,
action='store',
help="Your Jabber password")
jabber_group.add_option('--conference-domain',
default=None,
action='store',
help="Your Jabber conference domain (E.g. conference.jabber.example.com). "
+ "If not specifed, \"conference.\" will be prepended to your JID's domain.")
jabber_group.add_option('--no-use-tls',
default=None,
action='store_true')
jabber_group.add_option('--jabber-server-address',
default=None,
action='store',
help="The hostname of your Jabber server. This is only needed if "
"your server is missing SRV records")
jabber_group.add_option('--jabber-server-port',
default='5222',
action='store',
help="The port of your Jabber server. This is only needed if "
"your server is missing SRV records")
parser.add_option_group(jabber_group)
parser.add_option_group(zulip.generate_option_group(parser, "zulip-"))
(options, args) = parser.parse_args()
logging.basicConfig(level=options.log_level,
format='%(levelname)-8s %(message)s')
if options.zulip_config_file is None:
config_file = zulip.get_default_config_filename()
else:
config_file = options.zulip_config_file
config = SafeConfigParser()
try:
with file(config_file, 'r') as f:
config.readfp(f, config_file)
except IOError:
pass
for option in ("jid", "jabber_password", "conference_domain", "mode", "zulip_email_suffix", "jabber_server_address", "jabber_server_port"):
if (getattr(options, option) is None
and config.has_option("jabber_mirror", option)):
setattr(options, option, config.get("jabber_mirror", option))
for option in ("no_use_tls",):
if getattr(options, option) is None:
if config.has_option("jabber_mirror", option):
setattr(options, option, config.getboolean("jabber_mirror", option))
else:
setattr(options, option, False)
if options.mode is None:
options.mode = "personal"
if options.zulip_email_suffix is None:
options.zulip_email_suffix = ''
if options.mode not in ('public', 'personal'):
config_error("Bad value for --mode: must be one of 'public' or 'personal'")
if None in (options.jid, options.jabber_password):
config_error("You must specify your Jabber JID and Jabber password either "
+ "in the Zulip configuration file or on the commandline")
zulip = ZulipToJabberBot(zulip.init_from_options(options, "JabberMirror/" + __version__))
# This won't work for open realms that don't have a consistent domain
options.zulip_domain = zulip.client.email.partition('@')[-1]
try:
jid = JID(options.jid)
except InvalidJID as e:
config_error("Bad JID: %s: %s" % (options.jid, e.message))
if options.conference_domain is None:
options.conference_domain = "conference.%s" % (jid.domain,)
xmpp = JabberToZulipBot(jid, options.jabber_password, get_rooms(zulip))
address = None
if options.jabber_server_address:
address = (options.jabber_server_address, options.jabber_server_port)
if not xmpp.connect(use_tls=not options.no_use_tls, address=address):
sys.exit("Unable to connect to Jabber server")
xmpp.set_zulip_client(zulip)
zulip.set_jabber_client(xmpp)
xmpp.process(block=False)
if options.mode == 'public':
event_types = ['stream']
else:
event_types = ['message', 'subscription']
try:
logging.info("Connecting to Zulip.")
zulip.client.call_on_each_event(zulip.process_event,
event_types=event_types)
except BaseException as e:
logging.exception("Exception in main loop")
xmpp.abort()
sys.exit(1)

View File

@@ -1,4 +1,4 @@
#!/usr/bin/python
#!/usr/bin/env python2.7
import subprocess
import os
import sys

View File

@@ -1,4 +1,4 @@
#!/usr/bin/python
#!/usr/bin/env python2.7
import sys
import subprocess
import base64

View File

@@ -1,3 +1,4 @@
from __future__ import print_function
# This is hacky code to analyze data on our support stream. The main
# reusable bits are get_recent_messages and get_words.
@@ -31,7 +32,7 @@ def analyze_messages(msgs, word_count, email_count):
if False:
if ' ack' in msg['content']:
name = msg['sender_full_name'].split()[0]
print 'ACK', name
print('ACK', name)
m = re.search('ticket (Z....).*email: (\S+).*~~~(.*)', msg['content'], re.M | re.S)
if m:
ticket, email, req = m.groups()
@@ -40,9 +41,9 @@ def analyze_messages(msgs, word_count, email_count):
word_count[word] += 1
email_count[email] += 1
if False:
print
print()
for k, v in msg.items():
print '%-20s: %s' % (k, v)
print('%-20s: %s' % (k, v))
def generate_support_stats():
client = zulip.Client()
@@ -64,16 +65,16 @@ def generate_support_stats():
if True:
words = word_count.keys()
words = filter(lambda w: word_count[w] >= 10, words)
words = filter(lambda w: len(w) >= 5, words)
words = [w for w in words if word_count[w] >= 10]
words = [w for w in words if len(w) >= 5]
words = sorted(words, key=lambda w: word_count[w], reverse=True)
for word in words:
print word, word_count[word]
print(word, word_count[word])
if False:
emails = email_count.keys()
emails = sorted(emails, key=lambda w: email_count[w], reverse=True)
for email in emails:
print email, email_count[email]
print(email, email_count[email])
generate_support_stats()

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python2.7
import sys
import os
import logging

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python2.7
# Copyright (C) 2012 Zulip, Inc.
#
# Permission is hereby granted, free of charge, to any person

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python2.7
# Copyright (C) 2012 Zulip, Inc.
#
# Permission is hereby granted, free of charge, to any person
@@ -21,14 +21,15 @@
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
from __future__ import absolute_import
from __future__ import print_function
import sys
import subprocess
import os
import traceback
import signal
from zephyr_mirror_backend import parse_args
from zephyr_mirror_backend import RandomExponentialBackoff
from .zephyr_mirror_backend import parse_args
def die(signal, frame):
# We actually want to exit, so run os._exit (so as not to be caught and restarted)
@@ -38,6 +39,9 @@ signal.signal(signal.SIGINT, die)
(options, args) = parse_args()
sys.path[:0] = [os.path.join(options.root_path, 'api')]
from zulip import RandomExponentialBackoff
args = [os.path.join(options.root_path, "user_root", "zephyr_mirror_backend.py")]
args.extend(sys.argv[1:])
@@ -50,30 +54,30 @@ if options.forward_class_messages and not options.noshard:
if options.on_startup_command is not None:
subprocess.call([options.on_startup_command])
from zerver.lib.parallel import run_parallel
print "Starting parallel zephyr class mirroring bot"
print("Starting parallel zephyr class mirroring bot")
jobs = list("0123456789abcdef")
def run_job(shard):
subprocess.call(args + ["--shard=%s" % (shard,)])
return 0
for (status, job) in run_parallel(run_job, jobs, threads=16):
print "A mirroring shard died!"
print("A mirroring shard died!")
pass
sys.exit(0)
backoff = RandomExponentialBackoff()
backoff = RandomExponentialBackoff(timeout_success_equivalent=300)
while backoff.keep_going():
print "Starting zephyr mirroring bot"
print("Starting zephyr mirroring bot")
try:
subprocess.call(args)
except:
traceback.print_exc()
backoff.fail()
print ""
print ""
print "ERROR: The Zephyr mirroring bot is unable to continue mirroring Zephyrs."
print "This is often caused by failing to maintain unexpired Kerberos tickets"
print "or AFS tokens. See https://zulip.com/zephyr for documentation on how to"
print "maintain unexpired Kerberos tickets and AFS tokens."
print ""
print("")
print("")
print("ERROR: The Zephyr mirroring bot is unable to continue mirroring Zephyrs.")
print("This is often caused by failing to maintain unexpired Kerberos tickets")
print("or AFS tokens. See https://zulip.com/zephyr for documentation on how to")
print("maintain unexpired Kerberos tickets and AFS tokens.")
print("")
sys.exit(1)

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python2.7
# Copyright (C) 2012 Zulip, Inc.
#
# Permission is hereby granted, free of charge, to any person
@@ -20,8 +20,11 @@
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
from __future__ import absolute_import
import sys
from six.moves import map
from six.moves import range
try:
import simplejson
except ImportError:
@@ -37,43 +40,12 @@ import signal
import logging
import hashlib
import tempfile
import random
import select
class CountingBackoff(object):
def __init__(self, maximum_retries=10):
self.number_of_retries = 0
self.maximum_retries = maximum_retries
def keep_going(self):
return self.number_of_retries < self.maximum_retries
def succeed(self):
self.number_of_retries = 0
def fail(self):
self.number_of_retries = min(self.number_of_retries + 1,
self.maximum_retries)
class RandomExponentialBackoff(CountingBackoff):
def fail(self):
self.number_of_retries = min(self.number_of_retries + 1,
self.maximum_retries)
# Exponential growth with ratio sqrt(2); compute random delay
# between x and 2x where x is growing exponentially
delay_scale = int(2 ** (self.number_of_retries / 2.0 - 1)) + 1
delay = delay_scale + random.randint(1, delay_scale)
message = "Sleeping for %ss [max %s] before retrying." % (delay, delay_scale * 2)
try:
logger.warning(message)
except NameError:
print message
time.sleep(delay)
DEFAULT_SITE = "https://api.zulip.com"
class States:
Startup, ZulipToZephyr, ZephyrToZulip, ChildSending = range(4)
class States(object):
Startup, ZulipToZephyr, ZephyrToZulip, ChildSending = list(range(4))
CURRENT_STATE = States.Startup
def to_zulip_username(zephyr_username):
@@ -401,7 +373,7 @@ def process_notice(notice, log):
if is_personal:
if body.startswith("CC:"):
is_huddle = True
# Map "CC: sipbtest espuser" => "starnine@mit.edu,espuser@mit.edu"
# Map "CC: user1 user2" => "user1@mit.edu, user2@mit.edu"
huddle_recipients = [to_zulip_username(x.strip()) for x in
body.split("\n")[0][4:].split()]
if notice.sender not in huddle_recipients:
@@ -478,7 +450,7 @@ def quit_failed_initialization(message):
sys.exit(1)
def zephyr_init_autoretry():
backoff = RandomExponentialBackoff()
backoff = zulip.RandomExponentialBackoff()
while backoff.keep_going():
try:
# zephyr.init() tries to clear old subscriptions, and thus
@@ -493,7 +465,7 @@ def zephyr_init_autoretry():
quit_failed_initialization("Could not initialize Zephyr library, quitting!")
def zephyr_load_session_autoretry(session_path):
backoff = RandomExponentialBackoff()
backoff = zulip.RandomExponentialBackoff()
while backoff.keep_going():
try:
session = file(session_path, "r").read()
@@ -508,7 +480,7 @@ def zephyr_load_session_autoretry(session_path):
quit_failed_initialization("Could not load saved Zephyr session, quitting!")
def zephyr_subscribe_autoretry(sub):
backoff = RandomExponentialBackoff()
backoff = zulip.RandomExponentialBackoff()
while backoff.keep_going():
try:
zephyr.Subscriptions().add(sub)
@@ -629,7 +601,9 @@ Feedback button or at support@zulip.com."""
wrapped_content = "\n".join("\n".join(wrapper.wrap(line))
for line in message["content"].replace("@", "@@").split("\n"))
zwrite_args = ["zwrite", "-n", "-s", message["sender_full_name"], "-F", "Zephyr error: See http://zephyr.1ts.org/wiki/df"]
zwrite_args = ["zwrite", "-n", "-s", message["sender_full_name"],
"-F", "Zephyr error: See http://zephyr.1ts.org/wiki/df",
"-x", "UTF-8"]
# Hack to make ctl's fake username setup work :)
if message['type'] == "stream" and zulip_account_email == "ctl@mit.edu":
@@ -763,7 +737,7 @@ def maybe_forward_to_zephyr(message):
logger.exception("Error forwarding message:")
def zulip_to_zephyr(options):
# Sync messages from zephyr to zulip
# Sync messages from zulip to zephyr
logger.info("Starting syncing messages.")
while True:
try:

View File

@@ -1,5 +1,5 @@
[program:zmirror-USERNAME]
command=python /home/zulip/zulip/bots/zephyr_mirror_backend.py --root-path=/home/zulip/zulip/bots --user=USERNAME --log-path=/home/zulip/logs/mirror-log-%(program_name)s --use-sessions --session-path=/home/zulip/zephyr_sessions/%(program_name)s --api-key-file=/home/zulip/api-keys/%(program_name)s --ignore-expired-tickets --nagios-path=/home/zulip/mirror_status/%(program_name)s --nagios-class=zulip-mirror-nagios
command=python /home/zulip/zulip/bots/zephyr_mirror_backend.py --root-path=/home/zulip/zulip --user=USERNAME --log-path=/home/zulip/logs/mirror-log-%(program_name)s --use-sessions --session-path=/home/zulip/zephyr_sessions/%(program_name)s --api-key-file=/home/zulip/api-keys/%(program_name)s --ignore-expired-tickets --nagios-path=/home/zulip/mirror_status/%(program_name)s --nagios-class=zulip-mirror-nagios
priority=200 ; the relative start priority (default 999)
autostart=true ; start at supervisord start (default: true)
autorestart=true ; whether/when to restart (default: unexpected)

View File

@@ -39,4 +39,4 @@ def format_commit_message(author, subject, commit_id):
return '!avatar(%s) [%s](https://git.zulip.net/eng/zulip/commit/%s)\n' % (author, subject, commit_id)
ZULIP_API_PATH = "/home/zulip/zulip/api"
ZULIP_SITE = "https://staging.zulip.com"
ZULIP_SITE = "https://zulip.com"

View File

@@ -11,4 +11,4 @@ TRAC_BASE_TICKET_URL = "https://trac.zulip.net/ticket"
TRAC_NOTIFY_FIELDS = ["description", "summary", "resolution", "comment", "owner"]
ZULIP_API_PATH = "/home/zulip/zulip/api"
ZULIP_SITE = "https://staging.zulip.com"
ZULIP_SITE = "https://zulip.com"

View File

@@ -4,4 +4,4 @@
[api]
email = nagios-bot@zulip.com
key = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
site = https://staging.zulip.com
site = https://zulip.com

31
changelog.md Normal file
View File

@@ -0,0 +1,31 @@
# Change Log
All notable changes to this project will be documented in this file.
[Unreleased]
[1.3.9] - 2015-11-16
- Fixed buggy #! lines in upgrade scripts.
[1.3.8] - 2015-11-15
- Added options to the Python api for working with untrusted server certificates.
- Added a lot of documentation on the development environment and testing.
- Added partial support for translating the Zulip UI.
- Migrated installing Node dependencies to use npm.
- Fixed LDAP integration breaking autocomplete of @-mentions.
- Fixed admin panel reactivation/deactivation of bots.
- Fixed inaccurate documentation for downloading the desktop apps.
- Fixed various minor bugs in production installation process.
- Fixed security issue where recent history on private streams might
be visible to new users (to the Zulip team) who were invited with that
private stream as one of their initial streams
(https://github.com/zulip/zulip/issues/230).
- Major preliminary progress towards supporting Python 3.
[1.3.7] - 2015-10-19
- Turn off desktop and audible notifications for streams by default.
- Added support for the LDAP authentication integration creating new users.
- Added new endpoint to support Google auth on mobile.
- Fixed desktop notifications in modern Firefox.
- Fixed several installation issues for both production and development environments.
- Improved documentation for outgoing SMTP and the email mirror integration.

View File

@@ -1,45 +1,29 @@
# -*- coding: utf-8 -*-
import datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models
from __future__ import unicode_literals
from django.db import models, migrations
class Migration(SchemaMigration):
class Migration(migrations.Migration):
def forwards(self, orm):
# Adding model 'Confirmation'
db.create_table('confirmation_confirmation', (
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('content_type', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['contenttypes.ContentType'])),
('object_id', self.gf('django.db.models.fields.PositiveIntegerField')()),
('date_sent', self.gf('django.db.models.fields.DateTimeField')()),
('confirmation_key', self.gf('django.db.models.fields.CharField')(max_length=40)),
))
db.send_create_signal('confirmation', ['Confirmation'])
dependencies = [
('contenttypes', '0001_initial'),
]
def backwards(self, orm):
# Deleting model 'Confirmation'
db.delete_table('confirmation_confirmation')
models = {
'confirmation.confirmation': {
'Meta': {'object_name': 'Confirmation'},
'confirmation_key': ('django.db.models.fields.CharField', [], {'max_length': '40'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
'date_sent': ('django.db.models.fields.DateTimeField', [], {}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'object_id': ('django.db.models.fields.PositiveIntegerField', [], {})
},
'contenttypes.contenttype': {
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
}
}
complete_apps = ['confirmation']
operations = [
migrations.CreateModel(
name='Confirmation',
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('object_id', models.PositiveIntegerField()),
('date_sent', models.DateTimeField(verbose_name='sent')),
('confirmation_key', models.CharField(max_length=40, verbose_name='activation key')),
('content_type', models.ForeignKey(to='contenttypes.ContentType')),
],
options={
'verbose_name': 'confirmation email',
'verbose_name_plural': 'confirmation emails',
},
bases=(models.Model,),
),
]

View File

@@ -34,9 +34,10 @@ def generate_key():
return generate_random_token(40)
def generate_activation_url(key):
current_site = Site.objects.get_current()
return u'https://%s%s' % (current_site.domain,
reverse('confirmation.views.confirm', kwargs={'confirmation_key': key}))
return u'%s%s%s' % (settings.EXTERNAL_URI_SCHEME,
settings.EXTERNAL_HOST,
reverse('confirmation.views.confirm',
kwargs={'confirmation_key': key}))
class ConfirmationManager(models.Manager):
@@ -48,7 +49,7 @@ class ConfirmationManager(models.Manager):
except self.model.DoesNotExist:
return False
obj = confirmation.content_object
status_field = get_status_field(obj._meta.app_label, obj._meta.module_name)
status_field = get_status_field(obj._meta.app_label, obj._meta.model_name)
setattr(obj, status_field, getattr(settings, 'STATUS_ACTIVE', 1))
obj.save()
return obj
@@ -74,7 +75,7 @@ class ConfirmationManager(models.Manager):
if additional_context is not None:
context.update(additional_context)
templates = [
'confirmation/%s_confirmation_email_subject.txt' % obj._meta.module_name,
'confirmation/%s_confirmation_email_subject.txt' % obj._meta.model_name,
'confirmation/confirmation_email_subject.txt',
]
if subject_template_path:
@@ -83,7 +84,7 @@ class ConfirmationManager(models.Manager):
template = loader.select_template(templates)
subject = template.render(context).strip().replace(u'\n', u' ') # no newlines, please
templates = [
'confirmation/%s_confirmation_email_body.txt' % obj._meta.module_name,
'confirmation/%s_confirmation_email_body.txt' % obj._meta.model_name,
'confirmation/confirmation_email_body.txt',
]
if body_template_path:
@@ -104,7 +105,7 @@ class Confirmation(models.Model):
objects = ConfirmationManager()
class Meta:
class Meta(object):
verbose_name = _('confirmation email')
verbose_name_plural = _('confirmation emails')

View File

@@ -31,13 +31,13 @@ def confirm(request, confirmation_key):
'key': confirmation_key,
'full_name': request.GET.get("full_name", None),
'support_email': settings.ZULIP_ADMINISTRATOR,
'enterprise': settings.ENTERPRISE
'voyager': settings.VOYAGER
}
templates = [
'confirmation/confirm.html',
]
if obj:
# if we have an object, we can use specific template
templates.insert(0, 'confirmation/confirm_%s.html' % obj._meta.module_name)
templates.insert(0, 'confirmation/confirm_%s.html' % obj._meta.model_name)
return render_to_response(templates, ctx,
context_instance=RequestContext(request))

View File

@@ -2,20 +2,8 @@ from django.conf.urls import patterns, url
from django.views.generic import TemplateView, RedirectView
urlpatterns = patterns('',
# Job postings
url(r'^jobs/$', TemplateView.as_view(template_name='corporate/jobs/index.html')),
url(r'^jobs/lead-designer/$', TemplateView.as_view(template_name='corporate/jobs/lead-designer.html')),
# Zephyr/MIT
url(r'^zephyr/$', TemplateView.as_view(template_name='corporate/zephyr.html')),
url(r'^mit/$', TemplateView.as_view(template_name='corporate/mit.html')),
url(r'^zephyr-mirror/$', TemplateView.as_view(template_name='corporate/zephyr-mirror.html')),
# Marketing
url(r'^compare/$', TemplateView.as_view(template_name='corporate/compare.html')),
# signup form
url(r'^signup/$', TemplateView.as_view(template_name='corporate/signup.html'),
name='signup'),
# TODO: The beta signup view should probably be moved to corporate.
url(r'^signup/sign-me-up$', 'zerver.views.beta_signup_submission', name='beta-signup-submission'),
)

1
docs/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
_build

192
docs/Makefile Normal file
View File

@@ -0,0 +1,192 @@
# Makefile for Sphinx documentation
#
# You can set these variables from the command line.
SPHINXOPTS =
SPHINXBUILD = sphinx-build
PAPER =
BUILDDIR = _build
# User-friendly check for sphinx-build
ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1)
$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/)
endif
# Internal variables.
PAPEROPT_a4 = -D latex_paper_size=a4
PAPEROPT_letter = -D latex_paper_size=letter
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
# the i18n builder cannot share the environment and doctrees with the others
I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest coverage gettext
help:
@echo "Please use \`make <target>' where <target> is one of"
@echo " html to make standalone HTML files"
@echo " dirhtml to make HTML files named index.html in directories"
@echo " singlehtml to make a single large HTML file"
@echo " pickle to make pickle files"
@echo " json to make JSON files"
@echo " htmlhelp to make HTML files and a HTML help project"
@echo " qthelp to make HTML files and a qthelp project"
@echo " applehelp to make an Apple Help Book"
@echo " devhelp to make HTML files and a Devhelp project"
@echo " epub to make an epub"
@echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
@echo " latexpdf to make LaTeX files and run them through pdflatex"
@echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx"
@echo " text to make text files"
@echo " man to make manual pages"
@echo " texinfo to make Texinfo files"
@echo " info to make Texinfo files and run them through makeinfo"
@echo " gettext to make PO message catalogs"
@echo " changes to make an overview of all changed/added/deprecated items"
@echo " xml to make Docutils-native XML files"
@echo " pseudoxml to make pseudoxml-XML files for display purposes"
@echo " linkcheck to check all external links for integrity"
@echo " doctest to run all doctests embedded in the documentation (if enabled)"
@echo " coverage to run coverage check of the documentation (if enabled)"
clean:
rm -rf $(BUILDDIR)/*
html:
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
dirhtml:
$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
singlehtml:
$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
@echo
@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
pickle:
$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
@echo
@echo "Build finished; now you can process the pickle files."
json:
$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
@echo
@echo "Build finished; now you can process the JSON files."
htmlhelp:
$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
@echo
@echo "Build finished; now you can run HTML Help Workshop with the" \
".hhp project file in $(BUILDDIR)/htmlhelp."
qthelp:
$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
@echo
@echo "Build finished; now you can run "qcollectiongenerator" with the" \
".qhcp project file in $(BUILDDIR)/qthelp, like this:"
@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/zulip-contributor-docs.qhcp"
@echo "To view the help file:"
@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/zulip-contributor-docs.qhc"
applehelp:
$(SPHINXBUILD) -b applehelp $(ALLSPHINXOPTS) $(BUILDDIR)/applehelp
@echo
@echo "Build finished. The help book is in $(BUILDDIR)/applehelp."
@echo "N.B. You won't be able to view it unless you put it in" \
"~/Library/Documentation/Help or install it in your application" \
"bundle."
devhelp:
$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
@echo
@echo "Build finished."
@echo "To view the help file:"
@echo "# mkdir -p $$HOME/.local/share/devhelp/zulip-contributor-docs"
@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/zulip-contributor-docs"
@echo "# devhelp"
epub:
$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
@echo
@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
latex:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo
@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
@echo "Run \`make' in that directory to run these through (pdf)latex" \
"(use \`make latexpdf' here to do that automatically)."
latexpdf:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo "Running LaTeX files through pdflatex..."
$(MAKE) -C $(BUILDDIR)/latex all-pdf
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
latexpdfja:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo "Running LaTeX files through platex and dvipdfmx..."
$(MAKE) -C $(BUILDDIR)/latex all-pdf-ja
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
text:
$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
@echo
@echo "Build finished. The text files are in $(BUILDDIR)/text."
man:
$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
@echo
@echo "Build finished. The manual pages are in $(BUILDDIR)/man."
texinfo:
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
@echo
@echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
@echo "Run \`make' in that directory to run these through makeinfo" \
"(use \`make info' here to do that automatically)."
info:
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
@echo "Running Texinfo files through makeinfo..."
make -C $(BUILDDIR)/texinfo info
@echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
gettext:
$(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
@echo
@echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
changes:
$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
@echo
@echo "The overview file is in $(BUILDDIR)/changes."
linkcheck:
$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
@echo
@echo "Link check complete; look for any errors in the above output " \
"or in $(BUILDDIR)/linkcheck/output.txt."
doctest:
$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
@echo "Testing of doctests in the sources finished, look at the " \
"results in $(BUILDDIR)/doctest/output.txt."
coverage:
$(SPHINXBUILD) -b coverage $(ALLSPHINXOPTS) $(BUILDDIR)/coverage
@echo "Testing of coverage in the sources finished, look at the " \
"results in $(BUILDDIR)/coverage/python.txt."
xml:
$(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml
@echo
@echo "Build finished. The XML files are in $(BUILDDIR)/xml."
pseudoxml:
$(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml
@echo
@echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml."

23
docs/README.md Normal file
View File

@@ -0,0 +1,23 @@
These docs are written in rST, and are included on the zulip.org website
as well as on each development installation. Many of these docs
have been ported from the internal docs of Zulip Inc.,
and may need to be updated for use in the open source project.
To generate HTML docs locally from rST:
* `pip install sphinx`
* In this directory, `make html`. Output appears in a `_build/html` subdirectory.
To create rST from MediaWiki input:
* Use `pandoc -r mediawiki -w rst` on MediaWiki source.
* Use unescape.py to remove any leftover HTML entities (often inside <pre>
tags and the like).
We can use pandoc to translate mediawiki into reStructuredText, but some things need fixing up:
* Add page titles.
* Review pages for formatting (especially inline code chunks) and content.
* Fix wiki links?
* Add pages to the table of contents (`index.rst`).

10
docs/_static/theme_overrides.css vendored Normal file
View File

@@ -0,0 +1,10 @@
/* override table width restrictions */
.wy-table-responsive table td, .wy-table-responsive table th {
/* !important prevents the common CSS stylesheets from
overriding this as on RTD they are loaded after this stylesheet */
white-space: normal !important;
}
.wy-table-responsive {
overflow: visible !important;
}

484
docs/code-style.rst Normal file
View File

@@ -0,0 +1,484 @@
==========================
Code style and conventions
==========================
Be consistent!
==============
Look at the surrounding code, or a similar part of the project, and
try to do the same thing. If you think the other code has actively bad
style, fix it (in a separate commit).
When in doubt, send an email to zulip-devel@googlegroups.com with your
question.
Lint tools
==========
You can run them all at once with
::
./tools/lint-all
You can set this up as a local Git commit hook with
::
``tools/setup-git-repo``
The Vagrant setup process runs this for you.
``lint-all`` runs many lint checks in parallel, including
- Javascript (`JSLint <http://www.jslint.com/>`__)
``tools/jslint/check-all.js`` contains a pretty fine-grained set of
JSLint options, rule exceptions, and allowed global variables. If you
add a new global, you'll need to add it to the list.
- Python (`Pyflakes <http://pypi.python.org/pypi/pyflakes>`__)
- templates
- Puppet configuration
- custom checks (e.g. trailing whitespace and spaces-not-tabs)
Secrets
=======
Please don't put any passwords, secret access keys, etc. inline in the
code. Instead, use the ``get_secret`` function in
``zproject/settings.py`` to read secrets from ``/etc/zulip/secrets.conf``.
Dangerous constructs
====================
Misuse of database queries
--------------------------
Look out for Django code like this::
[Foo.objects.get(id=bar.x.id)
for bar in Bar.objects.filter(...)
if  bar.baz < 7]
This will make one database query for each ``Bar``, which is slow in
production (but not in local testing!). Instead of a list comprehension,
write a single query using Django's `QuerySet
API <https://docs.djangoproject.com/en/dev/ref/models/querysets/>`__.
If you can't rewrite it as a single query, that's a sign that something
is wrong with the database schema. So don't defer this optimization when
performing schema changes, or else you may later find that it's
impossible.
UserProfile.objects.get() / Client.objects.get / etc.
-----------------------------------------------------
In our Django code, never do direct
``UserProfile.objects.get(email=foo)`` database queries. Instead always
use ``get_user_profile_by_{email,id}``. There are 3 reasons for this:
#. It's guaranteed to correctly do a case-inexact lookup
#. It fetches the user object from memcached, which is faster
#. It always fetches a UserProfile object which has been queried using
.selected\_related(), and thus will perform well when one later
accesses related models like the Realm.
Similarly we have ``get_client`` and ``get_stream`` functions to fetch
those commonly accessed objects via memcached.
Using Django model objects as keys in sets/dicts
------------------------------------------------
Don't use Django model objects as keys in sets/dictionaries -- you will
get unexpected behavior when dealing with objects obtained from
different database queries:
For example,
``UserProfile.objects.only("id").get(id=17) in set([UserProfile.objects.get(id=17)])``
is False
You should work with the IDs instead.
user\_profile.save()
--------------------
You should always pass the update\_fields keyword argument to .save()
when modifying an existing Django model object. By default, .save() will
overwrite every value in the column, which results in lots of race
conditions where unrelated changes made by one thread can be
accidentally overwritten by another thread that fetched its UserProfile
object before the first thread wrote out its change.
Using raw saves to update important model objects
-------------------------------------------------
In most cases, we already have a function in zephyr/lib/actions.py with
a name like do\_activate\_user that will correctly handle lookups,
caching, and notifying running browsers via the event system about your
change. So please check whether such a function exists before writing
new code to modify a model object, since your new code has a good chance
of getting at least one of these things wrong.
``x.attr('zid')`` vs. ``rows.id(x)``
------------------------------------
Our message row DOM elements have a custom attribute ``zid`` which
contains the numerical message ID. **Don't access this directly as**
``x.attr('zid')`` ! The result will be a string and comparisons (e.g.
with ``<=``) will give the wrong result, occasionally, just enough to
make a bug that's impossible to track down.
You should instead use the ``id`` function from the ``rows`` module, as
in ``rows.id(x)``. This returns a number. Even in cases where you do
want a string, use the ``id`` function, as it will simplify future code
changes. In most contexts in JavaScript where a string is needed, you
can pass a number without any explicit conversion.
Javascript var
--------------
Always declare Javascript variables using ``var``::
var x = ...;
In a function, ``var`` is necessary or else ``x`` will be a global
variable. For variables declared at global scope, this has no effect,
but we do it for consistency.
Javascript has function scope only, not block scope. This means that a
``var`` declaration inside a ``for`` or ``if`` acts the same as a
``var`` declaration at the beginning of the surrounding ``function``. To
avoid confusion, declare all variables at the top of a function.
Javascript ``for (i in myArray)``
---------------------------------
Don't use it:
`[1] <http://stackoverflow.com/questions/500504/javascript-for-in-with-arrays>`__,
`[2] <http://google-styleguide.googlecode.com/svn/trunk/javascriptguide.xml#for-in_loop>`__,
`[3] <http://www.jslint.com/lint.html#forin>`__
jQuery global state
-------------------
Don't mess with jQuery global state once the app has loaded. Code like
this is very dangerous::
$.ajaxSetup({ async: false });
$.get(...);
$.ajaxSetup({ async: true });
jQuery and the browser are free to run other code while the request is
pending, which could perform other Ajax requests with the altered
settings.
Instead, switch to the more general |ajax|_ function, which can take options
like ``async``.
.. |ajax| replace:: ``$.ajax``
.. _ajax: http://api.jquery.com/jQuery.ajax
State and logs files
--------------------
Do not write state and logs files inside the current working directory
in the production environment. This will not how you expect, because the
current working directory for the app changes every time we do a deploy.
Instead, hardcode a path in settings.py -- see SERVER\_LOG\_PATH in
settings.py for an example.
JS array/object manipulation
============================
For generic functions that operate on arrays or JavaScript objects, you
should generally use `Underscore <http://underscorejs.org/>`__. We used
to use jQuery's utility functions, but the Underscore equivalents are
more consistent, better-behaved and offer more choices.
A quick conversion table::
   $.each  _.each (parameters to the callback reversed)
   $.inArray  _.indexOf (parameters reversed)
   $.grep  _.filter
   $.map  _.map
   $.extend  _.extend
There's a subtle difference in the case of ``_.extend``; it will replace
attributes with undefined, whereas jQuery won't::
   $.extend({foo: 2}, {foo: undefined});  // yields {foo: 2}, BUT...
   _.extend({foo: 2}, {foo: undefined});  // yields {foo: undefined}!
Also, ``_.each`` does not let you break out of the iteration early by
returning false, the way jQuery's version does. If you're doing this,
you probably want ``_.find``, ``_.every``, or ``_.any``, rather than
'each'.
Some Underscore functions have multiple names. You should always use the
canonical name (given in large print in the Underscore documentation),
with the exception of ``_.any``, which we prefer over the less clear
'some'.
More arbitrary style things
===========================
General
-------
Indentation is four space characters for Python, JS, CSS, and shell
scripts. Indentation is two space characters for HTML templates.
We never use tabs anywhere in source code we write, but we have some
third-party files which contain tabs.
Keep third-party static files under the directory
``zephyr/static/third/``, with one subdirectory per third-party project.
We don't have an absolute hard limit on line length, but we should avoid
extremely long lines. A general guideline is: refactor stuff to get it
under 85 characters, unless that makes the code a lot uglier, in which
case it's fine to go up to 120 or so.
Whitespace guidelines:
- Put one space (or more for alignment) around binary arithmetic and
equality operators.
- Put one space around each part of the ternary operator.
- Put one space between keywords like ``if`` and ``while`` and their
associated open paren.
- Put one space between the closing paren for ``if`` and ``while``-like
constructs and the opening curly brace. Put the curly brace on the
same line unless doing otherwise improves readability.
- Put no space before or after the open paren for function calls and no
space before the close paren for function calls.
- For the comma operator and colon operator in languages where it is
used for inline dictionaries, put no space before it and at least one
space after. Only use more than one space for alignment.
Javascript
----------
Don't use ``==`` and ``!=`` because these operators perform type
coercions, which can mask bugs. Always use ``===`` and ``!==``.
End every statement with a semicolon.
``if`` statements with no braces are allowed, if the body is simple and
its extent is abundantly clear from context and formatting.
Anonymous functions should have spaces before and after the argument
list::
var x = function (foo, bar) { // ...
When calling a function with an anonymous function as an argument, use
this style::
$.get('foo', function (data) {
    var x = ...;
    // ...
});
The inner function body is indented one level from the outer function
call. The closing brace for the inner function and the closing
parenthesis for the outer call are together on the same line. This style
isn't necessarily appropriate for calls with multiple anonymous
functions or other arguments following them.
Use
::
$(function () { ...
rather than
::
$(document).ready(function () { ...
and combine adjacent on-ready functions, if they are logically related.
The best way to build complicated DOM elements is a Mustache template
like ``zephyr/static/templates/message.handlebars``. For simpler things
you can use jQuery DOM building APIs like so::
var new_tr = $('<tr />').attr('id', zephyr.id);
Passing a HTML string to jQuery is fine for simple hardcoded things::
foo.append('<p id="selected">foo</p>');
but avoid programmatically building complicated strings.
We used to favor attaching behaviors in templates like so::
<p onclick="select_zephyr({{id}})">
but there are some reasons to prefer attaching events using jQuery code:
- Potential huge performance gains by using delegated events where
possible
- When calling a function from an ``onclick`` attribute, ``this`` is
not bound to the element like you might think
- jQuery does event normalization
Either way, avoid complicated JavaScript code inside HTML attributes;
call a helper function instead.
HTML / CSS
----------
Don't use the ``style=`` attribute. Instead, define logical classes and
put your styles in ``zulip.css``.
Don't use the tag name in a selector unless you have to. In other words,
use ``.foo`` instead of ``span.foo``. We shouldn't have to care if the
tag type changes in the future.
Don't use inline event handlers (``onclick=``, etc. attributes).
Instead, attach a jQuery event handler
(``$('#foo').on('click', function () {...})``) when the DOM is ready
(inside a ``$(function () {...})`` block).
Use this format when you have the same block applying to multiple CSS
styles (separate lines for each selector)::
selector1,
selector2 {
};
Python
------
- Scripts should start with ``#!/usr/bin/env python2.7`` and not
``#!/usr/bin/env python2.7``. See commit ``437d4aee`` for an explanation of
why. Don't put such a line on a Python file unless it's meaningful to
run it as a script. (Some libraries can also be run as scripts, e.g.
to run a test suite.)
- The first import in a file should be
``from __future__ import absolute_import``, per `PEP
328 <http://docs.python.org/2/whatsnew/2.5.html#pep-328-absolute-and-relative-imports>`__
- Put all imports together at the top of the file, absent a compelling
reason to do otherwise.
- Unpacking sequences doesn't require list brackets::
[x, y] = xs    # unnecessary
x, y = xs      # better
- For string formatting, use ``x % (y,)`` rather than ``x % y``, to
avoid ambiguity if ``y`` happens to be a tuple.
- When selecting by id, don't use ``foo.pk`` when you mean ``foo.id``.
E.g.
::
recipient = Recipient(type_id=huddle.pk, type=Recipient.HUDDLE)
should be written as
::
recipient = Recipient(type_id=huddle.id, type=Recipient.HUDDLE)
in case we ever change the primary keys.
Version Control
===============
Commit Discipline
-----------------
We follow the Git project's own commit discipline practice of "Each
commit is a minimal coherent idea".
Coherency requirements for any commit:
- It should pass tests (so test updates needed by a change should be in
the same commit as the original change, not a separate "fix the tests
that were broken by the last commit" commit).
- It should be safe to deploy individually, or comment in detail in the
commit message as to why it isn't (maybe with a [manual] tag). So
implementing a new API endpoint in one commit and then adding the
security checks in a future commit should be avoided -- the security
checks should be there from the beginning.
- Error handling should generally be included along with the code that
might trigger the error.
- TODO comments should be in the commit that introduces the
issue or functionality with further work required.
When you should be minimal:
- Significant refactorings should be done in a separate commit from
functional changes.
- Moving code from one file to another should be done in a separate
commits from functional changes or even refactoring within a file.
- 2 different refactorings should be done in different commits.
- 2 different features should be done in different commits.
- If you find yourself writing a commit message that reads like a list
of somewhat dissimilar things that you did, you probably should have
just done 2 commits.
When not to be overly minimal:
- For completely new features, you don't necessarily need to split out
new commits for each little subfeature of the new feature. E.g. if
you're writing a new tool from scratch, it's fine to have the initial
tool have plenty of options/features without doing separate commits
for each one. That said, reviewing a 2000-line giant blob of new
code isn't fun, so please be thoughtful about submitting things in
reviewable units.
- Don't bother to split back end commits from front end commits, even
though the backend can often be coherent on its own.
Other considerations:
- Overly fine commits are easily squashed, but not vice versa, so err
toward small commits, and the code reviewer can advise on squashing.
It can take some practice to get used to writing your commits this
way. For example, often you'll start adding a feature, and discover
you need to a refactoring partway through writing the feature. When
that happens, we recommend stashing your partial feature, do the
refactoring, commit it, and then finish implementing your feature.
Commit Messages
---------------
- The first line of commit messages should be written in the imperative
and be kept relatively short while concisely explaining what the
commit does. For example:
Bad::
bugfix
gather_subscriptions was broken
Good::
Prevent gather_subscriptions from throwing an exception when given bad input.
- Please use a complete sentence, ending with a period.
- The rest of the commit message should be written in full prose and
explain why and how the change was made. If the commit makes
performance improvements, you should generally include some rough
benchmarks showing that it actually improves the performance.
- In your commit message, you should describe any manual testing you
did in addition to running the automated tests, and any aspects of
the commit that you think are questionable and you'd like special
attention applied to.
Tests
-----
All significant new features should come with tests.
Third party code
----------------
When adding new third-party packages to our codebase, please include
"[third]" at the beginning of the commit message. You don't necessarily
need to do this when patching third-party code that's already in tree.

295
docs/conf.py Normal file
View File

@@ -0,0 +1,295 @@
# -*- coding: utf-8 -*-
#
# zulip-contributor-docs documentation build configuration file, created by
# sphinx-quickstart on Mon Aug 17 16:24:04 2015.
#
# This file is execfile()d with the current directory set to its
# containing dir.
#
# Note that not all possible configuration values are present in this
# autogenerated file.
#
# All configuration values have a default; values that are commented out
# serve to show the default.
import sys
import os
import shlex
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#sys.path.insert(0, os.path.abspath('.'))
# -- General configuration ------------------------------------------------
# If your documentation needs a minimal Sphinx version, state it here.
#needs_sphinx = '1.0'
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = []
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
# The suffix(es) of source filenames.
# You can specify multiple suffix as a list of string:
# source_suffix = ['.rst', '.md']
source_suffix = '.rst'
# The encoding of source files.
#source_encoding = 'utf-8-sig'
# The master toctree document.
master_doc = 'index'
# General information about the project.
project = u'Zulip'
copyright = u'2015, The Zulip Team'
author = u'The Zulip Team'
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The short X.Y version.
version = '0.1'
# The full version, including alpha/beta/rc tags.
release = '0.1'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#
# This is also used if you do content translation via gettext catalogs.
# Usually you set "language" from the command line for these cases.
language = None
# There are two options for replacing |today|: either, you set today to some
# non-false value, then it is used:
#today = ''
# Else, today_fmt is used as the format for a strftime call.
#today_fmt = '%B %d, %Y'
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
exclude_patterns = ['_build']
# The reST default role (used for this markup: `text`) to use for all
# documents.
#default_role = None
# If true, '()' will be appended to :func: etc. cross-reference text.
#add_function_parentheses = True
# If true, the current module name will be prepended to all description
# unit titles (such as .. function::).
#add_module_names = True
# If true, sectionauthor and moduleauthor directives will be shown in the
# output. They are ignored by default.
#show_authors = False
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'
# A list of ignored prefixes for module index sorting.
#modindex_common_prefix = []
# If true, keep warnings as "system message" paragraphs in the built documents.
#keep_warnings = False
# If true, `todo` and `todoList` produce output, else they produce nothing.
todo_include_todos = False
# -- Options for HTML output ----------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
# Read The Docs can't import sphinx_rtd_theme, so don't import it there.
on_rtd = os.environ.get('READTHEDOCS', None) == 'True'
if not on_rtd:
import sphinx_rtd_theme
html_theme = 'sphinx_rtd_theme'
html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# documentation.
#html_theme_options = {}
# Add any paths that contain custom themes here, relative to this directory.
#html_theme_path = []
# The name for this set of Sphinx documents. If None, it defaults to
# "<project> v<release> documentation".
#html_title = None
# A shorter title for the navigation bar. Default is the same as html_title.
#html_short_title = None
# The name of an image file (relative to this directory) to place at the top
# of the sidebar.
#html_logo = None
# The name of an image file (within the static path) to use as favicon of the
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
# pixels large.
#html_favicon = None
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']
# Add any extra paths that contain custom files (such as robots.txt or
# .htaccess) here, relative to this directory. These files are copied
# directly to the root of the documentation.
#html_extra_path = []
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
# using the given strftime format.
#html_last_updated_fmt = '%b %d, %Y'
# If true, SmartyPants will be used to convert quotes and dashes to
# typographically correct entities.
#html_use_smartypants = True
# Custom sidebar templates, maps document names to template names.
#html_sidebars = {}
# Additional templates that should be rendered to pages, maps page names to
# template names.
#html_additional_pages = {}
# If false, no module index is generated.
#html_domain_indices = True
# If false, no index is generated.
#html_use_index = True
# If true, the index is split into individual pages for each letter.
#html_split_index = False
# If true, links to the reST sources are added to the pages.
#html_show_sourcelink = True
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
#html_show_sphinx = True
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
#html_show_copyright = True
# If true, an OpenSearch description file will be output, and all pages will
# contain a <link> tag referring to it. The value of this option must be the
# base URL from which the finished HTML is served.
#html_use_opensearch = ''
# This is the file name suffix for HTML files (e.g. ".xhtml").
#html_file_suffix = None
# Language to be used for generating the HTML full-text search index.
# Sphinx supports the following languages:
# 'da', 'de', 'en', 'es', 'fi', 'fr', 'hu', 'it', 'ja'
# 'nl', 'no', 'pt', 'ro', 'ru', 'sv', 'tr'
#html_search_language = 'en'
# A dictionary with options for the search language support, empty by default.
# Now only 'ja' uses this config value
#html_search_options = {'type': 'default'}
# The name of a javascript file (relative to the configuration directory) that
# implements a search results scorer. If empty, the default will be used.
#html_search_scorer = 'scorer.js'
# Output file base name for HTML help builder.
htmlhelp_basename = 'zulip-contributor-docsdoc'
def setup(app):
# overrides for wide tables in RTD theme
app.add_stylesheet('theme_overrides.css') # path relative to _static
# -- Options for LaTeX output ---------------------------------------------
latex_elements = {
# The paper size ('letterpaper' or 'a4paper').
#'papersize': 'letterpaper',
# The font size ('10pt', '11pt' or '12pt').
#'pointsize': '10pt',
# Additional stuff for the LaTeX preamble.
#'preamble': '',
# Latex figure (float) alignment
#'figure_align': 'htbp',
}
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title,
# author, documentclass [howto, manual, or own class]).
latex_documents = [
(master_doc, 'zulip-contributor-docs.tex', u'Zulip Documentation',
u'The Zulip Team', 'manual'),
]
# The name of an image file (relative to this directory) to place at the top of
# the title page.
#latex_logo = None
# For "manual" documents, if this is true, then toplevel headings are parts,
# not chapters.
#latex_use_parts = False
# If true, show page references after internal links.
#latex_show_pagerefs = False
# If true, show URL addresses after external links.
#latex_show_urls = False
# Documents to append as an appendix to all manuals.
#latex_appendices = []
# If false, no module index is generated.
#latex_domain_indices = True
# -- Options for manual page output ---------------------------------------
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
(master_doc, 'zulip-contributor-docs', u'Zulip Documentation',
[author], 1)
]
# If true, show URL addresses after external links.
#man_show_urls = False
# -- Options for Texinfo output -------------------------------------------
# Grouping the document tree into Texinfo files. List of tuples
# (source start file, target name, title, author,
# dir menu entry, description, category)
texinfo_documents = [
(master_doc, 'zulip-contributor-docs', u'Zulip Documentation',
author, 'zulip-contributor-docs', 'Documentation for contributing to Zulip.',
'Miscellaneous'),
]
# Documents to append as an appendix to all manuals.
#texinfo_appendices = []
# If false, no module index is generated.
#texinfo_domain_indices = True
# How to display URL addresses: 'footnote', 'no', or 'inline'.
#texinfo_show_urls = 'footnote'
# If true, do not generate a @detailmenu in the "Top" node's menu.
#texinfo_no_detailmenu = False

View File

@@ -0,0 +1,95 @@
===================
Directory structure
===================
This page documents the Zulip directory structure and how to decide where to
put a file.
Scripts
=======
+--------------------+-----------------------------------------------------------------------------------+
| ``scripts/`` | Scripts that production deployments might run manually (e.g. ``restart-server``) |
+--------------------+-----------------------------------------------------------------------------------+
| ``bin/`` | Scripts that are needed on production deployments but humans should never run |
+--------------------+-----------------------------------------------------------------------------------+
| ``scripts/setup/`` | Tools that production deployments will only run once, during installation |
+--------------------+-----------------------------------------------------------------------------------+
| ``tools/`` | Development tools |
+--------------------+-----------------------------------------------------------------------------------+
Bots
====
+------------------------+----------------------------------------------------------------------+
| ``api/integrations`` | Bots distributed as part of the Zulip API bundle. |
+------------------------+----------------------------------------------------------------------+
| ``bots/`` | Previously Zulip internal bots. These usually need a bit of work. |
+------------------------+----------------------------------------------------------------------+
Management commands
===================
+-------------------------------------+------------------------------------------------------------------------------------------------------------------------------------+
| ``zerver/management/commands/`` | Management commands one might run at a production deployment site (e.g. scripts to change a value or deactivate a user properly) |
+-------------------------------------+------------------------------------------------------------------------------------------------------------------------------------+
Views
=====
+--------------------------------+-----------------------------------------+
| ``zerver/tornadoviews.py`` | Tornado views |
+--------------------------------+-----------------------------------------+
| ``zerver/views/webhooks.py`` | Webhook views |
+--------------------------------+-----------------------------------------+
| ``zerver/views/messages.py`` | message-related views |
+--------------------------------+-----------------------------------------+
| ``zerver/views/__init__.py`` | other Django views |
+--------------------------------+-----------------------------------------+
Static assets
=============
+---------------+---------------------------------------------------------------------------------------------------------------+
| ``assets/`` | For assets not to be served to the web (e.g. the system to generate our favicons) |
+---------------+---------------------------------------------------------------------------------------------------------------+
| ``static/`` | For things we do want to both serve to the web and distribute to production deployments (e.g. the webpages) |
+---------------+---------------------------------------------------------------------------------------------------------------+
Puppet
======
+--------------------+----------------------------------------------------------------------------------+
| ``puppet/zulip`` | For configuration for production deployments |
+--------------------+----------------------------------------------------------------------------------+
Templates
=========
+--------------------------+--------------------------------------------------------+
| ``templates/zerver`` | For templates related to zerver views |
+--------------------------+--------------------------------------------------------+
| ``static/templates`` | Handlebars templates for the frontend |
+--------------------------+--------------------------------------------------------+
Tests
=====
+------------------------+-----------------------------------+
| ``zerver/test*.py`` | Backend tests |
+------------------------+-----------------------------------+
| ``frontend_tests/node`` | Node Frontend unit tests |
+------------------------+-----------------------------------+
| ``frontend_tests/tests`` | Casper frontend tests |
+------------------------+-----------------------------------+
Documentation
=============
+-------------+-----------------------------------------------+
| ``docs/`` | Source for this documentation |
+-------------+-----------------------------------------------+
You can consult the repository's .gitattributes file to see exactly
which components are excluded from production releases (release
tarballs are generated using tools/build-release-tarball).

9
docs/html_unescape.py Executable file
View File

@@ -0,0 +1,9 @@
#!/usr/bin/env python2.7
# Remove HTML entity escaping left over from MediaWiki->rST conversion.
import html
import sys
for line in sys.stdin:
print(html.unescape(line), end='')

25
docs/index.rst Normal file
View File

@@ -0,0 +1,25 @@
.. zulip documentation master file, created by
sphinx-quickstart on Mon Aug 17 16:24:04 2015.
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
Welcome to Zulip documentation!
===============================
Contents:
.. toctree::
:maxdepth: 2
new-feature-tutorial
code-style
directory-structure
testing
Indices and tables
==================
* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`

View File

@@ -0,0 +1,216 @@
====================
New Feature Tutorial
====================
The changes needed to add a new feature will vary, of course, but this document
provides a general outline of what you may need to do, as well as an example of
the specific steps needed to add a new feature: adding a new option to the
application that is dynamically synced through the data system in real-time to
all browsers the user may have open.
General Process
===============
Adding a field to the database
------------------------------
**Update the model:** The server accesses the underlying database in `zerver/
models.py`. Add a new field in the appropriate class.
**Create and run the migration:** To create and apply a migration, run: ::
./manage.py makemigrations
./manage.py migrate
**Test your changes:** Once you've run the migration, restart memcached on your
development server (``/etc/init.d/memcached restart``) and then restart
``run-dev.py`` to avoid interacting with cached objects.
Backend changes
---------------
**Database interaction:** Add any necessary code for updating and interacting
with the database in ``zerver/lib/actions.py``. It should update the database and
send an event announcing the change.
**Application state:** Modify the ``fetch_initial_state_data`` and ``apply_events``
functions in ``zerver/lib/actions.py`` to update the state based on the event you
just created.
**Backend implementation:** Make any other modifications to the backend required for
your change.
**Testing:** At the very least, add a test of your event data flowing through
the system in ``test_events.py``.
Frontend changes
----------------
**JavaScript:** Zulip's JavaScript is located in the directory ``static/js/``.
The exact files you may need to change depend on your feature. If you've added a
new event that is sent to clients, be sure to add a handler for it to
``static/js/server_events.js``.
**CSS:** The primary CSS file is ``static/styles/zulip.css``. If your new
feature requires UI changes, you may need to add additional CSS to this file.
**Templates:** The initial page structure is rendered via Django templates
located in ``template/server``. For JavaScript, Zulip uses Handlebars templates located in
``static/templates``. Templates are precompiled as part of the build/deploy
process.
**Testing:** There are two types of frontend tests: node-based unit tests and
blackbox end-to-end tests. The blackbox tests are run in a headless browser
using Casper.js and are located in ``zerver/tests/frontend/tests/``. The unit
tests use Node's ``assert`` module are located in ``zerver/tests/frontend/node/``.
For more information on writing and running tests see the :doc:`testing
documentation <testing>`.
Example Feature
===============
This example describes the process of adding a new setting to Zulip:
a flag that restricts inviting new users to admins only (the default behavior
is that any user can invite other users). It is based on an actual Zulip feature,
and you can review `the original commit in the Zulip git repo <https://github.com/zulip/zulip/commit/5b7f3466baee565b8e5099bcbd3e1ccdbdb0a408>`_.
(Note that Zulip has since been upgraded from Django 1.6 to 1.8, so the migration
format has changed.)
First, update the database and model to store the new setting. Add a
new boolean field, ``realm_invite_by_admins_only``, to the Realm model in
``zerver/models.py``.
Then create a Django migration that adds a new field, ``invite_by_admins_only``,
to the ``zerver_realm`` table.
In ``zerver/lib/actions.py``, create a new function named
``do_set_realm_invite_by_admins_only``. This function will update the database
and trigger an event to notify clients when this setting changes. In this case
there was an exisiting ``realm|update`` event type which was used for setting
similar flags on the Realm model, so it was possible to add a new property to
that event rather than creating a new one. The property name matches the
database field to make it easy to understand what it indicates.
The second argument to ``send_event`` is the list of users whose browser
sessions should be notified. Depending on the setting, this can be a single user
(if the setting is a personal one, like time display format), only members in a
particular stream or all active users in a realm. ::
# zerver/lib/actions.py
def do_set_realm_invite_by_admins_only(realm, invite_by_admins_only):
realm.invite_by_admins_only = invite_by_admins_only
realm.save(update_fields=['invite_by_admins_only'])
event = dict(
type="realm",
op="update",
property='invite_by_admins_only',
value=invite_by_admins_only,
)
send_event(event, active_user_ids(realm))
return {}
You then need to add code that will handle the event and update the application
state. In ``zerver/lib/actions.py`` update the ``fetch_initial_state`` and
``apply_events`` functions. ::
def fetch_initial_state_data(user_profile, event_types, queue_id):
# ...
state['realm_invite_by_admins_only'] = user_profile.realm.invite_by_admins_only`
In this case you don't need to change ``apply_events`` because there is already
code that will correctly handle the realm update event type: ::
def apply_events(state, events, user_profile):
for event in events:
# ...
elif event['type'] == 'realm':
field = 'realm_' + event['property']
state[field] = event['value']
You then need to add a view for clients to access that will call the newly-added
``actions.py`` code to update the database. This example feature adds a new
parameter that should be sent to clients when the application loads and be
accessible via JavaScript, and there is already a view that does this for
related flags: ``update_realm``. So in this case, we can add out code to the
exisiting view instead of creating a new one. ::
# zerver/views/__init__.py
def home(request):
# ...
page_params = dict(
# ...
realm_invite_by_admins_only = register_ret['realm_invite_by_admins_only'],
# ...
)
Since this feature also adds a checkbox to the admin page, and adds a new
property the Realm model that can be modified from there, you also need to make
changes to the ``update_realm`` function in the same file: ::
# zerver/views/__init__.py
def update_realm(request, user_profile,
name=REQ(validator=check_string, default=None),
restricted_to_domain=REQ(validator=check_bool, default=None),
invite_by_admins_only=REQ(validator=check_bool,default=None)):
# ...
if invite_by_admins_only is not None and
realm.invite_by_admins_only != invite_by_admins_only:
do_set_realm_invite_by_admins_only(realm, invite_by_admins_only)
data['invite_by_admins_only'] = invite_by_admins_only
Then make the required front end changes: in this case a checkbox needs to be
added to the admin page (and its value added to the data sent back to server
when a realm is updated) and the change event needs to be handled on the client.
To add the checkbox to the admin page, modify the relevant template,
``static/templates/admin_tab.handlebars`` (omitted here since it is relatively
straightforward). Then add code to handle changes to the new form control in
``static/js/admin.js``. ::
var url = "/json/realm";
var new_invite_by_admins_only =
$("#id_realm_invite_by_admins_only").prop("checked");
data[invite_by_admins_only] = JSON.stringify(new_invite_by_admins_only);
channel.patch({
url: url,
data: data,
success: function (data) {
# ...
if (data.invite_by_admins_only) {
ui.report_success("New users must be invited by an admin!", invite_by_admins_only_status);
} else {
ui.report_success("Any user may now invite new users!", invite_by_admins_only_status);
}
# ...
}
});
Finally, update ``server_events.js`` to handle related events coming from the
server. ::
# static/js/server_events.js
function get_events_success(events) {
# ...
var dispatch_event = function dispatch_event(event) {
switch (event.type) {
# ...
case 'realm':
if (event.op === 'update' && event.property === 'invite_by_admins_only') {
page_params.realm_invite_by_admins_only = event.value;
}
}
}
Any code needed to update the UI should be placed in ``dispatch_event`` callback
(rather than the ``channel.patch``) function. This ensures the appropriate code
will run even if the changes are made in another browser window. In this example
most of the changes are on the backend, so no UI updates are required.

View File

@@ -0,0 +1 @@
# Empty requirements.txt to avoid readthedocs installing all our dependencies.

323
docs/testing.rst Normal file
View File

@@ -0,0 +1,323 @@
=======
Testing
=======
Running tests
=============
To run everything, just use ``./tools/test-all``. This runs lint checks,
web frontend / whole-system blackbox tests, and backend Django tests.
If you want to run individual parts, see the various commands inside
that script.
Schema and initial data changes
-------------------------------
If you change the database schema or change the initial test data, you
have have to regenerate the pristine test database by running
``tools/do-destroy-rebuild-test-database``.
Wiping the test databases
-------------------------
You should first try running: ``tools/do-destroy-rebuild-test-database``
If that fails you should try to do:
::
sudo -u postgres psql
> DROP DATABASE zulip_test;
> DROP DATABASE zulip_test_template;
and then run ``tools/do-destroy-rebuild-test-database``
Recreating the postgres cluster
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. warning::
**This is irreversible, so do it with care, and never do this anywhere
in production.**
If your postgres cluster (collection of databases) gets totally trashed
permissions-wise, and you can't otherwise repair it, you can recreate
it. On Ubuntu:
::
sudo pg_dropcluster --stop 9.1 main
sudo pg_createcluster --locale=en_US.utf8 --start 9.1 main
Backend Django tests
--------------------
These live in ``zerver/tests.py`` and ``zerver/test_*.py``. Run them
with ``tools/test-backend``.
Web frontend black-box casperjs tests
-------------------------------------
These live in ``frontend_tests/casper_tests/``. This is a "black box"
test; we load the frontend in a real (headless) browser, from a real dev
server, and simulate UI interactions like sending messages, narrowing,
etc.
Since this is interacting with a real dev server, it can catch backend
bugs as well.
You can run this with ``./tools/test-js-with-casper`` or as
``./tools/test-js-with-casper 05-settings.js`` to run a single test
file from ``frontend_tests/casper_tests/``.
Writing Casper tests
~~~~~~~~~~~~~~~~~~~~
Probably the easiest way to learn how to write Casper tests is to
study some of the existing test files. There are a few tips that can
be useful for writing Casper tests in addition to the debugging notes
below:
- Run just the file containing your new tests as described above to
have a fast debugging cycle.
- With frontend tests in general, it's very important to write your
code to wait for the right events. Before essentially every action
you take on the page, you'll want to use ``waitForSelector``,
``waitUntilVisible``, or a similar function to make sure the page or
elemant is ready before you interact with it. For instance, if you
want to click a button that you can select via ``#btn-submit``, and
then check that it causes ``success-elt`` to appear, you'll want to
write something like:
::
casper.waitForSelector("#btn-submit", function () {
casper.click('#btn-submit')
casper.test.assertExists("#success-elt");
});
This will ensure that the element is present before the interaction
is attempted. The various wait functions supported in Casper are
documented in the Casper here:
http://docs.casperjs.org/en/latest/modules/casper.html#waitforselector
and the various assert statements available are documented here:
http://docs.casperjs.org/en/latest/modules/tester.html#the-tester-prototype
- Casper uses CSS3 selectors; you can often save time by testing and
debugigng your selectors on the relevant page of the Zulip
development app in the Chrome javascript console by using
e.g. ``$$("#settings-dropdown")``.
- The test suite uses a smaller set of default user accounts and other
data initialized in the database than the development environment;
to see what differs check out the section related to
``options["test_suite"]`` in
``zilencer/management/commands/populate_db.py``.
- Casper effectively runs your test file in two phases -- first it
runs the code in the test file, which for most test files will just
collect a series of steps (each being a ``casper.then`` or
``casper.wait...`` call). Then, usually at the end of the test
file, you'll have a ``casper.run`` call which actually runs that
series of steps. This means that if you If you write code in your
test file outside a ``casper.then`` or ``casper.wait...`` method, it
will actually run before all the Casper test steps that are declared
in the file, which can lead to confusing failures where the new code
you write in between two ``casper.then`` blocks actually runs before
either of them. See this for more details about how Casper works:
http://docs.casperjs.org/en/latest/faq.html#how-does-then-and-the-step-stack-work
Debugging Casper.JS
~~~~~~~~~~~~~~~~~~~
Casper.js (via PhantomJS) has support for remote debugging. However, it
is not perfect. Here are some steps for using it and gotchas you might
want to know.
To turn on remote debugging, pass ``--remote-debug`` to the
``./frontend_tests/tests/run`` script. This will run the tests with
port ``7777`` open for remote debugging. You can now connect to
``localhost:7777`` in a Webkit browser. Somewhat recent versions of
Chrome or Safari might be required.
- When connecting to the remote debugger, you will see a list of pages,
probably 2. One page called ``about:blank`` is the headless page in
which the CasperJS test itself is actually running in. This is where
your test code is.
- The other page, probably ``localhost:9981``, is the Zulip page that
the test is testing---that is, the page running our app that our test
is exercising.
Since the tests are now running, you can open the ``about:blank`` page,
switch to the Scripts tab, and open the running ``0x-foo.js`` test. If
you set a breakpoint and it is hit, the inspector will pause and you can
do your normal JS debugging. You can also put breakpoints in the Zulip
webpage itself if you wish to inspect the state of the Zulip frontend.
If you need to use print debugging in casper, you can do using
``casper.log``; see http://docs.casperjs.org/en/latest/logging.html
for details.
An additional debugging technique is to enable verbose mode in the
Casper tests; you can do this by adding to the top of the relevant
test file the following:
::
var casper = require('casper').create({
verbose: true,
logLevel: "debug"
});
This can sometimes give insight into exactly what's happening.
Web frontend unit tests
-----------------------
As an alternative to the black-box whole-app testing, you can unit test
individual JavaScript files that use the module pattern. For example, to
test the ``foobar.js`` file, you would first add the following to the
bottom of ``foobar.js``:
::
if (typeof module !== 'undefined') {
module.exports = foobar;
}
This makes ``foobar.js`` follow the CommonJS module pattern, so it can
be required in Node.js, which runs our tests.
Now create ``frontend_tests/node_tests/foobar.js``. At the top, require
the `Node.js assert module <http://nodejs.org/api/assert.html>`__, and
the module you're testing, like so:
::
var assert = require('assert');
var foobar = require('js/foobar.js');
(If the module you're testing depends on other modules, or modifies
global state, you need to also read `the next section`__.)
__ handling-dependencies_
Define and call some tests using the `assert
module <http://nodejs.org/api/assert.html>`__. Note that for "equal"
asserts, the *actual* value comes first, the *expected* value second.
::
(function test_somefeature() {
assert.strictEqual(foobar.somefeature('baz'), 'quux');
assert.throws(foobar.somefeature('Invalid Input'));
}());
The test runner (index.js) automatically runs all .js files in the
frontend_tests/node directory.
.. _handling-dependencies:
Handling dependencies in unit tests
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The following scheme helps avoid tests leaking globals between each
other.
First, if you can avoid globals, do it, and the code that is directly
under test can simply be handled like this:
::
var search = require('js/search_suggestion.js');
For deeper dependencies, you want to categorize each module as follows:
- Exercise the module's real code for deeper, more realistic testing?
- Stub out the module's interface for more control, speed, and
isolation?
- Do some combination of the above?
For all the modules where you want to run actual code, add a statement
like the following to the top of your test file:
::
add_dependencies({
_: 'third/underscore/underscore.js',
util: 'js/util.js',
Dict: 'js/dict.js',
Handlebars: 'handlebars',
Filter: 'js/filter.js',
typeahead_helper: 'js/typeahead_helper.js',
stream_data: 'js/stream_data.js',
narrow: 'js/narrow.js'
});
For modules that you want to completely stub out, please use a pattern
like this:
::
set_global('page_params', {
email: 'bob@zulip.com'
});
// then maybe further down
global.page_params.email = 'alice@zulip.com';
Finally, there's the hybrid situation, where you want to borrow some of
a module's real functionality but stub out other pieces. Obviously, this
is a pretty strong smell that the other module might be lacking in
cohesion, but that code might be outside your jurisdiction. The pattern
here is this:
::
// Use real versions of parse/unparse
var narrow = require('js/narrow.js');
set_global('narrow', {
parse: narrow.parse,
unparse: narrow.unparse
});
// But later, I want to stub the stream without having to call super-expensive
// real code like narrow.activate().
global.narrow.stream = function () {
return 'office';
};
Coverage reports
~~~~~~~~~~~~~~~~
You can automatically generate coverage reports for the JavaScript unit
tests. To do so, install istanbul:
::
sudo npm install -g istanbul
And run test-js-with-node with the 'cover' parameter:
::
tools/test-js-with-node cover
Then open ``coverage/lcov-report/js/index.html`` in your browser.
Modules we don't test *at all* aren't listed in the report, so this
tends to overstate how good our overall coverage is, but it's accurate
for individual files. You can also click a filename to see the specific
statements and branches not tested. 100% branch coverage isn't
necessarily possible, but getting to at least 80% branch coverage is a
good goal.
Manual testing (local app + web browser)
========================================
Setting up the manual testing database
--------------------------------------
::
./tools/do-destroy-rebuild-database
Will populate your local database with all the usual accounts plus some
test messages involving Shakespeare characters.

2
frontend_tests/casper_lib/.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
/server.log
/test_credentials.js

View File

@@ -2,6 +2,8 @@ var common = (function () {
var exports = {};
var test_credentials = require('../casper_lib/test_credentials.js').test_credentials;
function timestamp() {
return new Date().getTime();
}
@@ -11,7 +13,7 @@ var last_send_or_update = -1;
function log_in(credentials) {
if (credentials === undefined) {
credentials = {username: 'iago@zulip.com', password: 'JhwLkBydEG1tAL5P'};
credentials = test_credentials.default_user;
}
casper.test.info('Logging in');
@@ -22,6 +24,10 @@ function log_in(credentials) {
}
exports.initialize_casper = function (viewport) {
if (casper.zulip_initialized !== undefined) {
return;
}
casper.zulip_initialized = true;
// These initialization steps will fail if they run before
// casper.start has been called.
@@ -57,6 +63,17 @@ exports.initialize_casper = function (viewport) {
last_send_or_update = timestamp();
}
});
casper.on('load.finished', function () {
casper.evaluateOrDie(function () {
$(document).trigger($.Event('phantom_page_loaded'));
return true;
});
});
casper.evaluate(function () {
window.localStorage.clear();
});
};
exports.then_log_in = function (credentials) {
@@ -99,7 +116,9 @@ exports.check_form = function (form_selector, expected, test_name) {
}
};
exports.send_message = function (type, params) {
// Wait for any previous send to finish, then send a message.
exports.then_send_message = function (type, params) {
casper.waitForSelector('#compose-send-button:enabled');
casper.waitForSelector('#new_message_content', function () {
if(type === "stream") {
casper.page.sendEvent('keypress', "c");
@@ -112,18 +131,11 @@ exports.send_message = function (type, params) {
}
casper.fill('form[action^="/json/send_message"]', params);
casper.click('#compose-send-button');
casper.waitFor(function emptyComposeBox() {
return casper.getFormValues('form[action^="/json/send_message"]').content === '';
}, function () {
last_send_or_update = timestamp();
});
});
};
// Wait for any previous send to finish, then send a message.
exports.wait_and_send = function (type, params) {
casper.waitForSelector('#compose-send-button:enabled', function () {
exports.send_message(type, params);
casper.waitFor(function emptyComposeBox() {
return casper.getFormValues('form[action^="/json/send_message"]').content === '';
}, function () {
last_send_or_update = timestamp();
});
};
@@ -136,7 +148,7 @@ exports.get_rendered_messages = function (table) {
return casper.evaluate(function (table) {
var tbl = $('#'+table);
return {
headings: $.map(tbl.find('.recipient_row .right_part'), function (elem) {
headings: $.map(tbl.find('.recipient_row .message-header-contents'), function (elem) {
return elem.innerText;
}),
@@ -149,6 +161,12 @@ exports.get_rendered_messages = function (table) {
});
};
exports.get_form_field_value = function (selector) {
return casper.evaluate(function (selector) {
return $(selector).val();
}, selector);
};
// Inject key presses by running some jQuery code in page context.
// PhantomJS and CasperJS don't provide a clean way to insert key
// presses by code, only strings of printable characters.
@@ -160,10 +178,10 @@ exports.keypress = function (code) {
});
};
// Send a whole list of messages using wait_and_send.
exports.send_many = function (msgs) {
// Send a whole list of messages using then_send_message.
exports.then_send_many = function (msgs) {
msgs.forEach(function (msg) {
exports.wait_and_send(
exports.then_send_message(
(msg.stream !== undefined) ? 'stream' : 'private',
msg);
});

View File

@@ -1,4 +1,4 @@
var common = require('../common.js').common;
var common = require('../casper_lib/common.js').common;
// Start of test script.
casper.start('http://localhost:9981/', common.initialize_casper);
@@ -10,7 +10,7 @@ casper.then(function () {
common.then_log_in();
casper.then(function () {
casper.waitForSelector('#zhome', function () {
casper.test.info('Logging out');
casper.click('li[title="Log out"] a');
});

View File

@@ -10,7 +10,7 @@
// For example, utils.dump() prints an Object with nice formatting.
var utils = require('utils');
var common = require('../common.js').common;
var common = require('../casper_lib/common.js').common;
common.start_and_log_in();
@@ -36,7 +36,7 @@ casper.then(function () {
// Send some messages.
common.send_many([
common.then_send_many([
{ stream: 'Verona', subject: 'frontend test',
content: 'test message A' },
@@ -73,7 +73,7 @@ common.wait_for_receive(function () {
casper.test.info('Sending more messages');
});
common.send_many([
common.then_send_many([
{ stream: 'Verona', subject: 'frontend test',
content: 'test message D' },

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