'use strict'; var serviceId = 'auth'; angular.module('app').factory(serviceId, ['$rootScope', 'common', 'commonConfig', 'config', '$http', '$q', '$window', '$location', '$injector', 'datacontext', 'userAuth', 'myUsersDataContext', auth]); function auth($rootScope, common, commonConfig, config, $http, $q, $window, $location, $injector, datacontext, userAuth, myUsersDataContext) { var getLogFn = common.logger.getLogFn; var logError = getLogFn(serviceId, "error"); var logInfo = getLogFn(serviceId); var verifying = false; if (config.appCode == 'MSA' || config.appCode == 'OB') { var paymentsDataContext = $injector.get('paymentsDataContext'); var rolesAdminDataContext = $injector.get('rolesAdminDataContext'); } const accessTokenRequest = { scopes: ["https://" + b2cName + ".onmicrosoft.com/MKMAPI/User.Access"] } var service = { registerB2cAuthentication: registerB2cAuthentication, acquireTokenSilent: acquireTokenSilent, authenticate: authenticate, register: register, registerPersonal: registerPersonal, registerOpenBadges: registerOpenBadges, registerCuppa: registerCuppa, getAccessToken: getAccessToken, setAccessToken: setAccessToken, logOut: logOut, fillAuthData: fillAuthData, getCurrentUser: getCurrentUser, acceptAgreement: acceptAgreement, getAgreements: getAgreements, acceptAllAgreements: acceptAllAgreements }; return service; function registerB2cAuthentication() { $rootScope.msalInitiated = false; config.msal.enableAccountStorageEvents(); config.msal.addEventCallback(function (message) { console.log(message) if (message.eventType === "msal:accountAdded") { $window.location.href = '#!/'; $window.location.reload(); } }); config.msal.handleRedirectPromise() .then(function (loginResponse) { if (loginResponse) { config.authenticated = true; config.msal.setActiveAccount(loginResponse.account); acquireTokenSilent().then(function () { $window.location.href = config.siteUrl; $rootScope.msalInitiated = true; }); } else { $rootScope.msalInitiated = true; } }) .catch(function (error) { $rootScope.signInError = error.errorMessage; $rootScope.msalInitiated = true; }); } function acquireTokenSilent() { console.log('Aquiring access token'); accessTokenRequest.account = config.msal.getActiveAccount(); accessTokenRequest.forceRefresh = true; return config.msal.acquireTokenSilent(accessTokenRequest).then(function (accessTokenResponse) { // Acquire token silent success var result = { access_token: accessTokenResponse.accessToken }; setAccessToken(result); }).catch(function (error) { //Acquire token silent failure if (error.errorCode === "post_request_failed" || error.errorCode === "monitor_window_timeout" || error.errorCode === "invalid_grant" || error.errorCode === "no_account_error" || error.errorCode === "consent_required" || error.errorCode === "interaction_required" || error.errorCode === "login_required") { logOut(); } }); } //get the bearer token for the user function getAccessToken() { return userAuth.getAuthToken(); } //set the bearer token for the user function setAccessToken(tokenData) { if (tokenData && tokenData.access_token) userAuth.setAuthToken(tokenData); } //fill in the user data from the token function fillAuthData() { var data = getAccessToken(); if ($location.$$path === "/signin/lockedOut") { config.isLockedOut = true; } if (data) { if (emailToVerify && !verifying) { verifying = true; var email = encodeURIComponent(emailToVerify); var url = config.realm + 'api/emailverifications?emailAddress=' + email + '&host=' + $window.location.host; var newToken = data; return $http({ method: 'get', url: url, headers: { 'Authorization': 'Bearer ' + data.access_token }, }). success(function (data, status, headers) { delete newToken.emailToVerify; setAccessToken(newToken); config.authenticated = true; if (config.appCode === 'OB') $location.path('/subscription/upgrade'); }). error(function (data, status, headers, config) { logError("User email verification failed (" + status + ")", url, true); }); } if (data.access_token) { config.authenticated = true; if (!data.userId) getCurrentUser(); else { config.userId = data.userId; config.accessLevel = 1; config.firstName = data.firstName; config.lastName = data.lastName; config.email = data.email; config.uploadBucketName = 'upload-' + data.userId; config.customSignIn = data.customSignIn; config.orgs = data.orgs; config.orgAdmin = data.orgAdmin; config.systemAdmin = data.systemAdmin; } } } return data; } function setAuthenticationData(data) { setAccessToken(data); fillAuthData(); config.authenticated = true; } function logOut(notAuthorised) { datacontext.clearAllCachedData(); setAccessToken(null); localStorage.clear(); config.userId = ''; config.authenticated = false; config.accessLevel = 0; config.firstName = ''; config.lastName = ''; config.customSignIn = ''; config.orgAdmin = ''; config.systemAdmin = ''; config.orgs = []; config.notAuthorised = notAuthorised; common.$broadcast(commonConfig.config.logoutSuccessEvent, { accessLevel: config.accessLevel }); config.msal.logoutRedirect(); } function acceptAgreement(agreementId) { var url = config.realm + 'api/Account/Agree/' + agreementId; return $http({ method: 'POST', url: url, headers: { 'Content-Type': 'application/x-www-form-urlencoded' } }). success(function (data, status, headers) { logInfo('Agreement Accepted'); }).error(function (data, status, headers, config) { logError("Accept Agreement Failed (" + status + ")", url, true); }); } function acceptAllAgreements() { var promises = []; getAgreements().forEach(function (agreement) { promises.push(acceptAgreement(agreement.Id)); }); return $q.all(promises).then(function (eventArgs) { var accessToken = getAccessToken(); if (accessToken) { accessToken.agreements = null; setAccessToken(accessToken); } getCurrentUser().then(function () { $location.path('/yourframeworks'); }); }); } function getAgreements() { var accessToken = getAccessToken(); if (accessToken) return JSON.parse(accessToken.agreements); return []; } function getCurrentUser() { var url = config.realm + 'api/Account/' + config.applicationId + '?cache =' + Date.now(); return $http({ method: 'GET', url: url }). success(function (data, status, headers) { var accessToken = getAccessToken(); if (accessToken) { config.notAuthorised = false; accessToken.userId = data.userId; accessToken.accessLevel = 1; accessToken.firstName = data.firstName; accessToken.lastName = data.lastName; accessToken.email = data.email; accessToken.agreements = data.agreements; accessToken.customSignIn = data.signIn; accessToken.orgs = data.orgs; accessToken.orgAdmin = data.orgAdmin; accessToken.systemAdmin = data.systemAdmin; accessToken.topLevelOrgId = data.topLevelOrgId; accessToken.roles = [{ //roles for non-fee paying adminMybadgesAccess: data.adminMybadgesAccess == null ? false : data.adminMybadgesAccess = "True" ? true : false, adminOrganisationAccess: data.adminOrganisationAccess == null ? false : data.adminOrganisationAccess = "True" ? true : false, adminOrganisationAddChild: data.adminOrganisationAddChild == null ? false : data.adminOrganisationAddChild = "True" ? true : false, adminOrganisationEdit: data.adminOrganisationEdit == null ? false : data.adminOrganisationEdit = "True" ? true : false, adminOrganisationRemove: data.adminOrganisationRemove == null ? false : data.adminOrganisationRemove = "True" ? true : false, //additional roles for fee paying adminGroupsAccess: data.adminGroupsAccess == null ? false : data.adminGroupsAccess = "True" ? true : false, adminFormsAccess: data.adminFormsAccess == null ? false : data.adminFormsAccess = "True" ? true : false, adminReportingAccess: data.adminReportingAccess == null ? false : data.adminReportingAccess = "True" ? true : false, adminOrganisationManageUsers: data.adminOrganisationManageUsers == null ? false : data.adminOrganisationManageUsers = "True" ? true : false, adminOrganisationManageFrameworks: data.adminOrganisationManageFrameworks == null ? false : data.adminOrganisationManageFrameworks = "True" ? true : false, adminOrganisationDiscoveryAndJoining: data.adminOrganisationDiscoveryAndJoining == null ? false : data.adminOrganisationDiscoveryAndJoining = "True" ? true : false, adminOrganisationIssuer: data.adminOrganisationIssuer == null ? false : data.adminOrganisationIssuer = "True" ? true : false, adminReviewAccess: data.adminReviewAccess == null ? false : data.adminReviewAccess = "True" ? true : false, adminBadgeReportingAccess: data.adminBadgeReportingAccess == null ? false : data.adminBadgeReportingAccess = "True" ? true : false }]; setAccessToken(accessToken); fillAuthData(); if (data.agreements) { config.authenticated = false; common.$broadcast(commonConfig.config.logoutSuccessEvent, { accessLevel: config.accessLevel }); $location.path('/account/agreements'); } else { config.authenticated = true; common.$broadcast(commonConfig.config.loginSuccessEvent, { accessLevel: config.accessLevel }); logInfo('Got User Data'); } return accessToken; } }). error(function (data, status, headers, config) { logError("User Data failed (" + status + ")", url, true); }); } function authenticate(username, password, noRedirect, refresh, brandorganisationId, applicationId) { var url = config.realm + 'Token'; return $http({ method: 'POST', url: url, data: $.param({ grant_type: "password", username: username, password: password, state: config.state, brandorganisationId: brandorganisationId, applicationId: applicationId, redirectUri: config.sysUrl }), headers: { 'Content-Type': 'application/x-www-form-urlencoded' } }) .then(function (response) { var data = response.data; logInfo('Authentication succeeded'); setAuthenticationData(data); if (!noRedirect) { return getCurrentUser().then(function () { if (refresh) { $window.location.href = '/'; } return data; }); } return data; }) .catch(function (error) { var status = error.status; logError("Authentication failed (" + status + ")", url, true); // You can handle the error here or rethrow it as needed. throw error; }); } function createOrgFeatures(organisationId, instanceCode, userId) { //get a bearer token from the myusers endpoint var url = config.orgAdminRemoteServiceUrl + 'organisationfeatures'; var organisationFeatureViewModel = { OrganisationId: organisationId, InstanceCode: instanceCode, UserId: userId }; console.log('Create Org Features'); return $http({ method: 'POST', url: url, data: organisationFeatureViewModel }). success(function (data, status, headers, config) { logInfo('Create Org Features Success'); }). error(function (data, status, headers, config) { logInfo('Create Org Features Error'); }); } //register a new user function registerPersonal(user) { var url = config.realm + 'api/Account/Register'; return $http({ method: 'POST', url: url, data: { ApplicationId: config.applicationId, FirstName: user.firstName, LastName: user.lastName, Email: user.email, Password: user.password, OrganisationId: user.organisation, AppCode: config.appCode }, headers: { 'Content-Type': 'application/json' } }). success(function (data, status, headers, config) { logInfo('Registration succeeded'); return true; }). error(function (data, status, headers, config) { if (data && data.errorCode && data.errorCode === "0") { } else logError("Registration failed (" + status + ")", url, true); }); } //register a new admin user - create an org with the specified name function register(user, payment, account, users) { $rootScope.licenceUrl = config.myShowcaseSiteUrl; var url = config.realm + 'api/Account/Register'; return $http({ method: 'POST', url: url, data: { ApplicationId: config.applicationId, FirstName: user.firstName, LastName: user.lastName, Email: user.email, Password: user.password, OrganisationId: user.organisation, OrganisationName: user.organisationName, OrganisationUrl: user.organisationUrl, NewOrganisation: user.newOrganisation, AdditionalProperties: { "RegisterCountry": user.countryCode }, Roles: [ "myshowcase", "mybadges", ], AppCode: config.appCode }, headers: { 'Content-Type': 'application/json' } }). success(function (data, status, headers, config) { logInfo('Registration succeeded'); common.$broadcast(commonConfig.config.registerSuccessEvent, { register: true }); $rootScope.userId = data.userId; logInfo('Instant code' + user.instanceCode); user.id = data.userId; user.organisationId = data.organisationId; return $q.all([ setupRegisteredUser(user) ]).then(function () { if (user.organisationUrl) { return myUsersDataContext.createOrganisationIssuer({ organisationId: user.organisationId, name: user.organisationName, description: user.organisationName, url: user.organisationUrl, createdBy: user.id, jsonUrl: "", logoUrl: null }).then(function () { return true; }, function () { return true; }); } else { return paymentsDataContext.sendRequest(true, user.organisationId).then(function (data) { return true; }); } console.log("register complete"); }).catch(function (error) { console.log(error); }); }). error(function (data, status, headers, config) { if (data && data.errorCode && data.errorCode === "2") { //Org name taken data.errorMessage = "There is already an organisation named '" + user.organisationName + "', please enter a different organisation name"; logError(data.errorMessage, url, true); return data; } if (data && data.errorCode && data.errorCode === "0") { } else logError("Registration failed (" + status + ")", url, true); }); } //register a new admin user - create an org with the specified name function registerOpenBadges(user, individual, brandingOrganisationId) { user.subDomain == ''; if (individual) { user.organisation = config.noOrgId; user.organisationUrl = null; user.organisationName = null; user.organisationSubDomain = null; user.newOrganisation = false; } var url = config.realm + 'api/Account/Register'; return $http({ method: 'POST', url: url, data: { ApplicationId: config.applicationId, FirstName: user.firstName, LastName: user.lastName, Email: user.email, Password: user.password, OrganisationId: user.organisation, OrganisationName: user.organisationName, OrganisationUrl: user.organisationUrl, OrganisationSubDomain: user.subDomain, NewOrganisation: user.newOrganisation, OrganisationBrandingId: brandingOrganisationId, AppCode: user.appCode, AdditionalProperties: { "RegisterCountry": user.countryCode }, Roles: ["mybadges", "myshowcase"] }, headers: { 'Content-Type': 'application/json' } }). success(function (data, status, headers, config) { logInfo('Registration succeeded'); common.$broadcast(commonConfig.config.registerSuccessEvent, { register: true }); $rootScope.userId = data.userId; user.id = data.userId; user.organisationId = data.organisationId; logInfo('Instant code' + user.instanceCode); if (!individual) { $q.all([ createOrgFeatures(data.organisationId, 'OBS', data.userId), createEmailTemplates(data.organisationId, config.data.AppCode), //Get the organisation's default 'systemadmin', 'admin' and 'user' roles //then set this user as it's Systemadmin as well as normal User setupRegisteredUser(user, individual) ]).then(function () { //now authenticate the newly created user without redirecting authenticate(user.email, user.password, true, data.organisationId).then(function () { //authenticate and redirect authenticate(user.email, user.password); generateNewDeveloperKey(data.organisationId).then(function() { $window.location.href = '#!/'; $window.location.reload(); }); }); console.log("register complete"); }).catch(function (error) { console.log(error); }); } else { $q.all([ setupRegisteredUser(user, individual) ]).then(function () { //now authenticate the newly created user without redirecting authenticate(user.email, user.password, true, false, brandingOrganisationId).then(function () { $rootScope.DoNotInitailize = true; //authenticate and redirect authenticate(user.email, user.password, false, false, brandingOrganisationId, config.data.ApplicationId); $window.location.href = '#!/'; $window.location.reload(); }); console.log("register complete"); }).catch(function (error) { console.log(error); }); } }). error(function (data, status, headers, config) { if (data && data.errorCode && data.errorCode === "2") { //Org name taken data.errorMessage = "There is already an organisation named '" + user.organisationName + "', please enter a different organisation name"; logError(data.errorMessage, url, true); return data; } if (data && data.errorCode && data.errorCode === "0") { } else logError("Registration failed (" + status + ")", url, true); }); } function registerCuppa(user) { user.subDomain == ''; var url = config.realm + 'api/Account/Register'; return $http({ method: 'POST', url: url, data: { ApplicationId: config.applicationId, FirstName: user.firstName, LastName: user.lastName, Email: user.email, Password: user.password, OrganisationId: user.organisation, OrganisationName: user.organisationName, OrganisationUrl: user.organisationUrl, OrganisationSubDomain: user.subDomain, NewOrganisation: user.newOrganisation, AppCode: user.appCode, AdditionalProperties: { "RegisterCountry": user.countryCode }, Roles: ["mybadges", "myshowcase"] }, headers: { 'Content-Type': 'application/json' } }). success(function (data, status, headers, config) { logInfo('Registration succeeded'); common.$broadcast(commonConfig.config.registerSuccessEvent, { register: true }); $rootScope.userId = data.userId; user.id = data.userId; user.organisationId = data.organisationId; logInfo('Instant code' + user.instanceCode); console.log(config); $q.all([ createOrgFeatures(data.organisationId, 'CC', data.userId), createEmailTemplates(data.organisationId, 'CC'), setupRegisteredUser(user, false) ]).then(function () { //now authenticate the newly created user without redirecting authenticate(user.email, user.password, true).then(function () { //authenticate and redirect authenticate(user.email, user.password); $window.location = sysUrl + '#/'; $window.location.reload(); }); console.log("register complete"); }).catch(function (error) { console.log(error); }); }). error(function (data, status, headers, config) { if (data && data.errorCode && data.errorCode === "2") { //Org name taken data.errorMessage = "There is already an organisation named '" + user.organisationName + "', please enter a different organisation name"; logError(data.errorMessage, url, true); return data; } if (data && data.errorCode && data.errorCode === "0") { } else logError("Registration failed (" + status + ")", url, true); }); } function setupRegisteredUser(user, individual) { return authenticate(user.email, user.password, true) .then(function () { return setDefaultCustomRoles($rootScope.userId, user.organisationId, individual).then(function () { if (individual) { return datacontext.setRolesIndividual($rootScope.userId); } else { return datacontext.setRoles($rootScope.userId); } }); }); } //set the systemadmin and user role //on the given user in the given org function setDefaultCustomRoles(userId, orgId, individual) { if (individual) { return rolesAdminDataContext.setSystemAdminDefaultRoles(config.userAppCodes, config.userRoles, config.noOrgId, userId); } else { return rolesAdminDataContext.setSystemAdminDefaultRoles(config.adminAppCodes, config.adminRoles, orgId, userId); } } function createEmailTemplates(organisationId, instanceCode) { //get a bearer token from the myusers endpoint if (instanceCode == "CUPPA") { var welCuppa = getDefaultCuppaWelcome(); welCuppa.systemShortCode = instanceCode; welCuppa.organisationId = organisationId; return createEmailTemplate(welCuppa); } var wel = getDefaultWelcome(); wel.systemShortCode = instanceCode; wel.organisationId = organisationId; var iss = getDefaultIssuing(); iss.systemShortCode = instanceCode; iss.organisationId = organisationId; return createEmailTemplate(wel).then(createEmailTemplate(iss)); } function createEmailTemplate(template) { var request = $http({ method: "post", url: config.myusersUrl + 'api/organisations/emailTemplates', data: template }); return (request.then(handleSuccess, handleError)); } function handleError(response) { // The API response from the server should be returned in a // nomralized format. However, if the request was not handled by the // server (or what not handles properly - ex. server error), then we // may have to normalize it on our end, as best we can. if ( !angular.isObject(response.data) || !response.data.message ) { return ($q.reject("An unknown error occurred.")); } // Otherwise, use expected error message. return ($q.reject(response.data.message)); } // I transform the successful response, unwrapping the application data // from the API response payload. function handleSuccess(response) { return (response.data); } function getDefaultIssuing() { return { name: 'Badge Issued', description: 'Email template for all badge being issued emails.', emailType: 'BadgeIssued', subject: "You've been issued a badge - {badgeName}", title: 'Congratulations!', content: "

You have been issued with a Badge by {issuer}. 


If you have any questions about this email then please contact the badge issuer.{badgeImage}

", signature: "

Regards,

The OpenBadges.me team. 


{badgeDownloadLink}


", fromEmail: 'badges@openbadges.me', new: false, htmlContent: ' You\'ve been issued a badge -{ badgeName }


Logo

Congratulations!

You have been issued with a Badge by {issuer}. 

If you have any questions about this email then please contact the badge issuer.{badgeImage}

Regards,

The OpenBadges.me team. 

{badgeDownloadLink}

{shareLink}

{register}

' }; } function getDefaultWelcome() { return { name: 'Welcome Email', description: 'Welcome template', emailType: 'Welcome', subject: "Welcome to openbadges.me", title: 'Welcome to openbadges.me', content: '

Get started

Your username is: {userName}

You set the password when you created the account (if you have any problems there’s a link to reset it on the sign in page).

Are you collecting badges? 

Sign in and start managing your badges, awards and collections

Are you issuing badges? 

Follow these steps and you’ll be awarding badges in no time:

  1. Set up your issuer details
    Tell the system who your badges come from by adding an issuer
  2. Create your first badge graphic
    Get creative: use the design tool or upload a graphic
  3. Create a badge
    Add information to your graphic: what’s it called? how do people earn it?
  4. Award your badge to some lucky recipients
    Issue badges in bulk, to specific users, or automatically using our APIs
  5. View reports and analytics
    Powerful overviews of how people are doing

If you need more help, you can visit our help center. 

Get started

', signature: "Regards,

The OpenBadges.me team.", fromEmail: 'badges@openbadges.me', new: false, htmlContent: ' Welcome to openbadges.me


Logo


Welcome to openbadges.me.

Get started

Your username is: {userName}

You set the password when you created the account (if you have any problems there’s a link to reset it on the sign in page).

Are you collecting badges? 

Sign in and start managing your badges, awards and collections

Are you issuing badges? 

Follow these steps and you’ll be awarding badges in no time:

  1. Set up your issuer details
    Tell the system who your badges come from by adding an issuer
  2. Create your first badge graphic
    Get creative: use the design tool or upload a graphic
  3. Create a badge
    Add information to your graphic: what’s it called? how do people earn it?
  4. Award your badge to some lucky recipients
    Issue badges in bulk, to specific users, or automatically using our APIs
  5. View reports and analytics
    Powerful overviews of how people are doing

If you need more help, you can visit our help center. 

Get started

Regards,

The OpenBadges.me team.
' }; } function getDefaultCuppaWelcome() { return { name: 'Welcome Email', description: 'Email template for welcome emails', emailType: 'Welcome', subject: "Welcome to Cuppa Care.", title: 'Message from CuppaCare, the learning service for social care', content: '

Thanks for setting up your admin account.

Your CuppaCare admin username is: {userName}

Log in any time at: https://admin.cuppacare.com

', signature: '

Happy brewing!

Team at CuppaCare

info@cuppacare.com

www.cuppacare.com

Copyright © 2019 Sara Dunn Associates Ltd. All rights reserved.

', fromEmail: 'noreply@cuppacare.com', new: false, htmlContent: ' Welcome to CuppaCare Admin


Logo


Message from CuppaCare, the learning service for social care

Thanks for setting up your admin account.

Your CuppaCare admin username is: {userName}

Log in any time at: https://admin.cuppacare.com

Happy brewing!

Team at CuppaCare

info@cuppacare.com

www.cuppacare.com

Copyright © 2019 Sara Dunn Associates Ltd. All rights reserved.

' }; } function generateNewDeveloperKey(orgId) { var k = randomPKey(60, true, false, true); var integration = { organisationId: orgId, connectionType: 8, connectionCode: orgId, connectionName: orgId, primaryKey: "", secondaryKey: k, } return datacontext.createIntegration(integration); }; function randomPKey(length, addUpper, addSymbols, addNums) { var lower = "abcdefghijklmnopqrstuvwxyz"; var upper = addUpper ? lower.toUpperCase() : ""; var nums = addNums ? "0123456789" : ""; var symbols = addSymbols ? "!#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~" : ""; var all = lower + upper + nums + symbols; while (true) { var pass = ""; for (var i = 0; i < length; i++) { pass += all[Math.random() * all.length | 0]; } // criteria: if (!/[a-z]/.test(pass)) continue; // lowercase is a must if (addUpper && !/[A-Z]/.test(pass)) continue; // check uppercase if (addSymbols && !/\W/.test(pass)) continue; // check symbols if (addNums && !/\d/.test(pass)) continue; // check nums return pass; // all good } } };