@@ -1056,7 +1056,8 @@ class OidcSessionData:
10561056
10571057
10581058UserAttributeDict = TypedDict (
1059- "UserAttributeDict" , {"localpart" : Optional [str ], "display_name" : Optional [str ]}
1059+ "UserAttributeDict" ,
1060+ {"localpart" : Optional [str ], "display_name" : Optional [str ], "emails" : List [str ]},
10601061)
10611062C = TypeVar ("C" )
10621063
@@ -1135,11 +1136,12 @@ def jinja_finalize(thing):
11351136env = Environment (finalize = jinja_finalize )
11361137
11371138
1138- @attr .s
1139+ @attr .s ( slots = True , frozen = True )
11391140class JinjaOidcMappingConfig :
11401141 subject_claim = attr .ib (type = str )
11411142 localpart_template = attr .ib (type = Optional [Template ])
11421143 display_name_template = attr .ib (type = Optional [Template ])
1144+ email_template = attr .ib (type = Optional [Template ])
11431145 extra_attributes = attr .ib (type = Dict [str , Template ])
11441146
11451147
@@ -1156,23 +1158,17 @@ def __init__(self, config: JinjaOidcMappingConfig):
11561158 def parse_config (config : dict ) -> JinjaOidcMappingConfig :
11571159 subject_claim = config .get ("subject_claim" , "sub" )
11581160
1159- localpart_template = None # type: Optional[Template]
1160- if "localpart_template" in config :
1161+ def parse_template_config (option_name : str ) -> Optional [Template ]:
1162+ if option_name not in config :
1163+ return None
11611164 try :
1162- localpart_template = env .from_string (config ["localpart_template" ])
1165+ return env .from_string (config [option_name ])
11631166 except Exception as e :
1164- raise ConfigError (
1165- "invalid jinja template" , path = ["localpart_template" ]
1166- ) from e
1167+ raise ConfigError ("invalid jinja template" , path = [option_name ]) from e
11671168
1168- display_name_template = None # type: Optional[Template]
1169- if "display_name_template" in config :
1170- try :
1171- display_name_template = env .from_string (config ["display_name_template" ])
1172- except Exception as e :
1173- raise ConfigError (
1174- "invalid jinja template" , path = ["display_name_template" ]
1175- ) from e
1169+ localpart_template = parse_template_config ("localpart_template" )
1170+ display_name_template = parse_template_config ("display_name_template" )
1171+ email_template = parse_template_config ("email_template" )
11761172
11771173 extra_attributes = {} # type Dict[str, Template]
11781174 if "extra_attributes" in config :
@@ -1192,6 +1188,7 @@ def parse_config(config: dict) -> JinjaOidcMappingConfig:
11921188 subject_claim = subject_claim ,
11931189 localpart_template = localpart_template ,
11941190 display_name_template = display_name_template ,
1191+ email_template = email_template ,
11951192 extra_attributes = extra_attributes ,
11961193 )
11971194
@@ -1213,16 +1210,23 @@ async def map_user_attributes(
12131210 # a usable mxid.
12141211 localpart += str (failures ) if failures else ""
12151212
1216- display_name = None # type: Optional[str]
1217- if self ._config .display_name_template is not None :
1218- display_name = self ._config .display_name_template .render (
1219- user = userinfo
1220- ).strip ()
1213+ def render_template_field (template : Optional [Template ]) -> Optional [str ]:
1214+ if template is None :
1215+ return None
1216+ return template .render (user = userinfo ).strip ()
1217+
1218+ display_name = render_template_field (self ._config .display_name_template )
1219+ if display_name == "" :
1220+ display_name = None
12211221
1222- if display_name == "" :
1223- display_name = None
1222+ emails = [] # type: List[str]
1223+ email = render_template_field (self ._config .email_template )
1224+ if email :
1225+ emails .append (email )
12241226
1225- return UserAttributeDict (localpart = localpart , display_name = display_name )
1227+ return UserAttributeDict (
1228+ localpart = localpart , display_name = display_name , emails = emails
1229+ )
12261230
12271231 async def get_extra_attributes (self , userinfo : UserInfo , token : Token ) -> JsonDict :
12281232 extras = {} # type: Dict[str, str]
0 commit comments