diff --git a/docs/code_style.rst b/docs/code_style.rst
index 8d73d17beb..9c52cb3182 100644
--- a/docs/code_style.rst
+++ b/docs/code_style.rst
@@ -1,52 +1,119 @@
-Basically, PEP8
+- Everything should comply with PEP8. Code should pass
+ ``pep8 --max-line-length=100`` without any warnings.
-- NEVER tabs. 4 spaces to indent.
-- Max line width: 79 chars (with flexibility to overflow by a "few chars" if
+- **Indenting**:
+
+ - NEVER tabs. 4 spaces to indent.
+
+ - follow PEP8; either hanging indent or multiline-visual indent depending
+ on the size and shape of the arguments and what makes more sense to the
+ author. In other words, both this::
+
+ print("I am a fish %s" % "moo")
+
+ and this::
+
+ print("I am a fish %s" %
+ "moo")
+
+ and this::
+
+ print(
+ "I am a fish %s" %
+ "moo",
+ )
+
+ ...are valid, although given each one takes up 2x more vertical space than
+ the previous, it's up to the author's discretion as to which layout makes
+ most sense for their function invocation. (e.g. if they want to add
+ comments per-argument, or put expressions in the arguments, or group
+ related arguments together, or want to deliberately extend or preserve
+ vertical/horizontal space)
+
+- **Line length**:
+
+ Max line length is 79 chars (with flexibility to overflow by a "few chars" if
the overflowing content is not semantically significant and avoids an
explosion of vertical whitespace).
-- Use camel case for class and type names
-- Use underscores for functions and variables.
-- Use double quotes.
-- Use parentheses instead of '\\' for line continuation where ever possible
- (which is pretty much everywhere)
-- There should be max a single new line between:
+
+ Use parentheses instead of ``\`` for line continuation where ever possible
+ (which is pretty much everywhere).
+
+- **Naming**:
+
+ - Use camel case for class and type names
+ - Use underscores for functions and variables.
+
+- Use double quotes ``"foo"`` rather than single quotes ``'foo'``.
+
+- **Blank lines**:
+
+ - There should be max a single new line between:
+
- statements
- functions in a class
-- There should be two new lines between:
+
+ - There should be two new lines between:
+
- definitions in a module (e.g., between different classes)
-- There should be spaces where spaces should be and not where there shouldn't be:
- - a single space after a comma
- - a single space before and after for '=' when used as assignment
- - no spaces before and after for '=' for default values and keyword arguments.
-- Indenting must follow PEP8; either hanging indent or multiline-visual indent
- depending on the size and shape of the arguments and what makes more sense to
- the author. In other words, both this::
-
- print("I am a fish %s" % "moo")
-
- and this::
-
- print("I am a fish %s" %
- "moo")
-
- and this::
-
- print(
- "I am a fish %s" %
- "moo"
- )
-
- ...are valid, although given each one takes up 2x more vertical space than
- the previous, it's up to the author's discretion as to which layout makes most
- sense for their function invocation. (e.g. if they want to add comments
- per-argument, or put expressions in the arguments, or group related arguments
- together, or want to deliberately extend or preserve vertical/horizontal
- space)
-
-Comments should follow the `google code style <http://google.github.io/styleguide/pyguide.html?showone=Comments#Comments>`_.
-This is so that we can generate documentation with
-`sphinx <http://sphinxcontrib-napoleon.readthedocs.org/en/latest/>`_. See the
-`examples <http://sphinxcontrib-napoleon.readthedocs.io/en/latest/example_google.html>`_
-in the sphinx documentation.
-
-Code should pass pep8 --max-line-length=100 without any warnings.
+
+- **Whitespace**:
+
+ There should be spaces where spaces should be and not where there shouldn't
+ be:
+
+ - a single space after a comma
+ - a single space before and after for '=' when used as assignment
+ - no spaces before and after for '=' for default values and keyword arguments.
+
+- **Comments**: should follow the `google code style
+ <http://google.github.io/styleguide/pyguide.html?showone=Comments#Comments>`_.
+ This is so that we can generate documentation with `sphinx
+ <http://sphinxcontrib-napoleon.readthedocs.org/en/latest/>`_. See the
+ `examples
+ <http://sphinxcontrib-napoleon.readthedocs.io/en/latest/example_google.html>`_
+ in the sphinx documentation.
+
+- **Imports**:
+
+ - Prefer to import classes and functions than packages or modules.
+
+ Example::
+
+ from synapse.types import UserID
+ ...
+ user_id = UserID(local, server)
+
+ is preferred over::
+
+ from synapse import types
+ ...
+ user_id = types.UserID(local, server)
+
+ (or any other variant).
+
+ This goes against the advice in the Google style guide, but it means that
+ errors in the name are caught early (at import time).
+
+ - Multiple imports from the same package can be combined onto one line::
+
+ from synapse.types import GroupID, RoomID, UserID
+
+ An effort should be made to keep the individual imports in alphabetical
+ order.
+
+ If the list becomes long, wrap it with parentheses and split it over
+ multiple lines.
+
+ - As per `PEP-8 <https://www.python.org/dev/peps/pep-0008/#imports>`_,
+ imports should be grouped in the following order, with a blank line between
+ each group:
+
+ 1. standard library imports
+ 2. related third party imports
+ 3. local application/library specific imports
+
+ - Imports within each group should be sorted alphabetically by module name.
+
+ - Avoid wildcard imports (``from synapse.types import *``) and relative
+ imports (``from .types import UserID``).
diff --git a/docs/password_auth_providers.rst b/docs/password_auth_providers.rst
new file mode 100644
index 0000000000..d8a7b61cdc
--- /dev/null
+++ b/docs/password_auth_providers.rst
@@ -0,0 +1,99 @@
+Password auth provider modules
+==============================
+
+Password auth providers offer a way for server administrators to integrate
+their Synapse installation with an existing authentication system.
+
+A password auth provider is a Python class which is dynamically loaded into
+Synapse, and provides a number of methods by which it can integrate with the
+authentication system.
+
+This document serves as a reference for those looking to implement their own
+password auth providers.
+
+Required methods
+----------------
+
+Password auth provider classes must provide the following methods:
+
+*class* ``SomeProvider.parse_config``\(*config*)
+
+ This method is passed the ``config`` object for this module from the
+ homeserver configuration file.
+
+ It should perform any appropriate sanity checks on the provided
+ configuration, and return an object which is then passed into ``__init__``.
+
+*class* ``SomeProvider``\(*config*, *account_handler*)
+
+ The constructor is passed the config object returned by ``parse_config``,
+ and a ``synapse.module_api.ModuleApi`` object which allows the
+ password provider to check if accounts exist and/or create new ones.
+
+Optional methods
+----------------
+
+Password auth provider classes may optionally provide the following methods.
+
+*class* ``SomeProvider.get_db_schema_files``\()
+
+ This method, if implemented, should return an Iterable of ``(name,
+ stream)`` pairs of database schema files. Each file is applied in turn at
+ initialisation, and a record is then made in the database so that it is
+ not re-applied on the next start.
+
+``someprovider.get_supported_login_types``\()
+
+ This method, if implemented, should return a ``dict`` mapping from a login
+ type identifier (such as ``m.login.password``) to an iterable giving the
+ fields which must be provided by the user in the submission to the
+ ``/login`` api. These fields are passed in the ``login_dict`` dictionary
+ to ``check_auth``.
+
+ For example, if a password auth provider wants to implement a custom login
+ type of ``com.example.custom_login``, where the client is expected to pass
+ the fields ``secret1`` and ``secret2``, the provider should implement this
+ method and return the following dict::
+
+ {"com.example.custom_login": ("secret1", "secret2")}
+
+``someprovider.check_auth``\(*username*, *login_type*, *login_dict*)
+
+ This method is the one that does the real work. If implemented, it will be
+ called for each login attempt where the login type matches one of the keys
+ returned by ``get_supported_login_types``.
+
+ It is passed the (possibly UNqualified) ``user`` provided by the client,
+ the login type, and a dictionary of login secrets passed by the client.
+
+ The method should return a Twisted ``Deferred`` object, which resolves to
+ the canonical ``@localpart:domain`` user id if authentication is successful,
+ and ``None`` if not.
+
+ Alternatively, the ``Deferred`` can resolve to a ``(str, func)`` tuple, in
+ which case the second field is a callback which will be called with the
+ result from the ``/login`` call (including ``access_token``, ``device_id``,
+ etc.)
+
+``someprovider.check_password``\(*user_id*, *password*)
+
+ This method provides a simpler interface than ``get_supported_login_types``
+ and ``check_auth`` for password auth providers that just want to provide a
+ mechanism for validating ``m.login.password`` logins.
+
+ Iif implemented, it will be called to check logins with an
+ ``m.login.password`` login type. It is passed a qualified
+ ``@localpart:domain`` user id, and the password provided by the user.
+
+ The method should return a Twisted ``Deferred`` object, which resolves to
+ ``True`` if authentication is successful, and ``False`` if not.
+
+``someprovider.on_logged_out``\(*user_id*, *device_id*, *access_token*)
+
+ This method, if implemented, is called when a user logs out. It is passed
+ the qualified user ID, the ID of the deactivated device (if any: access
+ tokens are occasionally created without an associated device ID), and the
+ (now deactivated) access token.
+
+ It may return a Twisted ``Deferred`` object; the logout request will wait
+ for the deferred to complete but the result is ignored.
diff --git a/docs/url_previews.rst b/docs/url_previews.md
index 634d9d907f..665554e165 100644
--- a/docs/url_previews.rst
+++ b/docs/url_previews.md
@@ -56,6 +56,7 @@ As a first cut, let's do #2 and have the receiver hit the API to calculate its o
API
---
+```
GET /_matrix/media/r0/preview_url?url=http://wherever.com
200 OK
{
@@ -66,6 +67,7 @@ GET /_matrix/media/r0/preview_url?url=http://wherever.com
"og:description" : "“Synapse 0.12 is out! Lots of polishing, performance &amp; bugfixes: /sync API, /r0 prefix, fulltext search, 3PID invites https://t.co/5alhXLLEGP”"
"og:site_name" : "Twitter"
}
+```
* Downloads the URL
* If HTML, just stores it in RAM and parses it for OG meta tags
diff --git a/docs/user_directory.md b/docs/user_directory.md
new file mode 100644
index 0000000000..4c8ee44f37
--- /dev/null
+++ b/docs/user_directory.md
@@ -0,0 +1,17 @@
+User Directory API Implementation
+=================================
+
+The user directory is currently maintained based on the 'visible' users
+on this particular server - i.e. ones which your account shares a room with, or
+who are present in a publicly viewable room present on the server.
+
+The directory info is stored in various tables, which can (typically after
+DB corruption) get stale or out of sync. If this happens, for now the
+quickest solution to fix it is:
+
+```
+UPDATE user_directory_stream_pos SET stream_id = NULL;
+```
+
+and restart the synapse, which should then start a background task to
+flush the current tables and regenerate the directory.
|