diff --git a/.circleci/config.yml b/.circleci/config.yml index 5bc8c0c..2caa1a3 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -70,7 +70,7 @@ workflows: branches: only: - dev - - jira-plat-742 + - feature/primary-role # Production builds are exectuted only on tagged commits to the # master branch. diff --git a/web-assets/auth0/dev-tenant/database/create.js b/web-assets/auth0/dev-tenant/database/create.js index a1c11f6..780698d 100644 --- a/web-assets/auth0/dev-tenant/database/create.js +++ b/web-assets/auth0/dev-tenant/database/create.js @@ -21,133 +21,66 @@ // callback(new ValidationError("user_exists", "my error message")); // 3. Something went wrong while trying to reach your database // callback(new Error("my error message")); - const msg = 'Please implement the Create script for this database connection ' + 'at https://manage.auth0.com/#/connections/database'; return callback(new Error(msg)); */ -function create(user, callback) { - //console.log("landed here..................................."); - var countryObj = JSON.parse(user.user_metadata.country); - var regSource = user.user_metadata.reg_source; - var utmSource = user.user_metadata.utm_source; - var utmMedium = user.user_metadata.utm_medium; - var utmCampaign = user.user_metadata.utm_campaign; - var retUrl = user.user_metadata.returnUrl; - var afterActivationURL = - retUrl !== null ? retUrl : "https://" + configuration.DOMAIN + "/home"; - if (regSource === configuration.REG_BUSINESS) { - afterActivationURL = "https://connect." + configuration.DOMAIN; - } - var data = { - param: { - handle: user.username, - email: user.email, - credential: { - password: user.password, - }, - firstName: user.user_metadata.firstName, - lastName: user.user_metadata.lastName, - country: { - code: countryObj.code, - isoAlpha3Code: countryObj.alpha3, - isoAlpha2Code: countryObj.alpha2, - }, - regSource: regSource, - utmSource: utmSource, - utmMedium: utmMedium, - utmCampaign: utmCampaign, - }, - options: { - afterActivationURL: encodeURIComponent(afterActivationURL), - }, - }; - //console.log("SignUp....", user, data); - request.post( - { - url: "https://api." + configuration.DOMAIN + "/v3/users", - json: data, - //for more options check: - //https://github.com/mikeal/request#requestoptions-callback - }, - function (err, response, body) { - // console.log(err); - // console.log(response.statusCode); - // console.log(body.result.content); - - if (err) return callback(err); - console.log(body.result.content); - if (response.statusCode !== 200) { - //return callback(new ValidationError("lock.fallback",body.result.content)); - const error_message = body.result.content; - let code = "lock.fallback"; + function create(user, callback) { - if (error_message.search("Handle may not contain a space") !== -1) { - code = "handle_invalid_space"; - } else if ( - error_message.search( - "Length of Handle in character should be between 2 and 15" - ) !== -1 - ) { - code = "handle_invalid_length"; - } else if ( - error_message.search( - "Please choose another handle, not starting with admin" - ) !== -1 - ) { - code = "handle_invalid_startwith_admin"; - } else if ( - error_message.search( - "Handle may contain only letters, numbers and" - ) !== -1 - ) { - code = "handle_invalid_constains_forbidden_char"; - } else if ( - error_message.search("Handle may not contain only punctuation") !== -1 - ) { - code = "handle_invalid_conatins_only_punctuation"; - } else if (error_message.search("The user already exists") !== -1) { - code = "user_exists"; - } else if (error_message.search("has already been taken") !== -1) { - code = "user_exists"; + var countryObj = JSON.parse(user.user_metadata.country); + var regSource = user.user_metadata.regSource; + var utmSource = user.user_metadata.utmSource; + var utmMedium = user.user_metadata.utmMedium; + var utmCampaign = user.user_metadata.utmCampaign; + var retUrl = user.user_metadata.returnUrl; + var afterActivationURL = retUrl ? retUrl : "https://www."+configuration.DOMAIN+"/start"; + if (regSource === configuration.REG_BUSINESS) { + afterActivationURL = "https://connect."+configuration.DOMAIN; + } + var data = { + "param": { + "handle": user.username, + "email": user.email, + "credential": { + "password": user.password + }, + "firstName": user.user_metadata.firstName, + "lastName": user.user_metadata.lastName, + "country": { + "code": countryObj.code, + "isoAlpha3Code": countryObj.alpha3, + "isoAlpha2Code": countryObj.alpha2 + }, + "primaryRole": user.user_metadata.primaryRole, + "regSource": regSource, + "utmSource": utmSource, + "utmMedium": utmMedium, + "utmCampaign": utmCampaign, + }, + "options": { + "afterActivationURL": encodeURIComponent(afterActivationURL) } + }; + console.log("SignUp....", user, data); + request.post({ + url: "http://api."+configuration.DOMAIN+"/v3/users", + json: data + //for more options check: + //https://github.com/mikeal/request#requestoptions-callback + }, function (err, response, body) { - return callback(new ValidationError(code, error_message)); + console.log(err); + console.log(response.statusCode); + console.log(body); - //return callback(new Error(body.result.content)); - } - //if (response.statusCode === 401) return callback(); - /* const Analytics = require('analytics-node'); - const _ = require('lodash'); - var analytics = new Analytics('bkPtWMUMTYDhww2zsJluzxtdhtmSsyd9'); - analytics.identify({ - anonymousId: 'signup', - traits: { - user: _.omit(user, ['credential', 'password']) - } - }); - analytics.track({ - anonymousId: 'BXWXUWnilVUPdN01t2Se29Tw2ZYNGZvH', - event: 'signUp', - properties: _.omit(user, ['credential', 'password']) - });*/ - /* const ua = require('universal-analytics'); - let visitor = ua('UA-6340959-1'); - visitor.pageview("/signup").send(); - var eParams = { - ec: "utmCode", - ea: "tracking", - el: "tracking", - cn: utmCampaign, - cm: utmMedium, - cs: utmSource, - dp: "/signup" - }; + if (err) return callback(err); - visitor.event(eParams).send(); */ - callback(null); - } - ); //end post request - //callback(null); + if (response.statusCode !== 200) { + return callback(new ValidationError('user_exists', body.result.content)); + } + //if (response.statusCode === 401) return callback(); + callback(null); + }); //end post request + //callback(null); } -//} +//} \ No newline at end of file diff --git a/web-assets/auth0/dev-tenant/rules/onboardingChecklist.js b/web-assets/auth0/dev-tenant/rules/onboardingChecklist.js index f630b35..ec79cdc 100644 --- a/web-assets/auth0/dev-tenant/rules/onboardingChecklist.js +++ b/web-assets/auth0/dev-tenant/rules/onboardingChecklist.js @@ -1,8 +1,8 @@ -function (user, context, callback) { +function OnboardingChecklist(user, context, callback) { if (context.clientID === configuration.CLIENT_ACCOUNTS_LOGIN) { console.log("rule:onboarding-checklist:enter"); - - if (context.redirect) { + + if (context.redirect) { console.log("rule:onboarding-checklist:exiting due to context being a redirect"); return callback(null, user, context); } @@ -24,10 +24,17 @@ function (user, context, callback) { const handle = context.idToken[global.AUTH0_CLAIM_NAMESPACE + 'handle']; console.log("rule:onboarding-checklist: fetch onboarding_checklist for email/handle: ", user.email, handle); - if (handle == null) { + if (handle === null) { console.log("rule:onboarding-checklist: exiting due to handle being null."); return callback(null, user, context); } + + const roles = context.idToken[global.AUTH0_CLAIM_NAMESPACE + 'roles']; + + if (roles && roles.includes('Topcoder Customer')) { + console.log("rule:onboarding-checklist:exiting due to user being a customer."); + return callback(null, user, context); + } const createdAt = _.get(user, "created_at", null); const thresholdDate = moment(configuration.PROFILE_CREATION_DATE_THRESHOLD, "YYYY-MM-DD"); @@ -42,14 +49,14 @@ function (user, context, callback) { } catch (err) { console.log("rule:onboarding-checklist: failed to compare userCreationDate", createdAt, " with threshold. Error", err); } - + /** * Returns M2M token needed to fetch onboarding_checklist */ - const getToken = function(callback) { + const getToken = function (callback) { if (global.M2MToken) { console.log('rule:onboarding-checklist:M2M token is available'); - const jwt = require('jsonwebtoken'); + const jwt = require('jsonwebtoken'); const decoded = jwt.decode(global.M2MToken); const exp = moment.unix(decoded.exp); @@ -72,7 +79,7 @@ function (user, context, callback) { } }, function (err, response, body) { if (err) { - return callback(err); + return callback(err); } global.M2MToken = body.access_token; @@ -81,14 +88,14 @@ function (user, context, callback) { }); }; - getToken(function(err, token) { + getToken(function (err, token) { if (err) { console.log('rule:onboarding-checklist:failed to fetch M2M token.'); return callback(null, user, context); } global.AUTH0_CLAIM_NAMESPACE = "https://" + configuration.DOMAIN + "/"; const axios = require('axios@0.19.2'); - + const options = { method: 'GET', url: `https://api.${configuration.DOMAIN}/v5/members/${handle}/traits?traitIds=onboarding_checklist`, @@ -96,68 +103,67 @@ function (user, context, callback) { Authorization: `Bearer ${token}` } }; - + // Fetch onboarding_checklist using v5 member Api. axios(options) - .then(result => { - try { - const data = result.data; - - if (data.length === 0) { - // User doesn't have any traits with traitId onboarding_checklist and should be shown the onboarding wizard - context.idToken[global.AUTH0_CLAIM_NAMESPACE + 'onboarding_wizard'] = 'show'; - console.log('rule:onboarding-checklist:Setting onboarding_wizard to show'); - return callback(null, user, context); - } + .then(result => { + try { + const data = result.data; + + if (data.length === 0) { + // User doesn't have any traits with traitId onboarding_checklist and should be shown the onboarding wizard + context.idToken[global.AUTH0_CLAIM_NAMESPACE + 'onboarding_wizard'] = 'show'; + console.log('rule:onboarding-checklist:Setting onboarding_wizard to show'); + return callback(null, user, context); + } - const onboardingChecklistTrait = data.filter((item) => item.traitId === 'onboarding_checklist')[0].traits; - let override = 'show'; - - for (let checklistTrait of onboardingChecklistTrait.data) { - if (checklistTrait.onboarding_wizard != null) { - if ( checklistTrait.onboarding_wizard.status !== 'pending_at_user' || // any non pending_at_user status indicates OB was either seen or completed and can be skipped - checklistTrait.onboarding_wizard.skip ||// for certain signup routes skip is set to true, and thus onboarding wizard needn't be shown - checklistTrait.onboarding_wizard.override === 'skip') - { - return callback(null, user, context); - } else if (checklistTrait.onboarding_wizard.override === 'useRetUrl') { - override = 'useRetUrl'; + const onboardingChecklistTrait = data.filter((item) => item.traitId === 'onboarding_checklist')[0].traits; + let override = 'show'; + + for (let checklistTrait of onboardingChecklistTrait.data) { + if (checklistTrait.onboarding_wizard !== null) { + if (checklistTrait.onboarding_wizard.status !== 'pending_at_user' || // any non pending_at_user status indicates OB was either seen or completed and can be skipped + checklistTrait.onboarding_wizard.skip ||// for certain signup routes skip is set to true, and thus onboarding wizard needn't be shown + checklistTrait.onboarding_wizard.override === 'skip') { + return callback(null, user, context); + } else if (checklistTrait.onboarding_wizard.override === 'useRetUrl') { + override = 'useRetUrl'; + } } } - } - const profileCompletedData = onboardingChecklistTrait.data.length > 0 ? onboardingChecklistTrait.data[0].profile_completed : null; - - if (profileCompletedData) { - if (profileCompletedData.status === "completed") { - return callback(null, user, context); - } - - for (const item in profileCompletedData.metadata) { - if (profileCompletedData.metadata[item]) { + const profileCompletedData = onboardingChecklistTrait.data.length > 0 ? onboardingChecklistTrait.data[0].profile_completed : null; + + if (profileCompletedData) { + if (profileCompletedData.status === "completed") { return callback(null, user, context); } + + for (const item in profileCompletedData.metadata) { + if (profileCompletedData.metadata[item]) { + return callback(null, user, context); + } + } } - } - - // All checks failed - indicating user newly registered and needs to be shown the onboarding wizard - console.log('rule:onboarding-checklist: set onboarding_wizard ' + override); - - context.idToken[global.AUTH0_CLAIM_NAMESPACE + 'onboarding_wizard'] = override; + // All checks failed - indicating user newly registered and needs to be shown the onboarding wizard + console.log('rule:onboarding-checklist: set onboarding_wizard ' + override); + context.idToken[global.AUTH0_CLAIM_NAMESPACE + 'onboarding_wizard'] = override; + + + return callback(null, user, context); + } catch (e) { + console.log("rule:onboarding-checklist:Error in fetching onboarding_checklist", e); + return callback(null, user, context); + } + }).catch(requestError => { + console.log("rule:onboarding-checklist:Failed fetching onboarding_checklist with error", requestError.response.status); return callback(null, user, context); - } catch (e) { - console.log("rule:onboarding-checklist:Error in fetching onboarding_checklist", e); - return callback(null, user, context); - } - }).catch(requestError => { - console.log("rule:onboarding-checklist:Failed fetching onboarding_checklist with error", requestError.response.status); - return callback(null, user, context); - }); + }); }); } else { return callback(null, user, context); } -} +} \ No newline at end of file diff --git a/web-assets/auth0/dev-tenant/universal-login.html b/web-assets/auth0/dev-tenant/universal-login.html index ee309a9..d3dc723 100644 --- a/web-assets/auth0/dev-tenant/universal-login.html +++ b/web-assets/auth0/dev-tenant/universal-login.html @@ -89,6 +89,13 @@ var languageDictionary; var language; var optionsObj = Array(); + var primaryRoleOptionsObj = [{ + label: 'Talent - join as a community member', + value: 'Topcoder Talent' + }, { + label: 'Customer - join to get work done', + value: 'Topcoder Customer' + }]; var regSource = config.extraParams.reg_source || null; var utmSource = config.extraParams.utm_source || null; var utmMedium = config.extraParams.utm_medium || null; @@ -110,7 +117,8 @@ title: "Topcoder Login", error: { login: { - 'lock.fallback': "We're sorry, something went wrong when attempting to log in." + 'lock.fallback': "We're sorry, something went wrong when attempting to log in.", + 'deactivated_account': "Account is deactivated" }, signUp: { "lock.fallback": "We're sorry, something went wrong when attempting to sign up.", @@ -291,6 +299,14 @@ hint: "Must have 2 or more chars, blank spaces not allowed" // optional }; } + }, + { + type: "select", + name: "primaryRole", + placeholder: "Select your role", + options: primaryRoleOptionsObj, + fieldLabel: 'The role you select maybe changed in your Profile Settings.', + fieldPlaceholder: 'Talent join to learn, complete, connect and find freelance gig work. Customers join to launch challenges, find freelancers, and get work done.' }, { type: "select", diff --git a/web-assets/auth0/prod-tenant/database/create.js b/web-assets/auth0/prod-tenant/database/create.js index 564b022..68ac07d 100644 --- a/web-assets/auth0/prod-tenant/database/create.js +++ b/web-assets/auth0/prod-tenant/database/create.js @@ -50,6 +50,7 @@ "isoAlpha3Code": countryObj.alpha3, "isoAlpha2Code": countryObj.alpha2 }, + "primaryRole": user.user_metadata.primaryRole, "regSource": regSource, "utmSource": utmSource, "utmMedium": utmMedium, @@ -59,6 +60,7 @@ "afterActivationURL": encodeURIComponent(afterActivationURL) } }; +// console.log("SignUp....", user, data); request.post({ url: "https://api."+configuration.DOMAIN+"/v3/users", json: data @@ -66,9 +68,9 @@ //https://github.com/mikeal/request#requestoptions-callback }, function (err, response, body) { - console.log(err); - console.log(response.statusCode); - console.log(body); + // console.log(err); + // console.log(response.statusCode); + // console.log(body); if (err) return callback(err); @@ -99,4 +101,4 @@ callback(null); }); //end post request //callback(null); -} +} \ No newline at end of file diff --git a/web-assets/auth0/prod-tenant/rules/onboardingChecklist.js b/web-assets/auth0/prod-tenant/rules/onboardingChecklist.js index f57dc16..b035cd4 100644 --- a/web-assets/auth0/prod-tenant/rules/onboardingChecklist.js +++ b/web-assets/auth0/prod-tenant/rules/onboardingChecklist.js @@ -1,9 +1,9 @@ function (user, context, callback) { if (context.clientID === configuration.CLIENT_ACCOUNTS_LOGIN) { - console.log("rule:onboarding-checklist:enter"); + //console.log("rule:onboarding-checklist:enter"); if (context.redirect) { - console.log("rule:onboarding-checklist:exiting due to context being a redirect"); + //console.log("rule:onboarding-checklist:exiting due to context being a redirect"); return callback(null, user, context); } @@ -13,19 +13,26 @@ function (user, context, callback) { const isSocial = _.get(user, "identities[0].isSocial"); const connection = _.get(user, "identities[0].connection"); - console.log("rule:onboarding-checklist: isSocial/connection", isSocial + "/" + connection); - console.log("rule:onboarding-checklist: WIPRO_SS_AZURE_AD_CONNECTION_NAME", configuration.WIPRO_SSO_AZURE_AD_CONNECTION_NAME); + //console.log("rule:onboarding-checklist: isSocial/connection", isSocial + "/" + connection); + //console.log("rule:onboarding-checklist: WIPRO_SS_AZURE_AD_CONNECTION_NAME", configuration.WIPRO_SSO_AZURE_AD_CONNECTION_NAME); if (_.includes([configuration.WIPRO_SSO_AZURE_AD_CONNECTION_NAME], connection)) { - console.log("rule:onboarding-checklist:exiting due to user being an enterprise user."); + //console.log("rule:onboarding-checklist:exiting due to user being an enterprise user."); return callback(null, user, context); } const handle = context.idToken[global.AUTH0_CLAIM_NAMESPACE + 'handle']; - console.log("rule:onboarding-checklist: fetch onboarding_checklist for email/handle: ", user.email, handle); + //console.log("rule:onboarding-checklist: fetch onboarding_checklist for email/handle: ", user.email, handle); - if (handle == null) { - console.log("rule:onboarding-checklist: exiting due to handle being null."); + if (handle === null) { + //console.log("rule:onboarding-checklist: exiting due to handle being null."); + return callback(null, user, context); + } + + const roles = context.idToken[global.AUTH0_CLAIM_NAMESPACE + 'roles']; + + if (roles && roles.includes('Topcoder Customer')) { + console.log("rule:onboarding-checklist:exiting due to user being a customer."); return callback(null, user, context); } @@ -36,7 +43,7 @@ function (user, context, callback) { // For users created before thresholdDate, we don't want to check onboarding_checklist // This is because older profiles might not have onboarding_checklist data and they don't need to see the onboarding_wizard if (createdAt && !thresholdDate.isBefore(moment(createdAt))) { - console.log("rule:onboarding-checklist: user created before threshold date. Not checking onboarding_checklist."); + //console.log("rule:onboarding-checklist: user created before threshold date. Not checking onboarding_checklist."); return callback(null, user, context); } } catch (err) { @@ -48,18 +55,18 @@ function (user, context, callback) { */ const getToken = function(callback) { if (global.M2MToken) { - console.log('rule:onboarding-checklist:M2M token is available'); + //console.log('rule:onboarding-checklist:M2M token is available'); const jwt = require('jsonwebtoken'); const decoded = jwt.decode(global.M2MToken); const exp = moment.unix(decoded.exp); if (exp > new Date()) { - console.log('rule:onboarding-checklist:M2M token is valid. Reusing...'); + //console.log('rule:onboarding-checklist:M2M token is valid. Reusing...'); return callback(null, global.M2MToken); } } - console.log('rule:onboarding-checklist:Fetching new M2M token'); + //console.log('rule:onboarding-checklist:Fetching new M2M token'); request.post({ url: `https://auth0proxy.${configuration.DOMAIN}/token`, headers: 'content-type: application/json', @@ -76,14 +83,14 @@ function (user, context, callback) { } global.M2MToken = body.access_token; - console.log('rule:onboarding-checklist:setting the M2MToken globally', global.M2MToken); + //console.log('rule:onboarding-checklist:setting the M2MToken globally', global.M2MToken); return callback(null, global.M2MToken); }); }; getToken(function(err, token) { if (err) { - console.log('rule:onboarding-checklist:failed to fetch M2M token.'); + //console.log('rule:onboarding-checklist:failed to fetch M2M token.'); return callback(null, user, context); } global.AUTH0_CLAIM_NAMESPACE = "https://" + configuration.DOMAIN + "/"; @@ -114,7 +121,7 @@ function (user, context, callback) { let override = 'show'; for (let checklistTrait of onboardingChecklistTrait.data) { - if (checklistTrait.onboarding_wizard != null) { + if (checklistTrait.onboarding_wizard !== null) { if ( checklistTrait.onboarding_wizard.status !== 'pending_at_user' || // any non pending_at_user status indicates OB was either seen or completed and can be skipped checklistTrait.onboarding_wizard.skip ||// for certain signup routes skip is set to true, and thus onboarding wizard needn't be shown checklistTrait.onboarding_wizard.override === 'skip') diff --git a/web-assets/auth0/prod-tenant/universal-login.html b/web-assets/auth0/prod-tenant/universal-login.html index 2455de0..479e26d 100644 --- a/web-assets/auth0/prod-tenant/universal-login.html +++ b/web-assets/auth0/prod-tenant/universal-login.html @@ -82,6 +82,13 @@ var languageDictionary; var language; var optionsObj = Array(); + var primaryRoleOptionsObj = [{ + label: 'Talent - join as a community member', + value: 'Topcoder Talent' + }, { + label: 'Customer - join to get work done', + value: 'Topcoder Customer' + }]; var regSource = config.extraParams.reg_source || null; var utmSource = config.extraParams.utm_source || null; var utmMedium = config.extraParams.utm_medium || null; @@ -104,7 +111,8 @@ title: "Topcoder Login", error: { login: { - 'lock.fallback': "We're sorry, something went wrong when attempting to log in." + 'lock.fallback': "We're sorry, something went wrong when attempting to log in.", + 'deactivated_account': "Account is deactivated" }, signUp: { "lock.fallback": "We're sorry, something went wrong when attempting to sign up.", @@ -188,7 +196,7 @@ socialButtonStyle: 'small' }, tc_standard: { - allowedConnections: ['TC-User-Database', 'github', 'google-oauth2', 'wipro-adfs', 'wipro-azuread', 'Verified-User-Database'], + allowedConnections: ['TC-User-Database', 'github', 'google-oauth2', 'wipro-adfs', 'wipro-azuread', 'Verified-User-Database','TopcoderProductionGoogleWorkspace'], theme: { logo: 'https://i.imgur.com/IY6TVjY.png', primaryColor: '#137d60' @@ -332,6 +340,14 @@ }; } }, + { + type: "select", + name: "primaryRole", + placeholder: "Select your role", + options: primaryRoleOptionsObj, + fieldLabel: 'The role you select maybe changed in your Profile Settings.', + fieldPlaceholder: 'Talent join to learn, complete, connect and find freelance gig work. Customers join to launch challenges, find freelancers, and get work done.' + }, { type: "select", name: "country",