@@ -19,6 +19,50 @@ const BeforeUpdateOrCreateUserFromExternalService = [];
1919
2020const IDENTITY_PROPNAME_FILTER = / \. / ;
2121
22+ const getNestedValue = ( propertyPath , source ) =>
23+ propertyPath . split ( '.' ) . reduce ( ( prev , curr ) => ( prev ? prev [ curr ] : undefined ) , source ) ;
24+
25+ // /^(.+)@/::email
26+ const REGEXP_FROM_FORMULA = / ^ \/ ( (? ! \/ : : ) .* ) \/ : : ( .+ ) / ;
27+ const getRegexpMatch = ( formula , data ) => {
28+ const regexAndPath = REGEXP_FROM_FORMULA . exec ( formula ) ;
29+ if ( ! regexAndPath ) {
30+ return getNestedValue ( formula , data ) ;
31+ }
32+ if ( regexAndPath . length !== 3 ) {
33+ throw new Error ( `expected array of length 3, got ${ regexAndPath . length } ` ) ;
34+ }
35+
36+ const [ , regexString , path ] = regexAndPath ;
37+ const nestedValue = getNestedValue ( path , data ) ;
38+ try {
39+ const regex = new RegExp ( regexString ) ;
40+ const matches = regex . exec ( nestedValue ) ;
41+
42+ // regexp does not match nested value
43+ if ( ! matches ) {
44+ return undefined ;
45+ }
46+
47+ // we only support regular expressions with a single capture group
48+ const [ , value ] = matches ;
49+
50+ // this could mean we return `undefined` (e.g. when capture group is empty)
51+ return value ;
52+ } catch ( error ) {
53+ throw new Meteor . Error ( 'CustomOAuth: Failed to extract identity value' , error . message ) ;
54+ }
55+ } ;
56+
57+ const templateStringRegex = / { { ( (?: (? ! } } ) .) + ) } } / g;
58+ const fromTemplate = ( template , data ) => {
59+ if ( ! templateStringRegex . test ( template ) ) {
60+ return getNestedValue ( template , data ) ;
61+ }
62+
63+ return template . replace ( templateStringRegex , ( fullMatch , match ) => getRegexpMatch ( match , data ) ) ;
64+ } ;
65+
2266export class CustomOAuth {
2367 constructor ( name , options ) {
2468 logger . debug ( 'Init CustomOAuth' , name , options ) ;
@@ -331,55 +375,40 @@ export class CustomOAuth {
331375 }
332376
333377 getUsername ( data ) {
334- let username = '' ;
378+ const value = fromTemplate ( this . usernameField , data ) ;
335379
336- username = this . usernameField . split ( '.' ) . reduce ( function ( prev , curr ) {
337- return prev ? prev [ curr ] : undefined ;
338- } , data ) ;
339-
340- if ( ! username ) {
380+ if ( ! value ) {
341381 throw new Meteor . Error ( 'field_not_found' , `Username field "${ this . usernameField } " not found in data` , data ) ;
342382 }
343- return username ;
383+ return value ;
344384 }
345385
346386 getEmail ( data ) {
347- let username = '' ;
348-
349- username = this . emailField . split ( '.' ) . reduce ( function ( prev , curr ) {
350- return prev ? prev [ curr ] : undefined ;
351- } , data ) ;
387+ const value = fromTemplate ( this . emailField , data ) ;
352388
353- if ( ! username ) {
354- throw new Meteor . Error ( 'field_not_found' , `Username field "${ this . emailField } " not found in data` , data ) ;
389+ if ( ! value ) {
390+ throw new Meteor . Error ( 'field_not_found' , `Email field "${ this . emailField } " not found in data` , data ) ;
355391 }
356- return username ;
392+ return value ;
357393 }
358394
359395 getCustomName ( data ) {
360- let customName = '' ;
396+ const value = fromTemplate ( this . nameField , data ) ;
361397
362- customName = this . nameField . split ( '.' ) . reduce ( function ( prev , curr ) {
363- return prev ? prev [ curr ] : undefined ;
364- } , data ) ;
365-
366- if ( ! customName ) {
398+ if ( ! value ) {
367399 return this . getName ( data ) ;
368400 }
369401
370- return customName ;
402+ return value ;
371403 }
372404
373405 getAvatarUrl ( data ) {
374- const avatarUrl = this . avatarField . split ( '.' ) . reduce ( function ( prev , curr ) {
375- return prev ? prev [ curr ] : undefined ;
376- } , data ) ;
406+ const value = fromTemplate ( this . avatarField , data ) ;
377407
378- if ( ! avatarUrl ) {
379- logger . debug ( `Avatar field "${ this . avatarField } " not found in data` , data ) ;
408+ if ( ! value ) {
409+ throw new Meteor . Error ( 'field_not_found' , `Avatar field "${ this . avatarField } " not found in data` , data ) ;
380410 }
381-
382- return avatarUrl ;
411+ return value ;
383412 }
384413
385414 getName ( identity ) {
0 commit comments