mirror of
https://git.anonymousland.org/anonymousland/synapse.git
synced 2025-12-15 16:21:00 -05:00
Allow admins to require a manual approval process before new accounts can be used (using MSC3866) (#13556)
This commit is contained in:
parent
8625ad8099
commit
be76cd8200
21 changed files with 731 additions and 34 deletions
|
|
@ -28,7 +28,14 @@ from typing import (
|
|||
|
||||
from typing_extensions import TypedDict
|
||||
|
||||
from synapse.api.errors import Codes, InvalidClientTokenError, LoginError, SynapseError
|
||||
from synapse.api.constants import ApprovalNoticeMedium
|
||||
from synapse.api.errors import (
|
||||
Codes,
|
||||
InvalidClientTokenError,
|
||||
LoginError,
|
||||
NotApprovedError,
|
||||
SynapseError,
|
||||
)
|
||||
from synapse.api.ratelimiting import Ratelimiter
|
||||
from synapse.api.urls import CLIENT_API_PREFIX
|
||||
from synapse.appservice import ApplicationService
|
||||
|
|
@ -55,11 +62,11 @@ logger = logging.getLogger(__name__)
|
|||
|
||||
class LoginResponse(TypedDict, total=False):
|
||||
user_id: str
|
||||
access_token: str
|
||||
access_token: Optional[str]
|
||||
home_server: str
|
||||
expires_in_ms: Optional[int]
|
||||
refresh_token: Optional[str]
|
||||
device_id: str
|
||||
device_id: Optional[str]
|
||||
well_known: Optional[Dict[str, Any]]
|
||||
|
||||
|
||||
|
|
@ -92,6 +99,12 @@ class LoginRestServlet(RestServlet):
|
|||
hs.config.registration.refreshable_access_token_lifetime is not None
|
||||
)
|
||||
|
||||
# Whether we need to check if the user has been approved or not.
|
||||
self._require_approval = (
|
||||
hs.config.experimental.msc3866.enabled
|
||||
and hs.config.experimental.msc3866.require_approval_for_new_accounts
|
||||
)
|
||||
|
||||
self.auth = hs.get_auth()
|
||||
|
||||
self.clock = hs.get_clock()
|
||||
|
|
@ -220,6 +233,14 @@ class LoginRestServlet(RestServlet):
|
|||
except KeyError:
|
||||
raise SynapseError(400, "Missing JSON keys.")
|
||||
|
||||
if self._require_approval:
|
||||
approved = await self.auth_handler.is_user_approved(result["user_id"])
|
||||
if not approved:
|
||||
raise NotApprovedError(
|
||||
msg="This account is pending approval by a server administrator.",
|
||||
approval_notice_medium=ApprovalNoticeMedium.NONE,
|
||||
)
|
||||
|
||||
well_known_data = self._well_known_builder.get_well_known()
|
||||
if well_known_data:
|
||||
result["well_known"] = well_known_data
|
||||
|
|
@ -356,6 +377,16 @@ class LoginRestServlet(RestServlet):
|
|||
errcode=Codes.INVALID_PARAM,
|
||||
)
|
||||
|
||||
if self._require_approval:
|
||||
approved = await self.auth_handler.is_user_approved(user_id)
|
||||
if not approved:
|
||||
# If the user isn't approved (and needs to be) we won't allow them to
|
||||
# actually log in, so we don't want to create a device/access token.
|
||||
return LoginResponse(
|
||||
user_id=user_id,
|
||||
home_server=self.hs.hostname,
|
||||
)
|
||||
|
||||
initial_display_name = login_submission.get("initial_device_display_name")
|
||||
(
|
||||
device_id,
|
||||
|
|
|
|||
|
|
@ -21,10 +21,15 @@ from twisted.web.server import Request
|
|||
import synapse
|
||||
import synapse.api.auth
|
||||
import synapse.types
|
||||
from synapse.api.constants import APP_SERVICE_REGISTRATION_TYPE, LoginType
|
||||
from synapse.api.constants import (
|
||||
APP_SERVICE_REGISTRATION_TYPE,
|
||||
ApprovalNoticeMedium,
|
||||
LoginType,
|
||||
)
|
||||
from synapse.api.errors import (
|
||||
Codes,
|
||||
InteractiveAuthIncompleteError,
|
||||
NotApprovedError,
|
||||
SynapseError,
|
||||
ThreepidValidationError,
|
||||
UnrecognizedRequestError,
|
||||
|
|
@ -414,6 +419,11 @@ class RegisterRestServlet(RestServlet):
|
|||
hs.config.registration.inhibit_user_in_use_error
|
||||
)
|
||||
|
||||
self._require_approval = (
|
||||
hs.config.experimental.msc3866.enabled
|
||||
and hs.config.experimental.msc3866.require_approval_for_new_accounts
|
||||
)
|
||||
|
||||
self._registration_flows = _calculate_registration_flows(
|
||||
hs.config, self.auth_handler
|
||||
)
|
||||
|
|
@ -734,6 +744,12 @@ class RegisterRestServlet(RestServlet):
|
|||
access_token=return_dict.get("access_token"),
|
||||
)
|
||||
|
||||
if self._require_approval:
|
||||
raise NotApprovedError(
|
||||
msg="This account needs to be approved by an administrator before it can be used.",
|
||||
approval_notice_medium=ApprovalNoticeMedium.NONE,
|
||||
)
|
||||
|
||||
return 200, return_dict
|
||||
|
||||
async def _do_appservice_registration(
|
||||
|
|
@ -778,7 +794,9 @@ class RegisterRestServlet(RestServlet):
|
|||
"user_id": user_id,
|
||||
"home_server": self.hs.hostname,
|
||||
}
|
||||
if not params.get("inhibit_login", False):
|
||||
# We don't want to log the user in if we're going to deny them access because
|
||||
# they need to be approved first.
|
||||
if not params.get("inhibit_login", False) and not self._require_approval:
|
||||
device_id = params.get("device_id")
|
||||
initial_display_name = params.get("initial_device_display_name")
|
||||
(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue