mirror of
https://github.com/element-hq/synapse.git
synced 2024-12-18 08:54:54 +03:00
feat: make the SCIM IPD id configurable
This commit is contained in:
parent
c48e7310a4
commit
36a600c4fb
3 changed files with 50 additions and 17 deletions
|
@ -256,6 +256,19 @@ class MSC3866Config:
|
|||
require_approval_for_new_accounts: bool = False
|
||||
|
||||
|
||||
@attr.s(auto_attribs=True, frozen=True, slots=True)
|
||||
class MSC4098Config:
|
||||
"""Configuration for MSC4098 (SCIM provisioning)"""
|
||||
|
||||
# Whether the SCIM provisioning API is enabled.
|
||||
enabled: bool = False
|
||||
|
||||
# The ID of the IDP that will be associated with the SCIM 'externalId' parameter.
|
||||
# This should be one of the values used in the SSO config.
|
||||
# If unset, a default '__scim__' id will be used.
|
||||
idp_id: Optional[str] = None
|
||||
|
||||
|
||||
class ExperimentalConfig(Config):
|
||||
"""Config section for enabling experimental features"""
|
||||
|
||||
|
@ -416,13 +429,18 @@ class ExperimentalConfig(Config):
|
|||
)
|
||||
|
||||
# MSC4098: SCIM provisioning API
|
||||
self.msc4098_enabled = experimental.get("msc4098", False)
|
||||
if self.msc4098_enabled and self.msc3861.enabled:
|
||||
try:
|
||||
self.msc4098 = MSC4098Config(**experimental.get("msc4098", {}))
|
||||
if self.msc4098.enabled and self.msc3861.enabled:
|
||||
raise ConfigError(
|
||||
"MSC3861 and MSC4098 are mutually exclusive. Please disable one or the"
|
||||
"other.",
|
||||
("experimental", "msc4098"),
|
||||
)
|
||||
except ValueError as exc:
|
||||
raise ConfigError(
|
||||
"MSC3861 and MSC4098 are mutually exclusive. Please disable one or the"
|
||||
"other.",
|
||||
("experimental", "msc4098"),
|
||||
)
|
||||
"Invalid MSC4098 configuration", ("experimental", "msc4098")
|
||||
) from exc
|
||||
|
||||
# MSC4108: Mechanism to allow OIDC sign in and E2EE set up via QR code
|
||||
self.msc4108_enabled = experimental.get("msc4108_enabled", False)
|
||||
|
|
|
@ -84,7 +84,7 @@ if TYPE_CHECKING:
|
|||
from synapse.server import HomeServer
|
||||
|
||||
SCIM_PREFIX = "/_synapse/admin/scim/v2"
|
||||
SCIM_IDP_ID = "__scim__"
|
||||
SCIM_DEFAULT_IDP_ID = "__scim__"
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
@ -99,7 +99,7 @@ class SCIMResource(JsonResource):
|
|||
|
||||
|
||||
def register_servlets(hs: "HomeServer", http_server: HttpServer) -> None:
|
||||
if not hs.config.experimental.msc4098_enabled:
|
||||
if not hs.config.experimental.msc4098.enabled:
|
||||
return
|
||||
|
||||
SchemaListServlet(hs).register(http_server)
|
||||
|
@ -156,9 +156,10 @@ class SCIMServlet(RestServlet):
|
|||
async def get_scim_external_id(self, user_id: str) -> Optional[str]:
|
||||
"""Read the external id stored in the special SCIM IDP."""
|
||||
|
||||
scim_idp_id = self.hs.config.experimental.msc4098.idp_id or SCIM_DEFAULT_IDP_ID
|
||||
external_ids = await self.store.get_external_ids_by_user(user_id)
|
||||
for idp_id, external_id in external_ids:
|
||||
if idp_id == SCIM_IDP_ID:
|
||||
if idp_id == scim_idp_id:
|
||||
return external_id
|
||||
|
||||
return None
|
||||
|
@ -303,13 +304,16 @@ class UserServlet(SCIMServlet):
|
|||
|
||||
external_id = await self.get_scim_external_id(user_id)
|
||||
if request_user.external_id != external_id:
|
||||
scim_idp_id = (
|
||||
self.hs.config.experimental.msc4098.idp_id or SCIM_DEFAULT_IDP_ID
|
||||
)
|
||||
if external_id:
|
||||
await self.store.remove_user_external_id(
|
||||
SCIM_IDP_ID, external_id, user_id
|
||||
scim_idp_id, external_id, user_id
|
||||
)
|
||||
if request_user.external_id:
|
||||
await self.store.record_user_external_id(
|
||||
SCIM_IDP_ID, request_user.external_id, user_id
|
||||
scim_idp_id, request_user.external_id, user_id
|
||||
)
|
||||
|
||||
if request_user.photos and request_user.photos[0].value:
|
||||
|
@ -451,8 +455,11 @@ class UserListServlet(SCIMServlet):
|
|||
)
|
||||
|
||||
if request_user.external_id:
|
||||
scim_idp_id = (
|
||||
self.hs.config.experimental.msc4098.idp_id or SCIM_DEFAULT_IDP_ID
|
||||
)
|
||||
await self.store.record_user_external_id(
|
||||
SCIM_IDP_ID, request_user.external_id, user_id
|
||||
scim_idp_id, request_user.external_id, user_id
|
||||
)
|
||||
|
||||
now_ts = self.hs.get_clock().time_msec()
|
||||
|
|
|
@ -8,7 +8,7 @@ import synapse.rest.scim
|
|||
from synapse.config import ConfigError
|
||||
from synapse.config.homeserver import HomeServerConfig
|
||||
from synapse.rest.client import login
|
||||
from synapse.rest.scim import HAS_SCIM2, SCIM_IDP_ID
|
||||
from synapse.rest.scim import HAS_SCIM2, SCIM_DEFAULT_IDP_ID
|
||||
from synapse.server import HomeServer
|
||||
from synapse.types import JsonDict, UserID
|
||||
from synapse.util import Clock
|
||||
|
@ -58,7 +58,9 @@ class SCIMExperimentalFeatureTestCase(HomeserverTestCase):
|
|||
|
||||
config_dict = {
|
||||
"experimental_features": {
|
||||
"msc4098": True,
|
||||
"msc4098": {
|
||||
"enabled": True,
|
||||
},
|
||||
"msc3861": {"enabled": True},
|
||||
},
|
||||
**default_config("test"),
|
||||
|
@ -90,7 +92,10 @@ class UserProvisioningTestCase(HomeserverTestCase):
|
|||
|
||||
def default_config(self) -> JsonDict:
|
||||
conf = super().default_config()
|
||||
conf.setdefault("experimental_features", {}).setdefault("msc4098", True)
|
||||
msc4098_conf = conf.setdefault("experimental_features", {}).setdefault(
|
||||
"msc4098", {}
|
||||
)
|
||||
msc4098_conf.setdefault("enabled", True)
|
||||
return conf
|
||||
|
||||
def prepare(self, reactor: MemoryReactor, clock: Clock, hs: HomeServer) -> None:
|
||||
|
@ -125,7 +130,7 @@ class UserProvisioningTestCase(HomeserverTestCase):
|
|||
)
|
||||
self.get_success(
|
||||
self.store.record_user_external_id(
|
||||
SCIM_IDP_ID, "IDP-user", self.user_user_id
|
||||
SCIM_DEFAULT_IDP_ID, "IDP-user", self.user_user_id
|
||||
)
|
||||
)
|
||||
|
||||
|
@ -578,7 +583,10 @@ class SCIMMetadataTestCase(HomeserverTestCase):
|
|||
|
||||
def default_config(self) -> JsonDict:
|
||||
conf = super().default_config()
|
||||
conf.setdefault("experimental_features", {}).setdefault("msc4098", True)
|
||||
msc4098_conf = conf.setdefault("experimental_features", {}).setdefault(
|
||||
"msc4098", {}
|
||||
)
|
||||
msc4098_conf.setdefault("enabled", True)
|
||||
return conf
|
||||
|
||||
def prepare(self, reactor: MemoryReactor, clock: Clock, hs: HomeServer) -> None:
|
||||
|
|
Loading…
Reference in a new issue