Generate guest access token on 3pid invites
This means that following the same link across multiple sessions or devices can re-use the same guest account. Note that this is somewhat of an abuse vector; we can't throw up captchas on this flow, so this is a way of registering ephemeral accounts for spam, whose sign-up we don't rate limit.pull/604/head
parent
869580206d
commit
33300673b7
|
@ -349,3 +349,18 @@ class RegistrationHandler(BaseHandler):
|
||||||
|
|
||||||
def auth_handler(self):
|
def auth_handler(self):
|
||||||
return self.hs.get_handlers().auth_handler
|
return self.hs.get_handlers().auth_handler
|
||||||
|
|
||||||
|
@defer.inlineCallbacks
|
||||||
|
def guest_access_token_for(self, medium, address, inviter_user_id):
|
||||||
|
access_token = yield self.store.get_3pid_guest_access_token(medium, address)
|
||||||
|
if access_token:
|
||||||
|
defer.returnValue(access_token)
|
||||||
|
|
||||||
|
_, access_token = yield self.register(
|
||||||
|
generate_token=True,
|
||||||
|
make_guest=True
|
||||||
|
)
|
||||||
|
access_token = yield self.store.save_or_get_3pid_guest_access_token(
|
||||||
|
medium, address, access_token, inviter_user_id
|
||||||
|
)
|
||||||
|
defer.returnValue(access_token)
|
||||||
|
|
|
@ -848,6 +848,13 @@ class RoomMemberHandler(BaseHandler):
|
||||||
user.
|
user.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
registration_handler = self.hs.get_handlers().registration_handler
|
||||||
|
guest_access_token = yield registration_handler.guest_access_token_for(
|
||||||
|
medium=medium,
|
||||||
|
address=address,
|
||||||
|
inviter_user_id=inviter_user_id,
|
||||||
|
)
|
||||||
|
|
||||||
is_url = "%s%s/_matrix/identity/api/v1/store-invite" % (
|
is_url = "%s%s/_matrix/identity/api/v1/store-invite" % (
|
||||||
id_server_scheme, id_server,
|
id_server_scheme, id_server,
|
||||||
)
|
)
|
||||||
|
@ -864,6 +871,7 @@ class RoomMemberHandler(BaseHandler):
|
||||||
"sender": inviter_user_id,
|
"sender": inviter_user_id,
|
||||||
"sender_display_name": inviter_display_name,
|
"sender_display_name": inviter_display_name,
|
||||||
"sender_avatar_url": inviter_avatar_url,
|
"sender_avatar_url": inviter_avatar_url,
|
||||||
|
"guest_access_token": guest_access_token,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
# TODO: Check for success
|
# TODO: Check for success
|
||||||
|
|
|
@ -387,3 +387,47 @@ class RegistrationStore(SQLBaseStore):
|
||||||
"find_next_generated_user_id",
|
"find_next_generated_user_id",
|
||||||
_find_next_generated_user_id
|
_find_next_generated_user_id
|
||||||
)))
|
)))
|
||||||
|
|
||||||
|
@defer.inlineCallbacks
|
||||||
|
def get_3pid_guest_access_token(self, medium, address):
|
||||||
|
ret = yield self._simple_select_one(
|
||||||
|
"threepid_guest_access_tokens",
|
||||||
|
{
|
||||||
|
"medium": medium,
|
||||||
|
"address": address
|
||||||
|
},
|
||||||
|
["guest_access_token"], True, 'get_3pid_guest_access_token'
|
||||||
|
)
|
||||||
|
if ret:
|
||||||
|
defer.returnValue(ret["guest_access_token"])
|
||||||
|
defer.returnValue(None)
|
||||||
|
|
||||||
|
@defer.inlineCallbacks
|
||||||
|
def save_or_get_3pid_guest_access_token(
|
||||||
|
self, medium, address, access_token, inviter_user_id
|
||||||
|
):
|
||||||
|
"""
|
||||||
|
Gets the 3pid's guest access token if exists, else saves access_token.
|
||||||
|
|
||||||
|
:param medium (str): Medium of the 3pid. Must be "email".
|
||||||
|
:param address (str): 3pid address.
|
||||||
|
:param access_token (str): The access token to persist if none is
|
||||||
|
already persisted.
|
||||||
|
:param inviter_user_id (str): User ID of the inviter.
|
||||||
|
:return (deferred str): Whichever access token is persisted at the end
|
||||||
|
of this function call.
|
||||||
|
"""
|
||||||
|
def insert(txn):
|
||||||
|
txn.execute(
|
||||||
|
"INSERT INTO threepid_guest_access_tokens "
|
||||||
|
"(medium, address, guest_access_token, first_inviter) "
|
||||||
|
"VALUES (?, ?, ?, ?)",
|
||||||
|
(medium, address, access_token, inviter_user_id)
|
||||||
|
)
|
||||||
|
|
||||||
|
try:
|
||||||
|
yield self.runInteraction("save_3pid_guest_access_token", insert)
|
||||||
|
defer.returnValue(access_token)
|
||||||
|
except self.database_engine.module.IntegrityError:
|
||||||
|
ret = yield self.get_3pid_guest_access_token(medium, address)
|
||||||
|
defer.returnValue(ret)
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
/* Copyright 2016 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
-- Stores guest account access tokens generated for unbound 3pids.
|
||||||
|
CREATE TABLE threepid_guest_access_tokens(
|
||||||
|
medium TEXT, -- The medium of the 3pid. Must be "email".
|
||||||
|
address TEXT, -- The 3pid address.
|
||||||
|
guest_access_token TEXT, -- The access token for a guest user for this 3pid.
|
||||||
|
first_inviter TEXT -- User ID of the first user to invite this 3pid to a room.
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE UNIQUE INDEX threepid_guest_access_tokens_index ON threepid_guest_access_tokens(medium, address);
|
Loading…
Reference in New Issue