Skip to content

Commit

Permalink
Merge branch 'develop' into application-services-txn-reliability
Browse files Browse the repository at this point in the history
Conflicts:
	synapse/storage/__init__.py
  • Loading branch information
kegsay committed Mar 26, 2015
2 parents f0d6f72 + 9ba6487 commit 4edcbce
Show file tree
Hide file tree
Showing 45 changed files with 1,247 additions and 727 deletions.
9 changes: 9 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
Changes in synapse v0.8.1 (2015-03-18)
======================================

* Disable registration by default. New users can be added using the command
``register_new_matrix_user`` or by enabling registration in the config.
* Add metrics to synapse. To enable metrics use config options
``enable_metrics`` and ``metrics_port``.
* Fix bug where banning only kicked the user.

Changes in synapse v0.8.0 (2015-03-06)
======================================

Expand Down
11 changes: 11 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,17 @@ To set up your homeserver, run (in your virtualenv, as before)::

Substituting your host and domain name as appropriate.

By default, registration of new users is disabled. You can either enable
registration in the config (it is then recommended to also set up CAPTCHA), or
you can use the command line to register new users::

$ source ~/.synapse/bin/activate
$ register_new_matrix_user -c homeserver.yaml https://localhost:8448
New user localpart: erikj
Password:
Confirm password:
Success!

For reliable VoIP calls to be routed via this homeserver, you MUST configure
a TURN server. See docs/turn-howto.rst for details.

Expand Down
149 changes: 149 additions & 0 deletions register_new_matrix_user
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Copyright 2015 OpenMarket Ltd
#
# 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.


import argparse
import getpass
import hashlib
import hmac
import json
import sys
import urllib2
import yaml


def request_registration(user, password, server_location, shared_secret):
mac = hmac.new(
key=shared_secret,
msg=user,
digestmod=hashlib.sha1,
).hexdigest()

data = {
"user": user,
"password": password,
"mac": mac,
"type": "org.matrix.login.shared_secret",
}

server_location = server_location.rstrip("/")

print "Sending registration request..."

req = urllib2.Request(
"%s/_matrix/client/api/v1/register" % (server_location,),
data=json.dumps(data),
headers={'Content-Type': 'application/json'}
)
try:
f = urllib2.urlopen(req)
f.read()
f.close()
print "Success."
except urllib2.HTTPError as e:
print "ERROR! Received %d %s" % (e.code, e.reason,)
if 400 <= e.code < 500:
if e.info().type == "application/json":
resp = json.load(e)
if "error" in resp:
print resp["error"]
sys.exit(1)


def register_new_user(user, password, server_location, shared_secret):
if not user:
try:
default_user = getpass.getuser()
except:
default_user = None

if default_user:
user = raw_input("New user localpart [%s]: " % (default_user,))
if not user:
user = default_user
else:
user = raw_input("New user localpart: ")

if not user:
print "Invalid user name"
sys.exit(1)

if not password:
password = getpass.getpass("Password: ")

if not password:
print "Password cannot be blank."
sys.exit(1)

confirm_password = getpass.getpass("Confirm password: ")

if password != confirm_password:
print "Passwords do not match"
sys.exit(1)

request_registration(user, password, server_location, shared_secret)


if __name__ == "__main__":
parser = argparse.ArgumentParser(
description="Used to register new users with a given home server when"
" registration has been disabled. The home server must be"
" configured with the 'registration_shared_secret' option"
" set.",
)
parser.add_argument(
"-u", "--user",
default=None,
help="Local part of the new user. Will prompt if omitted.",
)
parser.add_argument(
"-p", "--password",
default=None,
help="New password for user. Will prompt if omitted.",
)

group = parser.add_mutually_exclusive_group(required=True)
group.add_argument(
"-c", "--config",
type=argparse.FileType('r'),
help="Path to server config file. Used to read in shared secret.",
)

group.add_argument(
"-k", "--shared-secret",
help="Shared secret as defined in server config file.",
)

parser.add_argument(
"server_url",
default="https://localhost:8448",
nargs='?',
help="URL to use to talk to the home server. Defaults to "
" 'https://localhost:8448'.",
)

args = parser.parse_args()

if "config" in args and args.config:
config = yaml.safe_load(args.config)
secret = config.get("registration_shared_secret", None)
if not secret:
print "No 'registration_shared_secret' defined in config."
sys.exit(1)
else:
secret = args.shared_secret

register_new_user(args.user, args.password, args.server_url, secret)
4 changes: 2 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ def exec_file(path_segments):
version=version,
packages=find_packages(exclude=["tests", "tests.*"]),
description="Reference Synapse Home Server",
install_requires=dependencies["REQUIREMENTS"].keys(),
install_requires=dependencies['requirements'](include_conditional=True).keys(),
setup_requires=[
"Twisted==14.0.2", # Here to override setuptools_trial's dependency on Twisted>=2.4.0
"setuptools_trial",
Expand All @@ -55,5 +55,5 @@ def exec_file(path_segments):
include_package_data=True,
zip_safe=False,
long_description=long_description,
scripts=["synctl"],
scripts=["synctl", "register_new_matrix_user"],
)
2 changes: 1 addition & 1 deletion synapse/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,4 @@
""" This is a reference implementation of a Matrix home server.
"""

__version__ = "0.8.0"
__version__ = "0.8.1-r2"
36 changes: 24 additions & 12 deletions synapse/api/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,12 @@
logger = logging.getLogger(__name__)


