forked from MirrorHub/synapse
Grant ASes the ability to create alias in their own namespace.
Add a new errcode type M_EXCLUSIVE when users try to create aliases inside AS namespaces, and when ASes try to create aliases outside their own namespace.
This commit is contained in:
parent
0227618d3c
commit
e426df8e10
4 changed files with 63 additions and 24 deletions
|
@ -380,6 +380,18 @@ class Auth(object):
|
||||||
raise AuthError(403, "Unrecognised access token.",
|
raise AuthError(403, "Unrecognised access token.",
|
||||||
errcode=Codes.UNKNOWN_TOKEN)
|
errcode=Codes.UNKNOWN_TOKEN)
|
||||||
|
|
||||||
|
@defer.inlineCallbacks
|
||||||
|
def get_appservice_by_req(self, request):
|
||||||
|
try:
|
||||||
|
token = request.args["access_token"][0]
|
||||||
|
service = yield self.store.get_app_service_by_token(token)
|
||||||
|
if not service:
|
||||||
|
raise AuthError(403, "Unrecognised access token.",
|
||||||
|
errcode=Codes.UNKNOWN_TOKEN)
|
||||||
|
defer.returnValue(service)
|
||||||
|
except KeyError:
|
||||||
|
raise AuthError(403, "Missing access token.")
|
||||||
|
|
||||||
def is_server_admin(self, user):
|
def is_server_admin(self, user):
|
||||||
return self.store.is_server_admin(user)
|
return self.store.is_server_admin(user)
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,8 @@ class Codes(object):
|
||||||
CAPTCHA_NEEDED = "M_CAPTCHA_NEEDED"
|
CAPTCHA_NEEDED = "M_CAPTCHA_NEEDED"
|
||||||
CAPTCHA_INVALID = "M_CAPTCHA_INVALID"
|
CAPTCHA_INVALID = "M_CAPTCHA_INVALID"
|
||||||
MISSING_PARAM = "M_MISSING_PARAM",
|
MISSING_PARAM = "M_MISSING_PARAM",
|
||||||
TOO_LARGE = "M_TOO_LARGE"
|
TOO_LARGE = "M_TOO_LARGE",
|
||||||
|
EXCLUSIVE = "M_EXCLUSIVE"
|
||||||
|
|
||||||
|
|
||||||
class CodeMessageException(RuntimeError):
|
class CodeMessageException(RuntimeError):
|
||||||
|
|
|
@ -37,24 +37,15 @@ class DirectoryHandler(BaseHandler):
|
||||||
)
|
)
|
||||||
|
|
||||||
@defer.inlineCallbacks
|
@defer.inlineCallbacks
|
||||||
def create_association(self, user_id, room_alias, room_id, servers=None):
|
def _create_association(self, room_alias, room_id, servers=None):
|
||||||
|
# general association creation for both human users and app services
|
||||||
# TODO(erikj): Do auth.
|
|
||||||
|
|
||||||
if not self.hs.is_mine(room_alias):
|
if not self.hs.is_mine(room_alias):
|
||||||
raise SynapseError(400, "Room alias must be local")
|
raise SynapseError(400, "Room alias must be local")
|
||||||
# TODO(erikj): Change this.
|
# TODO(erikj): Change this.
|
||||||
|
|
||||||
# TODO(erikj): Add transactions.
|
# TODO(erikj): Add transactions.
|
||||||
|
|
||||||
# TODO(erikj): Check if there is a current association.
|
# TODO(erikj): Check if there is a current association.
|
||||||
|
|
||||||
is_claimed = yield self.is_alias_exclusive_to_appservices(room_alias)
|
|
||||||
if is_claimed:
|
|
||||||
raise SynapseError(
|
|
||||||
400, "This alias is reserved by an application service."
|
|
||||||
)
|
|
||||||
|
|
||||||
if not servers:
|
if not servers:
|
||||||
servers = yield self.store.get_joined_hosts_for_room(room_id)
|
servers = yield self.store.get_joined_hosts_for_room(room_id)
|
||||||
|
|
||||||
|
@ -67,6 +58,33 @@ class DirectoryHandler(BaseHandler):
|
||||||
servers
|
servers
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@defer.inlineCallbacks
|
||||||
|
def create_association(self, user_id, room_alias, room_id, servers=None):
|
||||||
|
# association creation for human users
|
||||||
|
# TODO(erikj): Do user auth.
|
||||||
|
|
||||||
|
is_claimed = yield self.is_alias_exclusive_to_appservices(room_alias)
|
||||||
|
if is_claimed:
|
||||||
|
raise SynapseError(
|
||||||
|
400, "This alias is reserved by an application service.",
|
||||||
|
errcode=Codes.EXCLUSIVE
|
||||||
|
)
|
||||||
|
yield self._create_association(room_alias, room_id, servers)
|
||||||
|
|
||||||
|
|
||||||
|
@defer.inlineCallbacks
|
||||||
|
def create_appservice_association(self, service, room_alias, room_id,
|
||||||
|
servers=None):
|
||||||
|
if not service.is_interested_in_alias(room_alias.to_string()):
|
||||||
|
raise SynapseError(
|
||||||
|
400, "This application service has not reserved"
|
||||||
|
" this kind of alias.", errcode=Codes.EXCLUSIVE
|
||||||
|
)
|
||||||
|
|
||||||
|
# association creation for app services
|
||||||
|
yield self._create_association(room_alias, room_id, servers)
|
||||||
|
|
||||||
@defer.inlineCallbacks
|
@defer.inlineCallbacks
|
||||||
def delete_association(self, user_id, room_alias):
|
def delete_association(self, user_id, room_alias):
|
||||||
# TODO Check if server admin
|
# TODO Check if server admin
|
||||||
|
@ -77,7 +95,8 @@ class DirectoryHandler(BaseHandler):
|
||||||
is_claimed = yield self.is_alias_exclusive_to_appservices(room_alias)
|
is_claimed = yield self.is_alias_exclusive_to_appservices(room_alias)
|
||||||
if is_claimed:
|
if is_claimed:
|
||||||
raise SynapseError(
|
raise SynapseError(
|
||||||
400, "This alias is reserved by an application service."
|
400, "This alias is reserved by an application service.",
|
||||||
|
errcode=Codes.EXCLUSIVE
|
||||||
)
|
)
|
||||||
|
|
||||||
room_id = yield self.store.delete_room_alias(room_alias)
|
room_id = yield self.store.delete_room_alias(room_alias)
|
||||||
|
|
|
@ -45,8 +45,6 @@ class ClientDirectoryServer(ClientV1RestServlet):
|
||||||
|
|
||||||
@defer.inlineCallbacks
|
@defer.inlineCallbacks
|
||||||
def on_PUT(self, request, room_alias):
|
def on_PUT(self, request, room_alias):
|
||||||
user, client = yield self.auth.get_user_by_req(request)
|
|
||||||
|
|
||||||
content = _parse_json(request)
|
content = _parse_json(request)
|
||||||
if not "room_id" in content:
|
if not "room_id" in content:
|
||||||
raise SynapseError(400, "Missing room_id key",
|
raise SynapseError(400, "Missing room_id key",
|
||||||
|
@ -70,16 +68,25 @@ class ClientDirectoryServer(ClientV1RestServlet):
|
||||||
dir_handler = self.handlers.directory_handler
|
dir_handler = self.handlers.directory_handler
|
||||||
|
|
||||||
try:
|
try:
|
||||||
user_id = user.to_string()
|
# try to auth as a user
|
||||||
yield dir_handler.create_association(
|
user, client = yield self.auth.get_user_by_req(request)
|
||||||
user_id, room_alias, room_id, servers
|
try:
|
||||||
|
user_id = user.to_string()
|
||||||
|
yield dir_handler.create_association(
|
||||||
|
user_id, room_alias, room_id, servers
|
||||||
|
)
|
||||||
|
yield dir_handler.send_room_alias_update_event(user_id, room_id)
|
||||||
|
except SynapseError as e:
|
||||||
|
raise e
|
||||||
|
except:
|
||||||
|
logger.exception("Failed to create association")
|
||||||
|
raise
|
||||||
|
except AuthError:
|
||||||
|
# try to auth as an application service
|
||||||
|
service = yield self.auth.get_appservice_by_req(request)
|
||||||
|
yield dir_handler.create_appservice_association(
|
||||||
|
service, room_alias, room_id, servers
|
||||||
)
|
)
|
||||||
yield dir_handler.send_room_alias_update_event(user_id, room_id)
|
|
||||||
except SynapseError as e:
|
|
||||||
raise e
|
|
||||||
except:
|
|
||||||
logger.exception("Failed to create association")
|
|
||||||
raise
|
|
||||||
|
|
||||||
defer.returnValue((200, {}))
|
defer.returnValue((200, {}))
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue