1+ function ( user , context , callback ) {
2+ if ( context . clientID === configuration . CLIENT_ACCOUNTS_LOGIN ) {
3+ console . log ( "rule:onboarding-checklist:enter" ) ;
4+ console . log ( "rule:onboarding-checklist:context.request" , context . request ) ;
5+
6+ if ( context . redirect ) {
7+ console . log ( "rule:onboarding-checklist:exiting due to context being a redirect" ) ;
8+ return callback ( null , user , context ) ;
9+ }
10+
11+ const _ = require ( 'lodash' ) ;
12+ const moment = require ( 'moment' ) ;
13+
14+ let handle = _ . get ( user , "handle" , null ) ;
15+ const provider = _ . get ( user , "identities[0].provider" , null ) ;
16+ if ( ! handle && provider === "auth0" ) {
17+ handle = _ . get ( user , "nickname" , null ) ;
18+ }
19+
20+ console . log ( "rule:onboarding-checklist: fetch onboarding_checklist for email/handle: " , user . email , handle , provider ) ;
21+
22+ const createdAt = _ . get ( user , "created_at" , null ) ;
23+ const thresholdDate = moment ( configuration . PROFILE_CREATION_DATE_THRESHOLD , "YYYY-MM-DD" ) ;
24+
25+ try {
26+ // For users created before thresholdDate, we don't want to check onboarding_checklist
27+ // This is because older profiles might not have onboarding_checklist data and they don't need to see the onboarding_wizard
28+ if ( createdAt && ! thresholdDate . isBefore ( moment ( createdAt ) ) ) {
29+ console . log ( "rule:onboarding-checklist: user created before threshold date. Not checking onboarding_checklist." ) ;
30+ return callback ( null , user , context ) ;
31+ }
32+ } catch ( err ) {
33+ console . log ( "rule:onboarding-checklist: failed to compare userCreationDate" , createdAt , " with threshold. Error" , err ) ;
34+ }
35+
36+ /**
37+ * Returns M2M token needed to fetch onboarding_checklist
38+ */
39+ const getToken = function ( callback ) {
40+ if ( global . M2MToken ) {
41+ console . log ( 'rule:onboarding-checklist:M2M token is available' ) ;
42+ const jwt = require ( 'jsonwebtoken' ) ;
43+ const decoded = jwt . decode ( global . M2MToken ) ;
44+ const exp = moment . unix ( decoded . exp ) ;
45+
46+ if ( exp > new Date ( ) ) {
47+ console . log ( 'rule:onboarding-checklist:M2M token is valid. Reusing...' ) ;
48+ return callback ( null , global . M2MToken ) ;
49+ }
50+ }
51+
52+ console . log ( 'rule:onboarding-checklist:Fetching new M2M token' ) ;
53+ request . post ( {
54+ url : `https://auth0proxy.${ configuration . DOMAIN } /token` ,
55+ headers : 'content-type: application/json' ,
56+ json : {
57+ client_id : configuration . M2M_CLIENT_ID ,
58+ client_secret : configuration . M2M_CLIENT_SECRET ,
59+ audience : configuration . M2M_AUDIENCE ,
60+ auth0_url : configuration . M2M_TOKEN_URL ,
61+ grant_type : 'client_credentials'
62+ }
63+ } , function ( err , response , body ) {
64+ if ( err ) {
65+ return callback ( err ) ;
66+ }
67+
68+ global . M2MToken = body . access_token ;
69+ console . log ( 'rule:onboarding-checklist:setting the M2MToken globally' , global . M2MToken ) ;
70+ return callback ( null , global . M2MToken ) ;
71+ } ) ;
72+ } ;
73+
74+ getToken ( function ( err , token ) {
75+ if ( err ) {
76+ console . log ( 'rule:onboarding-checklist:failed to fetch M2M token.' ) ;
77+ return callback ( null , user , context ) ;
78+ }
79+ global . AUTH0_CLAIM_NAMESPACE = "https://" + configuration . DOMAIN + "/" ;
80+ const axios = require ( 'axios@0.19.2' ) ;
81+
82+ const options = {
83+ method : 'GET' ,
84+ url : `https://api.${ configuration . DOMAIN } /v5/members/${ handle } /traits?traitIds=onboarding_checklist` ,
85+ headers : {
86+ Authorization : `Bearer ${ token } `
87+ }
88+ } ;
89+
90+ // Fetch onboarding_checklist using v5 member Api.
91+ axios ( options )
92+ . then ( result => {
93+ try {
94+ const data = result . data ;
95+
96+ if ( data . length === 0 ) {
97+ // User doesn't have any traits with traitId onboarding_checklist and should be shown the onboarding wizard
98+ context . idToken [ global . AUTH0_CLAIM_NAMESPACE + 'show_onboarding_wizard' ] = true ;
99+ console . log ( 'rule:onboarding-checklist:Setting show_onboarding_wizard to true' , user ) ;
100+ return callback ( null , user , context ) ;
101+ }
102+
103+ const onboardingChecklistTrait = data . filter ( ( item ) => item . traitId === 'onboarding_checklist' ) [ 0 ] . traits ;
104+
105+ for ( let checklistTrait of onboardingChecklistTrait . data ) {
106+ if (
107+ checklistTrait . onboarding_wizard != null &&
108+ ( checklistTrait . onboarding_wizard . status != null || // any valid status indicates user has already seen onboarding wizard and needn't be shown again.
109+ checklistTrait . onboarding_wizard . skip ) // for certain signup routes skip is set to true, and thus onboarding wizard needn't be shown
110+ ) {
111+ return callback ( null , user , context ) ;
112+ }
113+ }
114+
115+ const profileCompletedData = onboardingChecklistTrait . data [ 0 ] . profile_completed ;
116+
117+ if ( profileCompletedData ) {
118+ if ( profileCompletedData . status === "completed" ) {
119+ return callback ( null , user , context ) ;
120+ }
121+
122+ for ( const item in profileCompletedData . metadata ) {
123+ if ( profileCompletedData . metadata [ item ] ) {
124+ return callback ( null , user , context ) ;
125+ }
126+ }
127+ }
128+
129+ // All checks failed - indicating user newly registered and needs to be shown the onboarding wizard
130+ console . log ( 'rule:onboarding-checklist: set show_onboarding_wizard' , user ) ;
131+ context . idToken [ global . AUTH0_CLAIM_NAMESPACE + 'show_onboarding_wizard' ] = true ;
132+ return callback ( null , user , context ) ;
133+ } catch ( e ) {
134+ console . log ( "rule:onboarding-checklist:Error in fetching onboarding_checklist" , e ) ;
135+ return callback ( null , user , context ) ;
136+ }
137+ } ) . catch ( requestError => {
138+ console . log ( "rule:onboarding-checklist:Failed fetching onboarding_checklist with error" , requestError . response . status ) ;
139+ return callback ( null , user , context ) ;
140+ } ) ;
141+ } ) ;
142+ } else {
143+ return callback ( null , user , context ) ;
144+ }
145+ }
0 commit comments