AuthEventTypes = (
EventTypes.Create, EventTypes.Member, EventTypes.PowerLevels,
EventTypes.JoinRules,
)


class Auth(object):

def __init__(self, hs):
Expand Down Expand Up @@ -166,6 +172,7 @@ def is_membership_change_allowed(self, event, auth_events):
target = auth_events.get(key)

target_in_room = target and target.membership == Membership.JOIN
target_banned = target and target.membership == Membership.BAN

key = (EventTypes.JoinRules, "", )
join_rule_event = auth_events.get(key)
Expand Down Expand Up @@ -194,6 +201,7 @@ def is_membership_change_allowed(self, event, auth_events):
{
"caller_in_room": caller_in_room,
"caller_invited": caller_invited,
"target_banned": target_banned,
"target_in_room": target_in_room,
"membership": membership,
"join_rule": join_rule,
Expand All @@ -202,6 +210,11 @@ def is_membership_change_allowed(self, event, auth_events):
}
)

if ban_level:
ban_level = int(ban_level)
else:
ban_level = 50 # FIXME (erikj): What should we do here?

if Membership.INVITE == membership:
# TODO (erikj): We should probably handle this more intelligently
# PRIVATE join rules.
Expand All @@ -212,6 +225,10 @@ def is_membership_change_allowed(self, event, auth_events):
403,
"%s not in room %s." % (event.user_id, event.room_id,)
)
elif target_banned:
raise AuthError(
403, "%s is banned from the room" % (target_user_id,)
)
elif target_in_room: # the target is already in the room.
raise AuthError(403, "%s is already in the room." %
target_user_id)
Expand All @@ -221,6 +238,8 @@ def is_membership_change_allowed(self, event, auth_events):
# joined: It's a NOOP
if event.user_id != target_user_id:
raise AuthError(403, "Cannot force another user to join.")
elif target_banned:
raise AuthError(403, "You are banned from this room")
elif join_rule == JoinRules.PUBLIC:
pass
elif join_rule == JoinRules.INVITE:
Expand All @@ -238,6 +257,10 @@ def is_membership_change_allowed(self, event, auth_events):
403,
"%s not in room %s." % (target_user_id, event.room_id,)
)
elif target_banned and user_level < ban_level:
raise AuthError(
403, "You cannot unban user &s." % (target_user_id,)
)
elif target_user_id != event.user_id:
if kick_level:
kick_level = int(kick_level)
Expand All @@ -249,11 +272,6 @@ def is_membership_change_allowed(self, event, auth_events):
403, "You cannot kick user %s." % target_user_id
)
elif Membership.BAN == membership:
if ban_level:
ban_level = int(ban_level)
else:
ban_level = 50 # FIXME (erikj): What should we do here?

if user_level < ban_level:
raise AuthError(403, "You don't have permission to ban")
else:
Expand Down Expand Up @@ -370,7 +388,7 @@ def get_user_by_token(self, token):
AuthError if no user by that token exists or the token is invalid.
"""
try:
ret = yield self.store.get_user_by_token(token=token)
ret = yield self.store.get_user_by_token(token)
if not ret:
raise StoreError(400, "Unknown token")
user_info = {
Expand Down Expand Up @@ -412,12 +430,6 @@ def add_auth_events(self, builder, context):

builder.auth_events = auth_events_entries

context.auth_events = {
k: v
for k, v in context.current_state.items()
if v.event_id in auth_ids
}

def compute_auth_events(self, event, current_state):
if event.type == EventTypes.Create:
return []
Expand Down
1 change: 1 addition & 0 deletions synapse/api/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ class LoginType(object):
EMAIL_IDENTITY = u"m.login.email.identity"
RECAPTCHA = u"m.login.recaptcha"
APPLICATION_SERVICE = u"m.login.application_service"
SHARED_SECRET = u"org.matrix.login.shared_secret"


class EventTypes(object):
Expand Down
8 changes: 5 additions & 3 deletions synapse/app/homeserver.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,6 @@
import resource
import subprocess
import sqlite3
import syweb

logger = logging.getLogger(__name__)

Expand All @@ -83,6 +82,7 @@ def build_resource_for_app_services(self):
return AppServiceRestResource(self)

def build_resource_for_web_client(self):
import syweb
syweb_path = os.path.dirname(syweb.__file__)
webclient_path = os.path.join(syweb_path, "webclient")
return File(webclient_path) # TODO configurable?
Expand Down Expand Up @@ -130,7 +130,7 @@ def create_resource_tree(self, redirect_root_to_web_client):
True.
"""
config = self.get_config()
web_client = config.webclient
web_client = config.web_client

# list containing (path_str, Resource) e.g:
# [ ("/aaa/bbb/cc", Resource1), ("/aaa/dummy", Resource2) ]
Expand Down Expand Up @@ -343,7 +343,8 @@ def setup(config_options):

config.setup_logging()

check_requirements()
# check any extra requirements we have now we have a config
check_requirements(config)

version_string = get_version_string()

Expand Down Expand Up @@ -450,6 +451,7 @@ def in_thread():

def main():
with LoggingContext("main"):
# check base requirements
check_requirements()
hs = setup(sys.argv[1:])
run(hs)
Expand Down
Loading

0 comments on commit 4edcbce

Please sign in to comment.