diff --git a/README.md b/README.md index a2aaf0a76f..559c801140 100644 --- a/README.md +++ b/README.md @@ -192,8 +192,10 @@ mind: Browsing this list can be a great way to find feature ideas to implement that other Zulip users are excited about. -* [2016 roadmap milestone](http://zulip.readthedocs.io/en/latest/roadmap.html): The - projects that are [priorities for the Zulip project](https://zulip.readthedocs.io/en/latest/roadmap.html). These are great projects if you're looking to make an impact. +* [2016 roadmap milestone](http://zulip.readthedocs.io/en/latest/roadmap.html): + The projects that are + [priorities for the Zulip project](https://zulip.readthedocs.io/en/latest/roadmap.html). + These are great projects if you're looking to make an impact. Another way to find issues in Zulip is to take advantage of our "area:" convention in separating out issues. We partition all of diff --git a/docs/bots-guide.md b/docs/bots-guide.md index b20499de5c..fbd59cc6da 100644 --- a/docs/bots-guide.md +++ b/docs/bots-guide.md @@ -42,41 +42,59 @@ It presumes that you already have a fully implemented `.py` bot and now 3. Register a new bot on your Zulip server's web interface. - * Navigate to *Settings* -> *Your Bots* -> *Add a New Bot*, fill out the form and click on *Create Bot*. + * Navigate to *Settings* -> *Your Bots* -> *Add a New Bot*, fill + out the form and click on *Create Bot*. * A new bot should appear in the *Your Bots* panel. 4. Add the bot's configuration file on your Zulip server. - * In the *Your Bots* panel, click on the green icon to download its configuration file *.zuliprc* (the structure of this file is explained [here](#configuration-file). + * In the *Your Bots* panel, click on the green icon to download + its configuration file *.zuliprc* (the structure of this file is + explained [here](#configuration-file). * Copy the file to a destination of your choice on your Zulip server, e.g. to `~/.zuliprc` or `~/zuliprc-test`. 5. Subscribe the bot to the streams that the bot needs to read messages from or write messages to. - * To subscribe your bot to streams, navigate to *Manage Streams*. Select a stream and add your bot by its email address (the address you assigned in step 3). + * To subscribe your bot to streams, navigate to *Manage + Streams*. Select a stream and add your bot by its email address + (the address you assigned in step 3). * Now, the bot will do its job on the streams you subscribed it to. 6. Run the bot. * On your Zulip server (and outside the Vagrant environment), navigate to `~/zulip/contrib_bots/` - * Run `python run.py ~/zulip/contrib_bots/lib/.py --config-file ~/.zuliprc`. The `~/` before `.zuliprc` should point to the directory containing the file (in this case, it is the home directory). - * Check the output of the command. It should start with the text the `usage` function returns, followed by logging output similar to this: - ``` - INFO:root:starting message handling... - INFO:requests.packages.urllib3.connectionpool:Starting new HTTP connection (1): localhost - ``` + * Run `python run.py ~/zulip/contrib_bots/lib/.py + --config-file ~/.zuliprc`. The `~/` before `.zuliprc` should + point to the directory containing the file (in this case, it is + the home directory). + * Check the output of the command. It should start with the text + the `usage` function returns, followed by logging output similar + to this: + + ``` + INFO:root:starting message handling... + INFO:requests.packages.urllib3.connectionpool:Starting new HTTP connection (1): localhost + ``` + * Congrats! Now, your bot should be ready to test on the streams you've subscribed it to. ### Test the `followup.py` bot + 1. Do the previous steps for the `followup.py` bot. 2. Create the *followup* stream. -3. Subscribe the bot to the newly created *followup* stream and a stream you want to use it from, e.g. *social*. -4. Send a message to the stream you've subscribed the bot to (other than *followup*). If everything works, a copy of the message should now pop up in the *followup* stream. +3. Subscribe the bot to the newly created *followup* stream and a + stream you want to use it from, e.g. *social*. +4. Send a message to the stream you've subscribed the bot to (other + than *followup*). If everything works, a copy of the message should + now pop up in the *followup* stream. ## How to develop a bot -The tutorial below explains the structure of a bot `.py`. You can use this as boilerplate code for developing your own bot. +The tutorial below explains the structure of a bot `.py`. You +can use this as boilerplate code for developing your own bot. Every bot is built upon this structure: + ``` class MyBotHandler(object): ''' @@ -94,7 +112,11 @@ class MyBotHandler(object): handler_class = MyBotHandler ``` -* The class name (in this case *MyBotHandler*) can be defined by you and should match the name of your bot. To register your bot's class, adjust the last line `handler_class = MyBotHandler` to match your class name. + +* The class name (in this case *MyBotHandler*) can be defined by you + and should match the name of your bot. To register your bot's class, + adjust the last line `handler_class = MyBotHandler` to match your + class name. * Every bot needs to implement the functions * `usage(self)` @@ -104,7 +126,9 @@ handler_class = MyBotHandler * These functions are documented in the [next section](#bot-api). ## Bot API -This section documents the functions every bot needs to implement and the structure of the bot's config file. + +This section documents the functions every bot needs to implement and +the structure of the bot's config file. ### usage *usage(self)* @@ -212,13 +236,17 @@ None. site= ``` -* key - the API key you created for the bot; this is how Zulip knows the request is from an authorized user. +* key - the API key you created for the bot; this is how Zulip knows + the request is from an authorized user. * email - the email address of the bot, e.g. `some-bot@zulip.com` -* site - your development environment URL; if you are working on a development environment hosted on your computer, use `localhost:9991` +* site - your development environment URL; if you are working on a + development environment hosted on your computer, use + `localhost:9991` ## Common problems + * I modified my bot's code, yet the changes don't seem to have an effect. * Ensure that you restarted the `run.py` script. diff --git a/docs/dev-setup-non-vagrant.md b/docs/dev-setup-non-vagrant.md index 88611488ed..ff11aaf63a 100644 --- a/docs/dev-setup-non-vagrant.md +++ b/docs/dev-setup-non-vagrant.md @@ -320,7 +320,11 @@ Now run these commands: ./tools/install-mypy ./tools/setup/emoji/build_emoji ./scripts/setup/generate_secrets.py --development -if [ $(uname) = "OpenBSD" ]; then sudo cp ./puppet/zulip/files/postgresql/zulip_english.stop /var/postgresql/tsearch_data/; else sudo cp ./puppet/zulip/files/postgresql/zulip_english.stop /usr/share/postgresql/9.*/tsearch_data/; fi +if [ $(uname) = "OpenBSD" ]; then + sudo cp ./puppet/zulip/files/postgresql/zulip_english.stop /var/postgresql/tsearch_data/ +else + sudo cp ./puppet/zulip/files/postgresql/zulip_english.stop /usr/share/postgresql/9.*/tsearch_data/ +fi ./scripts/setup/configure-rabbitmq ./tools/setup/postgres-init-dev-db ./tools/do-destroy-rebuild-database diff --git a/docs/directory-structure.md b/docs/directory-structure.md index d16bfd3c15..1cfa8bddd2 100644 --- a/docs/directory-structure.md +++ b/docs/directory-structure.md @@ -13,9 +13,13 @@ Zulip uses the [Django web framework](https://docs.djangoproject.com/en/1.8/), so a lot of these paths will be familiar to Django developers. -* `zproject/urls.py` Main [Django routes file](https://docs.djangoproject.com/en/1.8/topics/http/urls/). Defines which URLs are handled by which view functions or templates. +* `zproject/urls.py` Main + [Django routes file](https://docs.djangoproject.com/en/1.8/topics/http/urls/). + Defines which URLs are handled by which view functions or templates. -* `zerver/models.py` Main [Django models](https://docs.djangoproject.com/en/1.8/topics/db/models/) file. Defines Zulip's database tables. +* `zerver/models.py` Main + [Django models](https://docs.djangoproject.com/en/1.8/topics/db/models/) + file. Defines Zulip's database tables. * `zerver/lib/actions.py` Most code doing writes to user-facing database tables. @@ -40,7 +44,8 @@ paths will be familiar to Django developers. See [our translating docs](translating.html) for details on Zulip's templating systems. -* `templates/zerver/` For [Jinja2](http://jinja.pocoo.org/) templates for the backend (for zerver app). +* `templates/zerver/` For [Jinja2](http://jinja.pocoo.org/) templates + for the backend (for zerver app). * `static/templates/` [Handlebars](http://handlebarsjs.com/) templates for the frontend. diff --git a/docs/life-of-a-request.md b/docs/life-of-a-request.md index fab4000752..6f56940b2a 100644 --- a/docs/life-of-a-request.md +++ b/docs/life-of-a-request.md @@ -21,10 +21,14 @@ are in your git checkout under `static`, and are served unminified. ## Nginx secures traffic with [SSL](prod-install.html) If you visit your Zulip server in your browser and discover that your -traffic isn't being properly encrypted, an [nginx misconfiguration](https://github.com/zulip/zulip/blob/master/puppet/zulip/files/nginx/sites-available/zulip-enterprise) is the +traffic isn't being properly encrypted, an [nginx misconfiguration][nginx-config] is the likely culprit. -## Static files are [served directly](https://github.com/zulip/zulip/blob/master/puppet/zulip/files/nginx/zulip-include-frontend/app) by Nginx +[nginx-config]: https://github.com/zulip/zulip/blob/master/puppet/zulip/files/nginx/sites-available/zulip-enterprise + +## Static files are [served directly][served-directly] by Nginx + +[served-directly]: https://github.com/zulip/zulip/blob/master/puppet/zulip/files/nginx/zulip-include-frontend/app Static files include JavaScript, css, static assets (like emoji, avatars), and user uploads (if stored locally and not on S3). @@ -36,7 +40,9 @@ location /static/ { } ``` -## Nginx routes other requests [between tornado and django](architecture-overview.html?highlight=tornado#tornado-and-django) +## Nginx routes other requests [between tornado and django][tornado-django] + +[tornado-django]: architecture-overview.html?highlight=tornado#tornado-and-django All our connected clients hold open long-polling connections so that they can recieve events (messages, presence notifications, and so on) in @@ -45,7 +51,9 @@ real-time. Events are served by Zulip's `tornado` application. Nearly every other kind of request is served by the `zerver` Django application. -[Here is the relevant nginx routing configuration.](https://github.com/zulip/zulip/blob/master/puppet/zulip/files/nginx/zulip-include-frontend/app) +[Here is the relevant nginx routing configuration.][nginx-config-link] + +[nginx-config-link]: https://github.com/zulip/zulip/blob/master/puppet/zulip/files/nginx/zulip-include-frontend/app ## Django routes the request to a view in urls.py files @@ -101,7 +109,9 @@ show my message multiple times. PATCH is special--it can be idempotent, and we like to write API endpoints in an idempotent fashion, as much as possible. -This [cookbook](http://restcookbook.com/) and [tutorial](http://www.restapitutorial.com/) can be helpful if you are new to REST web applications. +This [cookbook](http://restcookbook.com/) and +[tutorial](http://www.restapitutorial.com/) can be helpful if you are +new to REST web applications. ### PUT is only for creating new things @@ -137,7 +147,8 @@ In this way, the API is partially self-documenting. The endpoints from the legacy JSON API are written without REST in mind. They are used extensively by the web client, and use POST. -You can see them in [zproject/legacy_urls.py](https://github.com/zulip/zulip/blob/master/zproject/legacy_urls.py). +You can see them in +[zproject/legacy_urls.py](https://github.com/zulip/zulip/blob/master/zproject/legacy_urls.py). ### Webhook integrations may not be RESTful @@ -147,23 +158,29 @@ only POST. ## Django calls rest_dispatch for REST endpoints, and authenticates -For requests that correspond to a REST url pattern, Zulip configures its -url patterns (see [zerver/lib/rest.py](https://github.com/zulip/zulip/blob/master/zerver/lib/rest.py)) so that the action called is -`rest_dispatch`. This method will authenticate the user, either through -a session token from a cookie, or from an `email:api-key` string given -via HTTP Basic Auth for API clients. +For requests that correspond to a REST url pattern, Zulip configures +its url patterns (see +[zerver/lib/rest.py](https://github.com/zulip/zulip/blob/master/zerver/lib/rest.py)) +so that the action called is `rest_dispatch`. This method will +authenticate the user, either through a session token from a cookie, +or from an `email:api-key` string given via HTTP Basic Auth for API +clients. It will then look up what HTTP verb was used (GET, POST, etc) to make the request, and then figure out which view to show from that. In our example, + ``` {'GET': 'zerver.views.users.get_members_backend', 'PUT': 'zerver.views.users.create_user_backend'} ``` -is supplied as an argument to `rest_dispatch`, along with the [HTTPRequest](https://docs.djangoproject.com/en/1.8/ref/request-response/). + +is supplied as an argument to `rest_dispatch`, along with the +[HTTPRequest](https://docs.djangoproject.com/en/1.8/ref/request-response/). The request has the HTTP verb `PUT`, which `rest_dispatch` can use to -find the correct view to show: `zerver.views.users.create_user_backend`. +find the correct view to show: +`zerver.views.users.create_user_backend`. ## The view will authorize the user, extract request variables, and validate them @@ -176,7 +193,9 @@ return `json_error` in the case of an error, which gives a JSON string: `{'result': 'error', 'msg': }` -in a [HTTP Response](https://docs.djangoproject.com/en/1.8/ref/request-response/) with a content type of 'application/json'. +in a +[HTTP Response](https://docs.djangoproject.com/en/1.8/ref/request-response/) +with a content type of 'application/json'. To pass back data from the server to the calling client, in the event of a successfully handled request, we use `json_success(data=`. diff --git a/docs/prod-postgres.md b/docs/prod-postgres.md index 0cf41d6a5f..94759c1cc0 100644 --- a/docs/prod-postgres.md +++ b/docs/prod-postgres.md @@ -16,18 +16,29 @@ override that configuration). If you want to use a remote Postgresql database, you should configure the information about the connection with the server. You need a user called "zulip" in your database server. You can configure these -options in /etc/zulip/settings.py: +options in /etc/zulip/settings.py (the below descriptions are from the +Postgresql documentation): * REMOTE_POSTGRES_HOST: Name or IP address of the remote host -* REMOTE_POSTGRES_SSLMODE: SSL Mode used to connect to the server, different options you can use are: - * disable: I don't care about security, and I don't want to pay the overhead of encryption. - * allow: I don't care about security, but I will pay the overhead of encryption if the server insists on it. - * prefer: I don't care about encryption, but I wish to pay the overhead of encryption if the server supports it. - * require: I want my data to be encrypted, and I accept the overhead. I trust that the network will make sure I always connect to the server I want. - * verify-ca: I want my data encrypted, and I accept the overhead. I want to be sure that I connect to a server that I trust. - * verify-full: I want my data encrypted, and I accept the overhead. I want to be sure that I connect to a server I trust, and that it's the one I specify. +* REMOTE_POSTGRES_SSLMODE: SSL Mode used to connect to the server, + different options you can use are: + * disable: I don't care about security, and I don't want to pay the + overhead of encryption. + * allow: I don't care about security, but I will pay the overhead of + encryption if the server insists on it. + * prefer: I don't care about encryption, but I wish to pay the + overhead of encryption if the server supports it. + * require: I want my data to be encrypted, and I accept the + overhead. I trust that the network will make sure I always connect + to the server I want. + * verify-ca: I want my data encrypted, and I accept the overhead. I + want to be sure that I connect to a server that I trust. + * verify-full: I want my data encrypted, and I accept the + overhead. I want to be sure that I connect to a server I trust, + and that it's the one I specify. -Then you should specify the password of the user zulip for the database in /etc/zulip/zulip-secrets.conf: +Then you should specify the password of the user zulip for the +database in /etc/zulip/zulip-secrets.conf: ``` postgres_password = xxxx diff --git a/docs/writing-views.md b/docs/writing-views.md index d14d0db94d..f9658cdcf8 100644 --- a/docs/writing-views.md +++ b/docs/writing-views.md @@ -194,7 +194,9 @@ REQ also helps us with request variable validation. For example: integer (`converter` differs from `validator` in that it does not automatically marshall the input from JSON). -See [zerver/lib/validator.py](https://github.com/zulip/zulip/blob/master/zerver/lib/validator.py) for more validators and their documentation. +See +[zerver/lib/validator.py](https://github.com/zulip/zulip/blob/master/zerver/lib/validator.py) +for more validators and their documentation. ### Deciding which HTTP verb to use