2014-07-08 07:02:26 -04:00
|
|
|
define [
|
|
|
|
"base"
|
2015-04-24 09:33:01 -04:00
|
|
|
"libs/passfield"
|
2014-07-08 07:02:26 -04:00
|
|
|
], (App) ->
|
2017-12-11 07:58:55 -05:00
|
|
|
App.directive "asyncForm", ($http, validateCaptcha) ->
|
2014-07-08 07:02:26 -04:00
|
|
|
return {
|
2015-04-27 11:38:40 -04:00
|
|
|
controller: ['$scope', ($scope) ->
|
|
|
|
@getEmail = () ->
|
|
|
|
return $scope.email
|
|
|
|
return this
|
|
|
|
]
|
2014-07-08 07:02:26 -04:00
|
|
|
link: (scope, element, attrs) ->
|
|
|
|
formName = attrs.asyncForm
|
|
|
|
|
|
|
|
scope[attrs.name].response = response = {}
|
2014-07-11 12:08:19 -04:00
|
|
|
scope[attrs.name].inflight = false
|
2014-07-08 07:02:26 -04:00
|
|
|
|
2017-12-11 07:58:55 -05:00
|
|
|
validateCaptchaIfEnabled = (callback = (response) ->) ->
|
|
|
|
if attrs.captcha?
|
|
|
|
validateCaptcha callback
|
|
|
|
else
|
|
|
|
callback()
|
|
|
|
|
2017-12-11 08:31:16 -05:00
|
|
|
submitRequest = (grecaptchaResponse) ->
|
2014-07-08 07:02:26 -04:00
|
|
|
formData = {}
|
|
|
|
for data in element.serializeArray()
|
|
|
|
formData[data.name] = data.value
|
|
|
|
|
2017-12-11 07:58:55 -05:00
|
|
|
if grecaptchaResponse?
|
|
|
|
formData['g-recaptcha-response'] = grecaptchaResponse
|
|
|
|
|
2014-07-11 12:08:19 -04:00
|
|
|
scope[attrs.name].inflight = true
|
|
|
|
|
2016-11-04 11:44:12 -04:00
|
|
|
# for asyncForm prevent automatic redirect to /login if
|
|
|
|
# authentication fails, we will handle it ourselves
|
2014-07-08 07:02:26 -04:00
|
|
|
$http
|
2016-11-04 11:44:12 -04:00
|
|
|
.post(element.attr('action'), formData, {disableAutoLoginRedirect: true})
|
2017-06-20 11:04:06 -04:00
|
|
|
.then (httpResponse) ->
|
|
|
|
{ data, status, headers, config } = httpResponse
|
2014-07-11 12:08:19 -04:00
|
|
|
scope[attrs.name].inflight = false
|
2014-07-08 07:02:26 -04:00
|
|
|
response.success = true
|
|
|
|
response.error = false
|
|
|
|
|
2017-01-20 08:52:31 -05:00
|
|
|
onSuccessHandler = scope[attrs.onSuccess]
|
|
|
|
if onSuccessHandler
|
2017-06-20 11:04:06 -04:00
|
|
|
onSuccessHandler(httpResponse)
|
2017-01-10 09:46:09 -05:00
|
|
|
return
|
2017-06-20 11:04:06 -04:00
|
|
|
|
2014-07-08 07:02:26 -04:00
|
|
|
if data.redir?
|
|
|
|
ga('send', 'event', formName, 'success')
|
|
|
|
window.location = data.redir
|
|
|
|
else if data.message?
|
|
|
|
response.message = data.message
|
|
|
|
|
|
|
|
if data.message.type == "error"
|
|
|
|
response.success = false
|
|
|
|
response.error = true
|
|
|
|
ga('send', 'event', formName, 'failure', data.message)
|
|
|
|
else
|
|
|
|
ga('send', 'event', formName, 'success')
|
2014-07-11 12:08:19 -04:00
|
|
|
|
2017-06-20 11:04:06 -04:00
|
|
|
.catch (httpResponse) ->
|
|
|
|
{ data, status, headers, config } = httpResponse
|
2014-07-11 12:08:19 -04:00
|
|
|
scope[attrs.name].inflight = false
|
2014-07-08 07:02:26 -04:00
|
|
|
response.success = false
|
|
|
|
response.error = true
|
2017-01-10 09:46:09 -05:00
|
|
|
|
2017-01-20 08:52:31 -05:00
|
|
|
onErrorHandler = scope[attrs.onError]
|
|
|
|
if onErrorHandler
|
2017-06-20 11:04:06 -04:00
|
|
|
onErrorHandler(httpResponse)
|
2017-01-10 09:46:09 -05:00
|
|
|
return
|
|
|
|
|
2018-10-04 05:36:22 -04:00
|
|
|
if status == 400 # Bad Request
|
|
|
|
response.message =
|
|
|
|
text: "Invalid Request. Please correct the data and try again."
|
|
|
|
type: 'error'
|
|
|
|
else if status == 403 # Forbidden
|
2015-02-05 07:57:44 -05:00
|
|
|
response.message =
|
|
|
|
text: "Session error. Please check you have cookies enabled. If the problem persists, try clearing your cache and cookies."
|
|
|
|
type: "error"
|
|
|
|
else
|
|
|
|
response.message =
|
|
|
|
text: data.message?.text or data.message or "Something went wrong talking to the server :(. Please try again."
|
|
|
|
type: 'error'
|
2014-07-08 07:02:26 -04:00
|
|
|
ga('send', 'event', formName, 'failure', data.message)
|
2018-06-19 08:55:34 -04:00
|
|
|
|
|
|
|
submit = () ->
|
|
|
|
validateCaptchaIfEnabled (response) ->
|
|
|
|
submitRequest response
|
|
|
|
|
|
|
|
element.on "submit", (e) ->
|
|
|
|
e.preventDefault()
|
|
|
|
submit()
|
|
|
|
|
|
|
|
if attrs.autoSubmit
|
|
|
|
submit()
|
2014-07-08 07:02:26 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
App.directive "formMessages", () ->
|
|
|
|
return {
|
|
|
|
restrict: "E"
|
|
|
|
template: """
|
|
|
|
<div class="alert" ng-class="{
|
|
|
|
'alert-danger': form.response.message.type == 'error',
|
|
|
|
'alert-success': form.response.message.type != 'error'
|
|
|
|
}" ng-show="!!form.response.message">
|
|
|
|
{{form.response.message.text}}
|
|
|
|
</div>
|
|
|
|
<div ng-transclude></div>
|
|
|
|
"""
|
|
|
|
transclude: true
|
|
|
|
scope: {
|
|
|
|
form: "=for"
|
|
|
|
}
|
|
|
|
|
2014-07-11 12:08:19 -04:00
|
|
|
}
|
2015-04-24 09:33:01 -04:00
|
|
|
|
|
|
|
|
|
|
|
App.directive 'complexPassword', ->
|
|
|
|
require: ['^asyncForm', 'ngModel']
|
|
|
|
|
2015-04-27 11:38:40 -04:00
|
|
|
link: (scope, element, attrs, ctrl) ->
|
2015-04-24 09:33:01 -04:00
|
|
|
|
2015-04-28 11:20:12 -04:00
|
|
|
PassField.Config.blackList = []
|
2015-04-28 12:39:35 -04:00
|
|
|
defaultPasswordOpts =
|
|
|
|
pattern: ""
|
|
|
|
length:
|
2017-07-24 06:06:47 -04:00
|
|
|
min: 6
|
|
|
|
max: 128
|
2015-04-28 12:39:35 -04:00
|
|
|
allowEmpty: false
|
|
|
|
allowAnyChars: false
|
|
|
|
isMasked: true
|
|
|
|
showToggle: false
|
|
|
|
showGenerate: false
|
|
|
|
showTip:false
|
|
|
|
showWarn:false
|
|
|
|
checkMode : PassField.CheckModes.STRICT
|
|
|
|
chars:
|
|
|
|
digits: "1234567890"
|
|
|
|
letters: "abcdefghijklmnopqrstuvwxyz"
|
|
|
|
letters_up: "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
|
|
|
symbols: "@#$%^&*()-_=+[]{};:<>/?!£€.,"
|
|
|
|
|
|
|
|
opts = _.defaults(window.passwordStrengthOptions || {}, defaultPasswordOpts)
|
|
|
|
if opts.length.min == 1
|
|
|
|
opts.acceptRate = 0 #this allows basically anything to be a valid password
|
2015-04-28 12:50:06 -04:00
|
|
|
passField = new PassField.Field("passwordField", opts);
|
2015-04-27 11:38:40 -04:00
|
|
|
|
|
|
|
[asyncFormCtrl, ngModelCtrl] = ctrl
|
|
|
|
|
2015-04-28 11:20:12 -04:00
|
|
|
ngModelCtrl.$parsers.unshift (modelValue) ->
|
2015-04-24 09:33:01 -04:00
|
|
|
isValid = passField.validatePass()
|
2015-04-30 06:59:44 -04:00
|
|
|
email = asyncFormCtrl.getEmail() || window.usersEmail
|
2015-04-28 11:20:12 -04:00
|
|
|
if !isValid
|
|
|
|
scope.complexPasswordErrorMessage = passField.getPassValidationMessage()
|
2015-04-30 06:59:44 -04:00
|
|
|
else if (email? and email != "")
|
2015-04-28 12:39:35 -04:00
|
|
|
startOfEmail = email?.split("@")?[0]
|
2015-04-28 11:20:12 -04:00
|
|
|
if modelValue.indexOf(email) != -1 or modelValue.indexOf(startOfEmail) != -1
|
|
|
|
isValid = false
|
|
|
|
scope.complexPasswordErrorMessage = "Password can not contain email address"
|
2016-09-23 10:44:47 -04:00
|
|
|
if opts.length.max? and modelValue.length == opts.length.max
|
|
|
|
isValid = false
|
2016-10-03 06:33:14 -04:00
|
|
|
scope.complexPasswordErrorMessage = "Maximum password length #{opts.length.max} reached"
|
2017-07-24 06:06:47 -04:00
|
|
|
if opts.length.min? and modelValue.length < opts.length.min
|
|
|
|
isValid = false
|
|
|
|
scope.complexPasswordErrorMessage = "Password too short, minimum #{opts.length.min}"
|
2015-04-28 11:20:12 -04:00
|
|
|
ngModelCtrl.$setValidity('complexPassword', isValid)
|
|
|
|
return modelValue
|