77
88namespace OCA \UserOIDC \Service ;
99
10+ use InvalidArgumentException ;
11+ use OC \Accounts \AccountManager ;
1012use OCA \UserOIDC \AppInfo \Application ;
1113use OCA \UserOIDC \Db \UserMapper ;
1214use OCA \UserOIDC \Event \AttributeMappedEvent ;
2325use OCP \ISession ;
2426use OCP \IUser ;
2527use OCP \IUserManager ;
28+ use OCP \L10N \IFactory ;
2629use OCP \User \Events \UserChangedEvent ;
2730use Psr \Log \LoggerInterface ;
2831use Throwable ;
@@ -42,6 +45,7 @@ public function __construct(
4245 private IAvatarManager $ avatarManager ,
4346 private IConfig $ config ,
4447 private ISession $ session ,
48+ private IFactory $ l10nFactory ,
4549 ) {
4650 }
4751
@@ -76,6 +80,9 @@ public function provisionUser(string $tokenUserId, int $providerId, object $idTo
7680 $ quotaAttribute = $ this ->providerService ->getSetting ($ providerId , ProviderService::SETTING_MAPPING_QUOTA , 'quota ' );
7781 $ quota = $ idTokenPayload ->{$ quotaAttribute } ?? null ;
7882
83+ $ languageAttribute = $ this ->providerService ->getSetting ($ providerId , ProviderService::SETTING_MAPPING_LANGUAGE , 'language ' );
84+ $ language = $ idTokenPayload ->{$ languageAttribute } ?? null ;
85+
7986 $ genderAttribute = $ this ->providerService ->getSetting ($ providerId , ProviderService::SETTING_MAPPING_GENDER , 'gender ' );
8087 $ gender = $ idTokenPayload ->{$ genderAttribute } ?? null ;
8188
@@ -151,7 +158,11 @@ public function provisionUser(string $tokenUserId, int $providerId, object $idTo
151158 }
152159
153160 $ account = $ this ->accountManager ->getAccount ($ user );
154- $ scope = 'v2-local ' ;
161+ $ fallbackScope = 'v2-local ' ;
162+ $ defaultScopes = array_merge (
163+ AccountManager::DEFAULT_SCOPES ,
164+ $ this ->config ->getSystemValue ('account_manager.default_property_scope ' , []) ?? []
165+ );
155166
156167 // Update displayname
157168 if (isset ($ userName )) {
@@ -227,7 +238,20 @@ public function provisionUser(string $tokenUserId, int $providerId, object $idTo
227238 $ this ->eventDispatcher ->dispatchTyped ($ event );
228239 $ this ->logger ->debug ('Phone mapping event dispatched ' );
229240 if ($ event ->hasValue ()) {
230- $ account ->setProperty ('phone ' , $ event ->getValue (), $ scope , '1 ' , '' );
241+ $ account ->setProperty ('phone ' , $ event ->getValue (), $ defaultScopes [IAccountManager::PROPERTY_PHONE ] ?? $ fallbackScope , '1 ' , '' );
242+ }
243+
244+ $ event = new AttributeMappedEvent (ProviderService::SETTING_MAPPING_LANGUAGE , $ idTokenPayload , $ language );
245+ $ this ->eventDispatcher ->dispatchTyped ($ event );
246+ $ this ->logger ->debug ('Language mapping event dispatched ' );
247+ if ($ event ->hasValue ()) {
248+ $ language = $ event ->getValue ();
249+ $ languagesCodes = $ this ->l10nFactory ->findAvailableLanguages ();
250+ if (in_array ($ language , $ languagesCodes , true ) || $ language === 'en ' ) {
251+ $ this ->config ->setUserValue ($ user ->getUID (), 'core ' , 'lang ' , $ language );
252+ } else {
253+ $ this ->logger ->debug ('Invalid language in ID token ' , ['language ' => $ language ]);
254+ }
231255 }
232256
233257 $ addressParts = null ;
@@ -266,15 +290,15 @@ public function provisionUser(string $tokenUserId, int $providerId, object $idTo
266290 $ this ->eventDispatcher ->dispatchTyped ($ event );
267291 $ this ->logger ->debug ('Address mapping event dispatched ' );
268292 if ($ event ->hasValue () && $ event ->getValue () !== null && $ event ->getValue () !== '' ) {
269- $ account ->setProperty ('address ' , $ event ->getValue (), $ scope , '1 ' , '' );
293+ $ account ->setProperty ('address ' , $ event ->getValue (), $ defaultScopes [IAccountManager:: PROPERTY_ADDRESS ] ?? $ fallbackScope , '1 ' , '' );
270294 }
271295
272296 // Update the website
273297 $ event = new AttributeMappedEvent (ProviderService::SETTING_MAPPING_WEBSITE , $ idTokenPayload , $ website );
274298 $ this ->eventDispatcher ->dispatchTyped ($ event );
275299 $ this ->logger ->debug ('Website mapping event dispatched ' );
276300 if ($ event ->hasValue () && $ event ->getValue () !== null && $ event ->getValue () !== '' ) {
277- $ account ->setProperty ('website ' , $ event ->getValue (), $ scope , '1 ' , '' );
301+ $ account ->setProperty ('website ' , $ event ->getValue (), $ defaultScopes [IAccountManager:: PROPERTY_WEBSITE ] ?? $ fallbackScope , '1 ' , '' );
278302 }
279303
280304 // Update the avatar
@@ -290,23 +314,23 @@ public function provisionUser(string $tokenUserId, int $providerId, object $idTo
290314 $ this ->eventDispatcher ->dispatchTyped ($ event );
291315 $ this ->logger ->debug ('Twitter mapping event dispatched ' );
292316 if ($ event ->hasValue () && $ event ->getValue () !== null && $ event ->getValue () !== '' ) {
293- $ account ->setProperty ('twitter ' , $ event ->getValue (), $ scope , '1 ' , '' );
317+ $ account ->setProperty ('twitter ' , $ event ->getValue (), $ defaultScopes [IAccountManager:: PROPERTY_TWITTER ] ?? $ fallbackScope , '1 ' , '' );
294318 }
295319
296320 // Update fediverse
297321 $ event = new AttributeMappedEvent (ProviderService::SETTING_MAPPING_FEDIVERSE , $ idTokenPayload , $ fediverse );
298322 $ this ->eventDispatcher ->dispatchTyped ($ event );
299323 $ this ->logger ->debug ('Fediverse mapping event dispatched ' );
300324 if ($ event ->hasValue () && $ event ->getValue () !== null && $ event ->getValue () !== '' ) {
301- $ account ->setProperty ('fediverse ' , $ event ->getValue (), $ scope , '1 ' , '' );
325+ $ account ->setProperty ('fediverse ' , $ event ->getValue (), $ defaultScopes [IAccountManager:: PROPERTY_FEDIVERSE ] ?? $ fallbackScope , '1 ' , '' );
302326 }
303327
304328 // Update the organisation
305329 $ event = new AttributeMappedEvent (ProviderService::SETTING_MAPPING_ORGANISATION , $ idTokenPayload , $ organisation );
306330 $ this ->eventDispatcher ->dispatchTyped ($ event );
307331 $ this ->logger ->debug ('Organisation mapping event dispatched ' );
308332 if ($ event ->hasValue () && $ event ->getValue () !== null && $ event ->getValue () !== '' ) {
309- $ account ->setProperty ('organisation ' , $ event ->getValue (), $ scope , '1 ' , '' );
333+ $ account ->setProperty ('organisation ' , $ event ->getValue (), $ defaultScopes [IAccountManager:: PROPERTY_ORGANISATION ] ?? $ fallbackScope , '1 ' , '' );
310334 }
311335
312336 // Update role
@@ -322,28 +346,46 @@ public function provisionUser(string $tokenUserId, int $providerId, object $idTo
322346 $ this ->eventDispatcher ->dispatchTyped ($ event );
323347 $ this ->logger ->debug ('Headline mapping event dispatched ' );
324348 if ($ event ->hasValue () && $ event ->getValue () !== null && $ event ->getValue () !== '' ) {
325- $ account ->setProperty ('headline ' , $ event ->getValue (), $ scope , '1 ' , '' );
349+ $ account ->setProperty ('headline ' , $ event ->getValue (), $ defaultScopes [IAccountManager:: PROPERTY_HEADLINE ] ?? $ fallbackScope , '1 ' , '' );
326350 }
327351
328352 // Update the biography
329353 $ event = new AttributeMappedEvent (ProviderService::SETTING_MAPPING_BIOGRAPHY , $ idTokenPayload , $ biography );
330354 $ this ->eventDispatcher ->dispatchTyped ($ event );
331355 $ this ->logger ->debug ('Biography mapping event dispatched ' );
332356 if ($ event ->hasValue () && $ event ->getValue () !== null && $ event ->getValue () !== '' ) {
333- $ account ->setProperty ('biography ' , $ event ->getValue (), $ scope , '1 ' , '' );
357+ $ account ->setProperty ('biography ' , $ event ->getValue (), $ defaultScopes [IAccountManager:: PROPERTY_BIOGRAPHY ] ?? $ fallbackScope , '1 ' , '' );
334358 }
335359
336360 // Update the gender
361+ // Since until now there is no default for property for gender we have to use default
362+ // In v31 there will be introduced PRONOUNS, which could be of better use
337363 $ event = new AttributeMappedEvent (ProviderService::SETTING_MAPPING_GENDER , $ idTokenPayload , $ gender );
338364 $ this ->eventDispatcher ->dispatchTyped ($ event );
339365 $ this ->logger ->debug ('Gender mapping event dispatched ' );
340366 if ($ event ->hasValue () && $ event ->getValue () !== null && $ event ->getValue () !== '' ) {
341- $ account ->setProperty ('gender ' , $ event ->getValue (), $ scope , '1 ' , '' );
367+ $ account ->setProperty ('gender ' , $ event ->getValue (), $ fallbackScope , '1 ' , '' );
342368 }
343369
344370 $ this ->session ->set ('user_oidc.oidcUserData ' , $ oidcGssUserData );
345371
346- $ this ->accountManager ->updateAccount ($ account );
372+ while (true ) {
373+ try {
374+ $ this ->accountManager ->updateAccount ($ account );
375+ break ;
376+ } catch (InvalidArgumentException $ e ) {
377+ // If the message is a property name, then this was throws because of an invalid property value
378+ if (in_array ($ e ->getMessage (), IAccountManager::ALLOWED_PROPERTIES )) {
379+ $ property = $ account ->getProperty ($ e ->getMessage ());
380+ // Remove the property from account
381+ $ account ->setProperty ($ property ->getName (), '' , $ property ->getScope (), IAccountManager::NOT_VERIFIED );
382+ $ this ->logger ->info ('Invalid account property provisioned ' , ['account ' => $ user ->getUID (), 'property ' => $ property ->getName ()]);
383+ continue ;
384+ }
385+ // unrelated error - rethrow
386+ throw $ e ;
387+ }
388+ }
347389 return $ user ;
348390 }
349391
0 commit comments