2016-01-25 17:14:42 +01:00
ActiveEntry = {};
ActiveEntry . isAbc = function () {
return "abc" ;
};
if ( Meteor . isClient ) {
Session . setDefault ( 'Photonic.ActiveEntry' , {
logo : {
url : "https://upload.wikimedia.org/wikipedia/commons/1/1a/Photon-photon_scattering.png" ,
displayed : true
},
signIn : {
displayFullName : true ,
destination : "/"
},
signUp : {
destination : "/"
},
themeColors : {
primary : ""
2016-02-04 17:53:01 -05:00
},
passwordOptions : {
2016-02-11 08:48:11 -05:00
showPasswordStrengthIndicator : true ,
2016-02-14 20:45:04 -05:00
requireRegexValidation : true ,
2016-02-11 08:48:11 -05:00
//requireStrongPasswords: false
2016-02-14 20:45:04 -05:00
passwordHistoryCount : 6 ,
2016-02-15 13:09:58 -05:00
failedAttemptsLimit : 5 ,
2016-02-15 16:40:53 -05:00
passwordExpirationDays : 90 ,
2016-04-14 15:02:22 -04:00
inactivityPeriodDays : 180 ,
expireTimeInMinute : 30
2016-01-25 17:14:42 +01:00
}
});
ActiveEntry . errorMessages = new ReactiveDict ( 'errorMessages' );
ActiveEntry . errorMessages . set ( 'signInError' , false );
2016-02-02 10:25:02 -05:00
// Success messages
ActiveEntry . successMessages = new ReactiveDict ( 'successMessages' );
2016-01-25 17:14:42 +01:00
2016-02-04 17:53:01 -05:00
// Change password warning message according to whether zxcvbn is turned on
Session . set ( 'passwordWarning' , 'Password must have at least 8 characters. It must contain at least 1 uppercase, 1 lowercase, 1 number and 1 special character.' );
2016-03-22 15:43:06 -04:00
2016-04-14 15:02:22 -04:00
// Activate LDAP if ldap url and port is set in settings.json
2016-03-22 15:43:06 -04:00
Meteor . call ( 'isLDAPSet' , function ( error , isSet ) {
Session . set ( 'isLDAPSet' , isSet );
});
}
if ( Meteor . isServer ) {
2017-04-21 18:57:35 +02:00
LDAP_DEFAULTS = {};
2016-03-22 15:43:06 -04:00
LDAP_DEFAULTS . url = Meteor . settings . ldap && Meteor . settings . ldap . url ;
LDAP_DEFAULTS . port = Meteor . settings . ldap && Meteor . settings . ldap . port ;
2016-01-25 17:14:42 +01:00
}
ActiveEntry . configure = function ( configObject ) {
if ( Meteor . isClient ) {
2016-02-15 13:09:58 -05:00
// Set passwordOptions if they are not defined
if ( ! configObject . passwordOptions ) {
configObject . passwordOptions = {
showPasswordStrengthIndicator : true ,
requireRegexValidation : false ,
//requireStrongPasswords: false
passwordHistoryCount : 6 ,
failedAttemptsLimit : 5 ,
2016-02-15 16:40:53 -05:00
passwordExpirationDays : 90 ,
2016-04-14 15:02:22 -04:00
inactivityPeriodDays : 180 ,
expireTimeInMinute : 30
2016-02-15 13:09:58 -05:00
}
}
2016-01-25 17:14:42 +01:00
Session . set ( 'Photonic.ActiveEntry' , configObject );
}
};
ActiveEntry . verifyPassword = function ( password ) {
if ( password . length === 0 ) {
ActiveEntry . errorMessages . set ( 'password' , 'Password is required' );
2016-02-02 10:25:02 -05:00
ActiveEntry . successMessages . set ( 'password' , null );
2016-02-04 17:53:01 -05:00
} else if ( ! checkPasswordStrength ( password )) {
ActiveEntry . errorMessages . set ( 'password' , Session . get ( 'passwordWarning' ));
2016-02-02 10:25:02 -05:00
ActiveEntry . successMessages . set ( 'password' , null );
} else {
ActiveEntry . errorMessages . set ( 'password' , null );
ActiveEntry . successMessages . set ( 'password' , 'Password present' );
2016-01-25 17:14:42 +01:00
}
};
2016-02-03 14:41:51 -05:00
2016-01-25 17:14:42 +01:00
ActiveEntry . verifyConfirmPassword = function ( password , confirmPassword ) {
2016-02-11 08:48:11 -05:00
// we have two different logic checks happening in this function
// would be reasonable to separate them out into separate functions
if ( confirmPassword === "" ) {
2016-01-25 17:14:42 +01:00
ActiveEntry . errorMessages . set ( 'confirm' , 'Password is required' );
2016-02-11 08:48:11 -05:00
ActiveEntry . successMessages . set ( 'confirm' , null );
} else if ( confirmPassword === password ) {
2016-02-02 10:25:02 -05:00
ActiveEntry . errorMessages . set ( 'confirm' , null );
ActiveEntry . successMessages . set ( 'confirm' , 'Passwords match' );
2016-02-11 08:48:11 -05:00
} else {
2016-02-02 15:31:01 -05:00
ActiveEntry . errorMessages . set ( 'confirm' , 'Passwords do not match' );
ActiveEntry . successMessages . set ( 'confirm' , null );
2016-01-25 17:14:42 +01:00
}
};
2016-02-03 14:41:51 -05:00
2016-01-25 17:14:42 +01:00
ActiveEntry . verifyEmail = function ( email ) {
if ( email . length === 0 ) {
ActiveEntry . errorMessages . set ( 'email' , 'Email is required' );
2016-02-02 10:25:02 -05:00
ActiveEntry . successMessages . set ( 'email' , null );
2016-01-25 17:14:42 +01:00
} else if ( email . indexOf ( "@" ) === - 1 ){
ActiveEntry . errorMessages . set ( 'email' , 'Email is poorly formatted' );
2016-02-02 10:25:02 -05:00
ActiveEntry . successMessages . set ( 'email' , null );
2016-01-25 17:14:42 +01:00
} else if ( email . indexOf ( "@" ) >= 0 ){
2016-02-02 10:25:02 -05:00
ActiveEntry . errorMessages . set ( 'email' , null );
ActiveEntry . successMessages . set ( 'email' , 'Email present' );
2016-01-25 17:14:42 +01:00
}
};
2016-02-03 14:41:51 -05:00
2016-01-25 17:14:42 +01:00
ActiveEntry . verifyFullName = function ( fullName ) {
if ( fullName . length === 0 ) {
ActiveEntry . errorMessages . set ( 'fullName' , 'Name is required' );
2016-02-02 10:25:02 -05:00
ActiveEntry . successMessages . set ( 'fullName' , null );
2016-01-25 17:14:42 +01:00
} else if ( fullName . indexOf ( " " ) === - 1 ){
ActiveEntry . errorMessages . set ( 'fullName' , 'Name is probably not complete' );
2016-02-02 10:25:02 -05:00
ActiveEntry . successMessages . set ( 'fullName' , null );
2016-01-25 17:14:42 +01:00
} else if ( fullName . indexOf ( " " ) >= 0 ){
2016-02-02 10:25:02 -05:00
//ActiveEntry.errorMessages.set('fullName', 'Name present');
ActiveEntry . errorMessages . set ( 'fullName' , null );
ActiveEntry . successMessages . set ( 'fullName' , 'Name present' );
2016-01-25 17:14:42 +01:00
}
};
2016-03-22 17:03:13 -04:00
ActiveEntry . verifyLDAPUsername = function ( username ) {
if ( username === "" ) {
ActiveEntry . errorMessages . set ( "ldapUsername" , "Username is required" );
ActiveEntry . successMessages . set ( "ldapUsername" , null );
} else {
ActiveEntry . errorMessages . set ( "ldapUsername" , null );
ActiveEntry . successMessages . set ( "ldapUsername" , "Username present" );
}
};
ActiveEntry . verifyLDAPPassword = function ( password ) {
if ( password === "" ) {
ActiveEntry . errorMessages . set ( "ldapPassword" , "Password is required" );
ActiveEntry . successMessages . set ( "ldapPassword" , null );
} else {
ActiveEntry . errorMessages . set ( "ldapPassword" , null );
ActiveEntry . successMessages . set ( "ldapPassword" , "Password present" );
}
};
2016-01-25 17:14:42 +01:00
ActiveEntry . signIn = function ( emailValue , passwordValue ){
2016-02-15 13:09:58 -05:00
2016-01-25 17:14:42 +01:00
ActiveEntry . verifyPassword ( passwordValue );
ActiveEntry . verifyEmail ( emailValue );
2016-04-14 15:02:22 -04:00
var signInArgs = { email : emailValue , password : passwordValue };
2016-02-15 13:09:58 -05:00
2016-02-14 17:03:00 -05:00
var ActiveEntryConfig = Session . get ( 'Photonic.ActiveEntry' );
2016-04-14 15:02:22 -04:00
var passwordOptions = ActiveEntryConfig && ActiveEntryConfig . passwordOptions ;
2016-01-25 17:14:42 +01:00
2016-04-14 15:02:22 -04:00
Meteor . call ( "isAccountInactive" , emailValue , passwordOptions . inactivityPeriodDays , function ( error , isAccountInactive ) {
2016-01-25 17:14:42 +01:00
if ( error ) {
2016-04-14 15:02:22 -04:00
console . warn ( error . message );
return ;
}
if ( isAccountInactive ) {
// Lock account
ActiveEntry . lockAccount ( signInArgs );
2016-01-25 17:14:42 +01:00
} else {
2016-04-14 15:02:22 -04:00
// Check account is locked
ActiveEntry . isAccountLocked ( signInArgs , passwordOptions );
}
});
2016-02-15 13:09:58 -05:00
2016-04-14 15:02:22 -04:00
};
2016-02-15 13:09:58 -05:00
2016-04-14 15:02:22 -04:00
ActiveEntry . lockAccount = function ( signInArgs ) {
var emailValue = signInArgs && signInArgs . email ;
if ( ! emailValue ) {
return ;
}
Meteor . call ( "lockAccount" , emailValue );
ActiveEntry . errorMessages . set ( 'signInError' , "Your account has been locked due to inactivity." );
};
ActiveEntry . isAccountLocked = function ( signInArgs , passwordOptions ) {
var emailValue = signInArgs && signInArgs . email ;
if ( ! emailValue ) {
return ;
}
Meteor . call ( "isAccountLocked" , emailValue , function ( error , isAccountLocked ) {
if ( error ) {
console . warn ( error . message );
return ;
}
if ( isAccountLocked ) {
ActiveEntry . errorMessages . set ( 'signInError' , "Your account has been locked." );
return ;
}
// Get failed attempts count
ActiveEntry . getFailedAttemptsCount ( signInArgs , passwordOptions );
});
};
ActiveEntry . getFailedAttemptsCount = function ( signInArgs , passwordOptions ) {
var emailValue = signInArgs && signInArgs . email ;
if ( ! emailValue ) {
return ;
}
Meteor . call ( "getFailedAttemptsCount" , emailValue , function ( error , failedAttemptsCount ) {
if ( error ) {
console . warn ( error . message );
return ;
}
if ( failedAttemptsCount != passwordOptions . failedAttemptsLimit ) {
// Login with password
ActiveEntry . loginWithPassword ( signInArgs , passwordOptions );
} else {
ActiveEntry . errorMessages . set ( 'signInError' , "Your account has been locked." );
}
});
};
ActiveEntry . loginWithPassword = function ( signInArgs , passwordOptions ) {
var emailValue = signInArgs && signInArgs . email ;
var password = signInArgs && signInArgs . password ;
if ( ! emailValue || ! password ) {
return ;
}
Meteor . loginWithPassword ( emailValue , password , function ( loginError , result ) {
if ( loginError ) {
// Login failed
if ( loginError . error == 403 ) {
ActiveEntry . updateFailedAttempts ( signInArgs , passwordOptions , loginError );
2016-02-15 16:40:53 -05:00
}
2016-04-14 15:02:22 -04:00
return ;
}
// Reset failed attempts
Meteor . call ( "resetFailedAttempts" , emailValue );
// Check password expiration
ActiveEntry . isPasswordExpired ( passwordOptions );
});
};
ActiveEntry . isPasswordExpired = function ( passwordOptions ) {
// if password expired, route to changePassword page
Meteor . call ( "isPasswordExpired" , passwordOptions . passwordExpirationDays , function ( error , isPasswordExpired ) {
if ( error ) {
console . warn ( error . message );
return ;
}
// Update last login time
Meteor . call ( "updateLastLoginDate" );
if ( isPasswordExpired ) {
ActiveEntry . errorMessages . set ( 'changePasswordError' , 'Your password expired. Please change your password.' );
Router . go ( '/changePassword' );
} else {
var ActiveEntryConfig = Session . get ( 'Photonic.ActiveEntry' );
Router . go ( ActiveEntryConfig . signIn . destination );
2016-01-25 17:14:42 +01:00
}
});
2016-04-14 15:02:22 -04:00
};
2016-02-14 17:03:00 -05:00
2016-04-14 15:02:22 -04:00
ActiveEntry . updateFailedAttempts = function ( signInArgs , passwordOptions , loginError ) {
var emailValue = signInArgs && signInArgs . email ;
if ( ! emailValue ) {
return ;
}
Meteor . call ( "updateFailedAttempts" , emailValue , passwordOptions . failedAttemptsLimit , function ( error , failedAttemptCount ) {
if ( error ) {
console . warn ( error . message );
return ;
}
if ( failedAttemptCount == passwordOptions . failedAttemptsLimit ) {
ActiveEntry . errorMessages . set ( 'signInError' , "Too many failed login attempts. Your account has been locked." );
} else if ( failedAttemptCount < passwordOptions . failedAttemptsLimit ) {
ActiveEntry . errorMessages . set ( 'signInError' , loginError . message + "<br />" + ( passwordOptions . failedAttemptsLimit - failedAttemptCount ) + " attempts remaining." );
} else {
ActiveEntry . errorMessages . set ( 'signInError' , loginError . message );
}
});
2016-01-25 17:14:42 +01:00
};
2016-04-14 15:02:22 -04:00
2016-03-22 15:43:06 -04:00
ActiveEntry . loginWithLDAP = function ( username , password ) {
2016-03-22 17:03:13 -04:00
ActiveEntry . verifyLDAPUsername ( username );
ActiveEntry . verifyLDAPPassword ( password );
ActiveEntry . errorMessages . set ( 'signInError' , null );
if ( ActiveEntry . errorMessages . get ( "ldapUsername" ) || ActiveEntry . errorMessages . get ( "ldapPassword" )) {
2016-03-22 15:43:06 -04:00
return ;
}
Meteor . loginWithLDAP ( username , password , {
// The dn value depends on what you want to search/auth against
// The structure will depend on how your ldap server
// is configured or structured.
dn : "uid=" + username + ",ou=users,ou=system" ,
// The search value is optional. Set it if your search does not
// work with the bind dn.
searchResultsProfileMap : [
{
resultKey : 'cn' ,
profileProperty : 'fullName'
},
{
resultKey : 'mail' ,
profileProperty : 'email'
}
]
}, function ( error ) {
if ( error ) {
ActiveEntry . errorMessages . set ( 'signInError' , error . errorType + " [" + error . error + "]" );
return ;
}
ActiveEntry . errorMessages . set ( 'signInError' , null );
// Update last login time
Meteor . call ( "updateLastLoginDate" );
var ActiveEntryConfig = Session . get ( 'Photonic.ActiveEntry' );
Router . go ( ActiveEntryConfig . signIn . destination );
});
};
2016-01-25 17:14:42 +01:00
ActiveEntry . signUp = function ( emailValue , passwordValue , confirmPassword , fullName ){
ActiveEntry . verifyEmail ( emailValue );
ActiveEntry . verifyPassword ( passwordValue );
ActiveEntry . verifyConfirmPassword ( passwordValue , confirmPassword );
ActiveEntry . verifyFullName ( fullName );
2016-02-02 15:31:01 -05:00
ActiveEntry . errorMessages . set ( 'signInError' , null );
2016-01-25 17:14:42 +01:00
2016-02-02 10:25:02 -05:00
var errorIsFound = false ;
Object . keys ( ActiveEntry . errorMessages . keys ). forEach ( function ( key ) {
if ( ActiveEntry . errorMessages . get ( key ) !== "null" && ActiveEntry . errorMessages . get ( key ) !== null ) {
errorIsFound = true ;
}
});
if ( errorIsFound ) {
return ;
}
2016-01-25 17:14:42 +01:00
2016-03-22 15:43:06 -04:00
// Capitalize first letter of every word in fullName
var capitalizedFullName = fullName . replace ( /[^\s]+/g , function ( str ){
return str . substr ( 0 , 1 ). toUpperCase () + str . substr ( 1 ). toLowerCase ();
});
2016-01-25 17:14:42 +01:00
Accounts . createUser ({
email : emailValue ,
password : passwordValue ,
profile : {
2016-03-22 15:43:06 -04:00
fullName : capitalizedFullName
2016-01-25 17:14:42 +01:00
}
}, function ( error , result ) {
if ( error ) {
ActiveEntry . errorMessages . set ( 'signInError' , error . message );
2016-04-14 15:02:22 -04:00
return ;
}
// Add password in previousPasswords field
ActiveEntry . insertHashedPassword ( passwordValue );
2016-02-15 13:09:58 -05:00
2016-04-14 15:02:22 -04:00
// Update password set date
ActiveEntry . updatePasswordSetDate ();
2016-02-15 16:40:53 -05:00
2016-04-14 15:02:22 -04:00
// Update last login time
Meteor . call ( "updateLastLoginDate" );
2016-02-15 16:40:53 -05:00
2016-04-14 15:02:22 -04:00
var ActiveEntryConfig = Session . get ( 'Photonic.ActiveEntry' );
Router . go ( ActiveEntryConfig . signUp . destination );
});
};
ActiveEntry . changePassword = function ( oldPassword , password ) {
Meteor . call ( "checkPasswordExistence" , new String ( password ). hashCode (), function ( error , isPasswordExisted ) {
if ( error ) {
console . warn ( error . message );
ActiveEntry . errorMessages . set ( 'changePasswordError' , error . message );
return ;
}
if ( isPasswordExisted ) {
ActiveEntry . errorMessages . set ( 'changePasswordError' , 'Password is used before. Please change your new password.' );
} else {
ActiveEntry . errorMessages . set ( 'changePasswordError' , null );
// If password is not found in password history, change the password
Accounts . changePassword ( oldPassword , password , function ( error ) {
if ( error ) {
console . warn ( error );
ActiveEntry . errorMessages . set ( 'changePasswordError' , error . message );
return ;
}
// Save the new password
ActiveEntry . insertHashedPassword ( password );
// Update password expiration date
ActiveEntry . updatePasswordSetDate ();
// Logout
ActiveEntry . signOut ();
// Go to signIn page for new entry
Router . go ( '/entrySignIn' );
});
2016-01-25 17:14:42 +01:00
}
2016-04-14 15:02:22 -04:00
2016-01-25 17:14:42 +01:00
});
};
2016-02-14 17:03:00 -05:00
2016-03-16 10:28:07 -04:00
ActiveEntry . forgotPassword = function ( emailAddress ) {
ActiveEntry . verifyEmail ( emailAddress );
ActiveEntry . errorMessages . set ( "forgotPassword" , null );
ActiveEntry . successMessages . set ( "forgotPassword" , null );
if ( ActiveEntry . errorMessages . get ( "email" )) {
return ;
}
Accounts . forgotPassword ({ email : emailAddress }, function ( error ){
if ( error ) {
console . warn ( error . message );
ActiveEntry . errorMessages . set ( "forgotPassword" , error . message );
2016-04-14 15:02:22 -04:00
ActiveEntry . successMessages . set ( "forgotPassword" , null );
2016-03-16 10:28:07 -04:00
return ;
}
2016-04-14 15:02:22 -04:00
2016-03-16 10:28:07 -04:00
// Show email sent notification
ActiveEntry . successMessages . set ( "forgotPassword" , "Your password reset email is sent to <strong>" + emailAddress + "</strong>" );
});
};
ActiveEntry . resetPassword = function ( passwordValue , confirmPassword ) {
ActiveEntry . verifyPassword ( passwordValue );
ActiveEntry . verifyConfirmPassword ( passwordValue , confirmPassword );
ActiveEntry . errorMessages . set ( "resetPassword" , null );
// Check error messages
if ( ActiveEntry . errorMessages . get ( "password" ) || ActiveEntry . errorMessages . get ( "confirm" )) {
return ;
}
2016-04-14 15:02:22 -04:00
var ActiveEntryConfig = Session . get ( 'Photonic.ActiveEntry' );
var passwordOptions = ActiveEntryConfig && ActiveEntryConfig . passwordOptions ;
2016-04-13 14:56:35 -04:00
// Check token is expired
2016-04-14 15:02:22 -04:00
Meteor . call ( 'checkResetTokenIsExpired' , Session . get ( '_resetPasswordToken' ), passwordOptions . expireTimeInMinute , function ( error , isTokenExpired ) {
2016-03-16 10:28:07 -04:00
if ( error ) {
2016-04-13 14:56:35 -04:00
console . log ( error . message );
2016-03-16 10:28:07 -04:00
return ;
}
2016-04-13 14:56:35 -04:00
if ( isTokenExpired ) {
console . log ( "Your link is expired" );
// Go to forgotPassword to create a new reset link
ActiveEntry . errorMessages . set ( "forgotPassword" , 'Your link is expired. Please create a new reset link.' );
Router . go ( '/forgotPassword' );
return ;
}
2016-04-14 15:02:22 -04:00
// Check password history
Meteor . call ( "checkResetPasswordExistence" , new String ( passwordValue ). hashCode (), Session . get ( '_resetPasswordToken' ), function ( error , isPasswordExisted ) {
2016-04-13 14:56:35 -04:00
if ( error ) {
2016-04-14 15:02:22 -04:00
console . warn ( error . message );
ActiveEntry . errorMessages . set ( 'resetPasswordError' , error . message );
2016-04-13 14:56:35 -04:00
return ;
}
2016-04-14 15:02:22 -04:00
if ( isPasswordExisted ) {
ActiveEntry . errorMessages . set ( 'resetPasswordError' , 'Password is used before. Please change your new password.' );
} else {
ActiveEntry . errorMessages . set ( 'resetPasswordError' , null );
Accounts . resetPassword ( Session . get ( '_resetPasswordToken' ), passwordValue , function ( error ) {
if ( error ) {
ActiveEntry . errorMessages . set ( "resetPassword" , error . message );
return ;
}
Session . set ( '_resetPasswordToken' , null );
// Save the new password
ActiveEntry . insertHashedPassword ( passwordValue );
// Update password expiration date
ActiveEntry . updatePasswordSetDate ();
// Update last login time
Meteor . call ( "updateLastLoginDate" );
var ActiveEntryConfig = Session . get ( 'Photonic.ActiveEntry' );
Router . go ( ActiveEntryConfig . signIn . destination );
});
}
2016-04-13 14:56:35 -04:00
});
2016-03-16 10:28:07 -04:00
});
};
2016-02-14 17:03:00 -05:00
// Insert hashed password in previousPasswords fields
ActiveEntry . insertHashedPassword = function ( passwordValue ) {
var ActiveEntryConfig = Session . get ( 'Photonic.ActiveEntry' );
var passwordHistoryCount = ActiveEntryConfig && ActiveEntryConfig . passwordOptions && ActiveEntryConfig . passwordOptions . passwordHistoryCount || 6 ;
Meteor . call ( "insertHashedPassword" , [ new String ( passwordValue ). hashCode (), passwordHistoryCount ]);
};
2016-02-15 13:09:58 -05:00
ActiveEntry . updatePasswordSetDate = function () {
Meteor . call ( "updatePasswordSetDate" );
2016-02-14 17:03:00 -05:00
};
2016-01-25 17:14:42 +01:00
ActiveEntry . signOut = function (){
Meteor . logout ();
};
ActiveEntry . reset = function (){
2016-02-02 15:31:01 -05:00
ActiveEntry . errorMessages . set ( 'signInError' , false );
2016-01-25 17:14:42 +01:00
ActiveEntry . errorMessages . set ( 'fullName' , false );
ActiveEntry . errorMessages . set ( 'email' , false );
ActiveEntry . errorMessages . set ( 'confirm' , false );
ActiveEntry . errorMessages . set ( 'password' , false );
};
2016-02-03 14:41:51 -05:00
2016-01-25 17:14:42 +01:00
ActiveEntry . logoIsDisplayed = function (){
var ActiveEntryConfig = Session . get ( 'Photonic.ActiveEntry' );
return ActiveEntryConfig . logo . displayed ;
2016-02-03 14:41:51 -05:00
};