Merge pull request #74 from clems4ever/client-notifications
Notifications to users do not use notifyjs anymore. They are more com…pull/80/head
commit
9403326226
|
@ -162,7 +162,7 @@ module.exports = function (grunt) {
|
|||
grunt.registerTask('docker-restart', ['run:docker-restart']);
|
||||
|
||||
grunt.registerTask('unit-tests', ['run:unit-tests']);
|
||||
grunt.registerTask('integration-tests', ['run:unit-tests']);
|
||||
grunt.registerTask('integration-tests', ['run:integration-tests']);
|
||||
|
||||
grunt.registerTask('test', ['unit-tests']);
|
||||
};
|
||||
|
|
|
@ -88,7 +88,6 @@
|
|||
"jsdom": "^11.0.0",
|
||||
"mocha": "^3.4.2",
|
||||
"mockdate": "^2.0.1",
|
||||
"notifyjs-browser": "^0.4.2",
|
||||
"nyc": "^10.3.2",
|
||||
"power-assert": "^1.4.4",
|
||||
"proxyquire": "^1.8.0",
|
||||
|
|
|
@ -20,3 +20,42 @@ body {
|
|||
font-size: 0.7em;
|
||||
color: #6b6b6b;
|
||||
}
|
||||
|
||||
/* notifications */
|
||||
|
||||
.notification {
|
||||
padding: 10px;
|
||||
border-radius: 6px;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.notification img {
|
||||
width: 24px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.notification i,
|
||||
.notification span {
|
||||
display:table-cell;
|
||||
vertical-align:middle;
|
||||
}
|
||||
|
||||
.info {
|
||||
border: 1px solid #9cb1ff;
|
||||
background-color: rgb(192, 220, 255);
|
||||
}
|
||||
|
||||
.success {
|
||||
border: 1px solid #65ec7c;
|
||||
background-color: rgb(163, 255, 157);
|
||||
}
|
||||
|
||||
.error {
|
||||
border: 1px solid #ffa3a3;
|
||||
background-color: rgb(255, 175, 175);
|
||||
}
|
||||
|
||||
.warning {
|
||||
border: 1px solid #ffd743;
|
||||
background-color: rgb(255, 230, 143);
|
||||
}
|
|
@ -1,12 +1,12 @@
|
|||
|
||||
import FirstFactorValidator = require("./firstfactor/FirstFactorValidator");
|
||||
import FirstFactorValidator = require("./lib/firstfactor/FirstFactorValidator");
|
||||
|
||||
import FirstFactor from "./firstfactor/index";
|
||||
import SecondFactor from "./secondfactor/index";
|
||||
import TOTPRegister from "./totp-register/totp-register";
|
||||
import U2fRegister from "./u2f-register/u2f-register";
|
||||
import ResetPasswordRequest from "./reset-password/reset-password-request";
|
||||
import ResetPasswordForm from "./reset-password/reset-password-form";
|
||||
import FirstFactor from "./lib/firstfactor/index";
|
||||
import SecondFactor from "./lib/secondfactor/index";
|
||||
import TOTPRegister from "./lib/totp-register/totp-register";
|
||||
import U2fRegister from "./lib/u2f-register/u2f-register";
|
||||
import ResetPasswordRequest from "./lib/reset-password/reset-password-request";
|
||||
import ResetPasswordForm from "./lib/reset-password/reset-password-form";
|
||||
import jslogger = require("js-logger");
|
||||
import jQuery = require("jquery");
|
||||
import u2fApi = require("u2f-api");
|
||||
|
@ -14,8 +14,6 @@ import u2fApi = require("u2f-api");
|
|||
jslogger.useDefaults();
|
||||
jslogger.setLevel(jslogger.INFO);
|
||||
|
||||
require("notifyjs-browser")(jQuery);
|
||||
|
||||
export = {
|
||||
firstfactor: function () {
|
||||
FirstFactor(window, jQuery, FirstFactorValidator, jslogger);
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
|
||||
declare type Handler = () => void;
|
||||
|
||||
export interface Handlers {
|
||||
onFadedIn: Handler;
|
||||
onFadedOut: Handler;
|
||||
}
|
||||
|
||||
export interface INotifier {
|
||||
success(msg: string, handlers?: Handlers): void;
|
||||
error(msg: string, handlers?: Handlers): void;
|
||||
warning(msg: string, handlers?: Handlers): void;
|
||||
info(msg: string, handlers?: Handlers): void;
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
|
||||
|
||||
import util = require("util");
|
||||
import { INotifier, Handlers } from "./INotifier";
|
||||
|
||||
export class Notifier implements INotifier {
|
||||
private element: JQuery;
|
||||
|
||||
constructor(selector: string, $: JQueryStatic) {
|
||||
this.element = $(selector);
|
||||
}
|
||||
|
||||
private displayAndFadeout(msg: string, statusType: string, handlers?: Handlers): void {
|
||||
const that = this;
|
||||
const FADE_TIME = 500;
|
||||
const html = util.format('<i><img src="/img/notifications/%s.png" alt="status %s"/></i>\
|
||||
<span>%s</span>', statusType, statusType, msg);
|
||||
this.element.html(html);
|
||||
this.element.addClass(statusType);
|
||||
this.element.fadeIn(FADE_TIME, function() {
|
||||
handlers.onFadedIn();
|
||||
})
|
||||
.delay(4000)
|
||||
.fadeOut(FADE_TIME, function() {
|
||||
that.element.removeClass(statusType);
|
||||
handlers.onFadedOut();
|
||||
});
|
||||
}
|
||||
|
||||
success(msg: string, handlers?: Handlers) {
|
||||
this.displayAndFadeout(msg, "success", handlers);
|
||||
}
|
||||
|
||||
error(msg: string, handlers?: Handlers) {
|
||||
this.displayAndFadeout(msg, "error", handlers);
|
||||
}
|
||||
|
||||
warning(msg: string, handlers?: Handlers) {
|
||||
this.displayAndFadeout(msg, "warning", handlers);
|
||||
}
|
||||
|
||||
info(msg: string, handlers?: Handlers) {
|
||||
this.displayAndFadeout(msg, "info", handlers);
|
||||
}
|
||||
}
|
|
@ -1,8 +1,8 @@
|
|||
|
||||
import BluebirdPromise = require("bluebird");
|
||||
import Endpoints = require("../../server/endpoints");
|
||||
import Endpoints = require("../../../server/endpoints");
|
||||
|
||||
export function validate(username: string, password: string, $: JQueryStatic): BluebirdPromise < void> {
|
||||
export function validate(username: string, password: string, $: JQueryStatic): BluebirdPromise<void> {
|
||||
return new BluebirdPromise<void>(function (resolve, reject) {
|
||||
$.post(Endpoints.FIRST_FACTOR_POST, {
|
||||
username: username,
|
||||
|
@ -12,9 +12,7 @@ export function validate(username: string, password: string, $: JQueryStatic): B
|
|||
resolve();
|
||||
})
|
||||
.fail(function (xhr: JQueryXHR, textStatus: string) {
|
||||
if (xhr.status == 401)
|
||||
reject(new Error("Authetication failed. Please check your credentials."));
|
||||
reject(new Error(textStatus));
|
||||
});
|
||||
});
|
||||
}
|
|
@ -1,10 +1,15 @@
|
|||
import FirstFactorValidator = require("./FirstFactorValidator");
|
||||
import JSLogger = require("js-logger");
|
||||
import UISelectors = require("./UISelectors");
|
||||
import { Notifier } from "../Notifier";
|
||||
|
||||
import Endpoints = require("../../server/endpoints");
|
||||
import Endpoints = require("../../../server/endpoints");
|
||||
|
||||
export default function (window: Window, $: JQueryStatic,
|
||||
firstFactorValidator: typeof FirstFactorValidator, jslogger: typeof JSLogger) {
|
||||
|
||||
const notifier = new Notifier(".notification", $);
|
||||
|
||||
export default function (window: Window, $: JQueryStatic, firstFactorValidator: typeof FirstFactorValidator, jslogger: typeof JSLogger) {
|
||||
function onFormSubmitted() {
|
||||
const username: string = $(UISelectors.USERNAME_FIELD_ID).val();
|
||||
const password: string = $(UISelectors.PASSWORD_FIELD_ID).val();
|
||||
|
@ -27,7 +32,7 @@ export default function (window: Window, $: JQueryStatic, firstFactorValidator:
|
|||
jslogger.debug("First factor failed.");
|
||||
|
||||
$(UISelectors.PASSWORD_FIELD_ID).val("");
|
||||
$.notify("Error during authentication: " + err.message, "error");
|
||||
notifier.error("Authentication failed. Please double check your credentials.");
|
||||
}
|
||||
|
||||
|
|
@ -1,9 +1,12 @@
|
|||
import BluebirdPromise = require("bluebird");
|
||||
|
||||
import Endpoints = require("../../server/endpoints");
|
||||
import Endpoints = require("../../../server/endpoints");
|
||||
import Constants = require("./constants");
|
||||
import { Notifier } from "../Notifier";
|
||||
|
||||
export default function (window: Window, $: JQueryStatic) {
|
||||
const notifier = new Notifier(".notification", $);
|
||||
|
||||
function modifyPassword(newPassword: string) {
|
||||
return new BluebirdPromise(function (resolve, reject) {
|
||||
$.post(Endpoints.RESET_PASSWORD_FORM_POST, {
|
||||
|
@ -23,22 +26,22 @@ export default function (window: Window, $: JQueryStatic) {
|
|||
const password2 = $("#password2").val();
|
||||
|
||||
if (!password1 || !password2) {
|
||||
$.notify("You must enter your new password twice.", "warn");
|
||||
notifier.warning("You must enter your new password twice.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (password1 != password2) {
|
||||
$.notify("The passwords are different", "warn");
|
||||
notifier.warning("The passwords are different.");
|
||||
return false;
|
||||
}
|
||||
|
||||
modifyPassword(password1)
|
||||
.then(function () {
|
||||
$.notify("Your password has been changed. Please login again", "success");
|
||||
notifier.success("Your password has been changed. Please log in again.");
|
||||
window.location.href = Endpoints.FIRST_FACTOR_GET;
|
||||
})
|
||||
.error(function () {
|
||||
$.notify("An error occurred during password change.", "warn");
|
||||
notifier.warning("An error occurred during password reset. Your password has not been changed.");
|
||||
});
|
||||
return false;
|
||||
}
|
|
@ -1,11 +1,14 @@
|
|||
|
||||
import BluebirdPromise = require("bluebird");
|
||||
|
||||
import Endpoints = require("../../server/endpoints");
|
||||
import Endpoints = require("../../../server/endpoints");
|
||||
import Constants = require("./constants");
|
||||
import jslogger = require("js-logger");
|
||||
import { Notifier } from "../Notifier";
|
||||
|
||||
export default function(window: Window, $: JQueryStatic) {
|
||||
const notifier = new Notifier(".notification", $);
|
||||
|
||||
function requestPasswordReset(username: string) {
|
||||
return new BluebirdPromise(function (resolve, reject) {
|
||||
$.get(Endpoints.RESET_PASSWORD_IDENTITY_START_GET, {
|
||||
|
@ -24,19 +27,19 @@ export default function(window: Window, $: JQueryStatic) {
|
|||
const username = $("#username").val();
|
||||
|
||||
if (!username) {
|
||||
$.notify("You must provide your username to reset your password.", "warn");
|
||||
notifier.warning("You must provide your username to reset your password.");
|
||||
return;
|
||||
}
|
||||
|
||||
requestPasswordReset(username)
|
||||
.then(function () {
|
||||
$.notify("An email has been sent. Click on the link to change your password.", "success");
|
||||
notifier.success("An email has been sent to you. Follow the link to change your password.");
|
||||
setTimeout(function () {
|
||||
window.location.replace(Endpoints.FIRST_FACTOR_GET);
|
||||
}, 1000);
|
||||
})
|
||||
.error(function () {
|
||||
$.notify("Are you sure this is your username?", "warn");
|
||||
notifier.warning("Are you sure this is your username?");
|
||||
});
|
||||
return false;
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
|
||||
import BluebirdPromise = require("bluebird");
|
||||
import Endpoints = require("../../server/endpoints");
|
||||
import Endpoints = require("../../../server/endpoints");
|
||||
|
||||
export function validate(token: string, $: JQueryStatic): BluebirdPromise<string> {
|
||||
return new BluebirdPromise<string>(function (resolve, reject) {
|
|
@ -2,8 +2,9 @@
|
|||
import U2fApi = require("u2f-api");
|
||||
import U2f = require("u2f");
|
||||
import BluebirdPromise = require("bluebird");
|
||||
import { SignMessage } from "../../server/lib/routes/secondfactor/u2f/sign_request/SignMessage";
|
||||
import Endpoints = require("../../server/endpoints");
|
||||
import { SignMessage } from "../../../server/lib/routes/secondfactor/u2f/sign_request/SignMessage";
|
||||
import Endpoints = require("../../../server/endpoints");
|
||||
import { INotifier } from "../INotifier";
|
||||
|
||||
function finishU2fAuthentication(responseData: U2fApi.SignResponse, $: JQueryStatic): BluebirdPromise<void> {
|
||||
return new BluebirdPromise<void>(function (resolve, reject) {
|
||||
|
@ -22,11 +23,11 @@ function finishU2fAuthentication(responseData: U2fApi.SignResponse, $: JQuerySta
|
|||
});
|
||||
}
|
||||
|
||||
function startU2fAuthentication($: JQueryStatic, u2fApi: typeof U2fApi): BluebirdPromise<void> {
|
||||
function startU2fAuthentication($: JQueryStatic, notifier: INotifier, u2fApi: typeof U2fApi): BluebirdPromise<void> {
|
||||
return new BluebirdPromise<void>(function (resolve, reject) {
|
||||
$.get(Endpoints.SECOND_FACTOR_U2F_SIGN_REQUEST_GET, {}, undefined, "json")
|
||||
.done(function (signResponse: SignMessage) {
|
||||
$.notify("Please touch the token", "info");
|
||||
notifier.info("Please touch the token");
|
||||
|
||||
const signRequest: U2fApi.SignRequest = {
|
||||
appId: signResponse.request.appId,
|
||||
|
@ -41,7 +42,7 @@ function startU2fAuthentication($: JQueryStatic, u2fApi: typeof U2fApi): Bluebir
|
|||
.then(function (data) {
|
||||
resolve(data);
|
||||
}, function (err) {
|
||||
$.notify("Error when finish U2F transaction", "error");
|
||||
notifier.error("Error when finish U2F transaction");
|
||||
reject(err);
|
||||
});
|
||||
})
|
||||
|
@ -56,6 +57,6 @@ function startU2fAuthentication($: JQueryStatic, u2fApi: typeof U2fApi): Bluebir
|
|||
}
|
||||
|
||||
|
||||
export function validate($: JQueryStatic, u2fApi: typeof U2fApi): BluebirdPromise<void> {
|
||||
return startU2fAuthentication($, u2fApi);
|
||||
export function validate($: JQueryStatic, notifier: INotifier, u2fApi: typeof U2fApi): BluebirdPromise<void> {
|
||||
return startU2fAuthentication($, notifier, u2fApi);
|
||||
}
|
|
@ -4,24 +4,25 @@ import jslogger = require("js-logger");
|
|||
|
||||
import TOTPValidator = require("./TOTPValidator");
|
||||
import U2FValidator = require("./U2FValidator");
|
||||
|
||||
import Endpoints = require("../../server/endpoints");
|
||||
|
||||
import Endpoints = require("../../../server/endpoints");
|
||||
import Constants = require("./constants");
|
||||
import { Notifier } from "../Notifier";
|
||||
|
||||
|
||||
export default function (window: Window, $: JQueryStatic, u2fApi: typeof U2fApi) {
|
||||
const notifierTotp = new Notifier(".notification-totp", $);
|
||||
const notifierU2f = new Notifier(".notification-u2f", $);
|
||||
|
||||
function onAuthenticationSuccess(data: any) {
|
||||
window.location.href = data.redirection_url;
|
||||
}
|
||||
|
||||
|
||||
function onSecondFactorTotpSuccess(data: any) {
|
||||
onAuthenticationSuccess(data);
|
||||
}
|
||||
|
||||
function onSecondFactorTotpFailure(err: Error) {
|
||||
$.notify("Error while validating TOTP token. Cause: " + err.message, "error");
|
||||
notifierTotp.error("Problem with TOTP validation.");
|
||||
}
|
||||
|
||||
function onU2fAuthenticationSuccess(data: any) {
|
||||
|
@ -29,10 +30,9 @@ export default function (window: Window, $: JQueryStatic, u2fApi: typeof U2fApi)
|
|||
}
|
||||
|
||||
function onU2fAuthenticationFailure() {
|
||||
$.notify("Problem with U2F authentication. Did you register before authenticating?", "warn");
|
||||
notifierU2f.error("Problem with U2F validation. Did you register before authenticating?");
|
||||
}
|
||||
|
||||
|
||||
function onTOTPFormSubmitted(): boolean {
|
||||
const token = $(Constants.TOTP_TOKEN_SELECTOR).val();
|
||||
jslogger.debug("TOTP token is %s", token);
|
||||
|
@ -45,7 +45,7 @@ export default function (window: Window, $: JQueryStatic, u2fApi: typeof U2fApi)
|
|||
|
||||
function onU2FFormSubmitted(): boolean {
|
||||
jslogger.debug("Start U2F authentication");
|
||||
U2FValidator.validate($, U2fApi)
|
||||
U2FValidator.validate($, notifierU2f, U2fApi)
|
||||
.then(onU2fAuthenticationSuccess, onU2fAuthenticationFailure);
|
||||
return false;
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
|
||||
import BluebirdPromise = require("bluebird");
|
||||
import U2f = require("u2f");
|
||||
import u2fApi = require("u2f-api");
|
||||
import Endpoints = require("../../../server/endpoints");
|
||||
import jslogger = require("js-logger");
|
||||
import { Notifier } from "../Notifier";
|
||||
|
||||
export default function (window: Window, $: JQueryStatic) {
|
||||
const notifier = new Notifier(".notification", $);
|
||||
|
||||
function checkRegistration(regResponse: u2fApi.RegisterResponse): BluebirdPromise<string> {
|
||||
const registrationData: U2f.RegistrationData = regResponse;
|
||||
|
||||
jslogger.debug("registrationResponse = %s", JSON.stringify(registrationData));
|
||||
|
||||
return new BluebirdPromise<string>(function (resolve, reject) {
|
||||
$.post(Endpoints.SECOND_FACTOR_U2F_REGISTER_POST, registrationData, undefined, "json")
|
||||
.done(function (data) {
|
||||
resolve(data.redirection_url);
|
||||
})
|
||||
.fail(function (xhr, status) {
|
||||
reject();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function requestRegistration(): BluebirdPromise<string> {
|
||||
return new BluebirdPromise<string>(function (resolve, reject) {
|
||||
$.get(Endpoints.SECOND_FACTOR_U2F_REGISTER_REQUEST_GET, {}, undefined, "json")
|
||||
.done(function (registrationRequest: U2f.Request) {
|
||||
jslogger.debug("registrationRequest = %s", JSON.stringify(registrationRequest));
|
||||
|
||||
const registerRequest: u2fApi.RegisterRequest = registrationRequest;
|
||||
u2fApi.register([registerRequest], [], 120)
|
||||
.then(function (res: u2fApi.RegisterResponse) {
|
||||
return checkRegistration(res);
|
||||
})
|
||||
.then(function (redirectionUrl: string) {
|
||||
resolve(redirectionUrl);
|
||||
})
|
||||
.catch(function (err: Error) {
|
||||
reject(err);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function onRegisterFailure(err: Error) {
|
||||
notifier.error("Problem while registering your U2F device.");
|
||||
}
|
||||
|
||||
$(document).ready(function () {
|
||||
requestRegistration()
|
||||
.then(function (redirectionUrl: string) {
|
||||
document.location.href = redirectionUrl;
|
||||
})
|
||||
.error(function (err) {
|
||||
onRegisterFailure(err);
|
||||
});
|
||||
});
|
||||
}
|
|
@ -1,53 +0,0 @@
|
|||
|
||||
import BluebirdPromise = require("bluebird");
|
||||
import U2f = require("u2f");
|
||||
import u2fApi = require("u2f-api");
|
||||
|
||||
import Endpoints = require("../../server/endpoints");
|
||||
import jslogger = require("js-logger");
|
||||
|
||||
export default function(window: Window, $: JQueryStatic) {
|
||||
|
||||
function checkRegistration(regResponse: u2fApi.RegisterResponse, fn: (err: Error) => void) {
|
||||
const registrationData: U2f.RegistrationData = regResponse;
|
||||
|
||||
jslogger.debug("registrationResponse = %s", JSON.stringify(registrationData));
|
||||
|
||||
$.post(Endpoints.SECOND_FACTOR_U2F_REGISTER_POST, registrationData, undefined, "json")
|
||||
.done(function (data) {
|
||||
document.location.href = data.redirection_url;
|
||||
})
|
||||
.fail(function (xhr, status) {
|
||||
$.notify("Error when finish U2F transaction" + status);
|
||||
});
|
||||
}
|
||||
|
||||
function requestRegistration(fn: (err: Error) => void) {
|
||||
$.get(Endpoints.SECOND_FACTOR_U2F_REGISTER_REQUEST_GET, {}, undefined, "json")
|
||||
.done(function (registrationRequest: U2f.Request) {
|
||||
jslogger.debug("registrationRequest = %s", JSON.stringify(registrationRequest));
|
||||
|
||||
const registerRequest: u2fApi.RegisterRequest = registrationRequest;
|
||||
u2fApi.register([registerRequest], [], 120)
|
||||
.then(function (res: u2fApi.RegisterResponse) {
|
||||
checkRegistration(res, fn);
|
||||
})
|
||||
.catch(function (err: Error) {
|
||||
fn(err);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function onRegisterFailure(err: Error) {
|
||||
$.notify("Problem authenticating with U2F.", "error");
|
||||
}
|
||||
|
||||
$(document).ready(function () {
|
||||
requestRegistration(function (err: Error) {
|
||||
if (err) {
|
||||
onRegisterFailure(err);
|
||||
return;
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
|
@ -5,6 +5,7 @@ block form-header
|
|||
<img class="header-img" src="/img/user.png" alt="">
|
||||
|
||||
block content
|
||||
<div class="notification"></div>
|
||||
<form class="form-signin">
|
||||
<div class="form-inputs">
|
||||
<input type="text" class="form-control" id="username" placeholder="Username" required autofocus>
|
||||
|
|
|
@ -9,6 +9,7 @@ block form-header
|
|||
<p>Set your new password and confirm it.</p>
|
||||
|
||||
block content
|
||||
<div class="notification"></div>
|
||||
<form class="form-signin">
|
||||
<div class="form-inputs">
|
||||
<input class="form-control" type="password" name="password1" id="password1" placeholder="New password" required="required" />
|
||||
|
|
|
@ -9,6 +9,7 @@ block form-header
|
|||
<p>After giving your username, you will receive an email to change your password.</p>
|
||||
|
||||
block content
|
||||
<div class="notification"></div>
|
||||
<form class="form-signin">
|
||||
<div class="form-inputs">
|
||||
<input type="text" class="form-control" name="username" id="username" placeholder="Your username" required="required" />
|
||||
|
|
|
@ -5,6 +5,7 @@ block form-header
|
|||
<img class="header-img" src="../img/padlock.png" alt="">
|
||||
|
||||
block content
|
||||
<div class="notification notification-totp"></div>
|
||||
<form class="form-signin totp">
|
||||
<div class="form-inputs">
|
||||
<input type="text" class="form-control" id="token" placeholder="Token" required autofocus>
|
||||
|
@ -14,6 +15,7 @@ block content
|
|||
<span class="clearfix"></span>
|
||||
</form>
|
||||
<hr>
|
||||
<div class="notification notification-u2f"></div>
|
||||
<form class="form-signin u2f">
|
||||
<button class="btn btn-lg btn-primary btn-block u2f-button" type="submit">U2F</button>
|
||||
a(href=u2f_identity_start_endpoint, class="pull-right link register-u2f") Need to register?
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
|
||||
interface JQueryStatic {
|
||||
notify: any;
|
||||
}
|
|
@ -12,7 +12,7 @@ Feature: User validate first factor
|
|||
When I set field "username" to "john"
|
||||
And I set field "password" to "bad-password"
|
||||
And I click on "Sign in"
|
||||
Then I get a notification with message "Error during authentication: Authetication failed. Please check your credentials."
|
||||
Then I get a notification of type "error" with message "Authentication failed. Please double check your credentials."
|
||||
|
||||
Scenario: User succeeds TOTP second factor
|
||||
Given I visit "https://auth.test.local:8080/"
|
||||
|
@ -29,7 +29,7 @@ Feature: User validate first factor
|
|||
And I login with user "john" and password "password"
|
||||
And I use "BADTOKEN" as TOTP token
|
||||
And I click on "TOTP"
|
||||
Then I get a notification with message "Error while validating TOTP token. Cause: error"
|
||||
Then I get a notification of type "error" with message "Problem with TOTP validation."
|
||||
|
||||
Scenario: User logs out
|
||||
Given I visit "https://auth.test.local:8080/"
|
||||
|
|
|
@ -9,7 +9,7 @@ Feature: User is able to reset his password
|
|||
Given I'm on https://auth.test.local:8080/password-reset/request
|
||||
When I set field "username" to "james"
|
||||
And I click on "Reset Password"
|
||||
Then I get a notification with message "An email has been sent. Click on the link to change your password."
|
||||
Then I get a notification of type "success" with message "An email has been sent to you. Follow the link to change your password."
|
||||
|
||||
Scenario: User resets his password
|
||||
Given I'm on https://auth.test.local:8080/password-reset/request
|
||||
|
@ -30,4 +30,4 @@ Feature: User is able to reset his password
|
|||
And I set field "password1" to "newpassword"
|
||||
And I set field "password2" to "newpassword2"
|
||||
And I click on "Reset Password"
|
||||
Then I get a notification with message "The passwords are different"
|
||||
Then I get a notification of type "warning" with message "The passwords are different."
|
||||
|
|
|
@ -14,4 +14,3 @@ Feature: Non authenticated users have no access to certain pages
|
|||
| https://auth.test.local:8080/secondfactor/totp/identity/finish | 403 |
|
||||
| https://auth.test.local:8080/password-reset/identity/start | 403 |
|
||||
| https://auth.test.local:8080/password-reset/identity/finish | 403 |
|
||||
|
|
@ -38,15 +38,6 @@ Cucumber.defineSupportCode(function ({ Given, When, Then }) {
|
|||
return this.useTotpTokenHandle(handle);
|
||||
});
|
||||
|
||||
Then("I get a notification with message {stringInDoubleQuotes}", function (notificationMessage: string) {
|
||||
const that = this;
|
||||
that.driver.sleep(500);
|
||||
return this.driver
|
||||
.findElement(seleniumWebdriver.By.className("notifyjs-corner"))
|
||||
.findElement(seleniumWebdriver.By.tagName("span"))
|
||||
.findElement(seleniumWebdriver.By.xpath("//span[contains(.,'" + notificationMessage + "')]"));
|
||||
});
|
||||
|
||||
When("I visit {stringInDoubleQuotes} and get redirected {stringInDoubleQuotes}", function (url: string, redirectUrl: string) {
|
||||
const that = this;
|
||||
return this.driver.get(url)
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
import Cucumber = require("cucumber");
|
||||
import seleniumWebdriver = require("selenium-webdriver");
|
||||
import Assert = require("assert");
|
||||
import Fs = require("fs");
|
||||
import CustomWorld = require("../support/world");
|
||||
|
||||
Cucumber.defineSupportCode(function ({ Given, When, Then }) {
|
||||
Then("I get a notification of type {stringInDoubleQuotes} with message {stringInDoubleQuotes}",
|
||||
function (notificationType: string, notificationMessage: string) {
|
||||
const that = this;
|
||||
const notificationEl = this.driver.findElement(seleniumWebdriver.By.className("notification"));
|
||||
return this.driver.wait(seleniumWebdriver.until.elementIsVisible(notificationEl), 2000)
|
||||
.then(function () {
|
||||
return notificationEl.getText();
|
||||
})
|
||||
.then(function (txt: string) {
|
||||
Assert.equal(notificationMessage, txt);
|
||||
return notificationEl.getAttribute("class");
|
||||
})
|
||||
.then(function(classes: string) {
|
||||
Assert(classes.indexOf(notificationType) > -1, "Class '" + notificationType + "' not found in notification element.");
|
||||
});
|
||||
});
|
||||
|
||||
});
|
|
@ -3,6 +3,7 @@ import seleniumWebdriver = require("selenium-webdriver");
|
|||
import Cucumber = require("cucumber");
|
||||
import Fs = require("fs");
|
||||
import Speakeasy = require("speakeasy");
|
||||
import Assert = require("assert");
|
||||
|
||||
function CustomWorld() {
|
||||
const that = this;
|
||||
|
@ -26,16 +27,26 @@ function CustomWorld() {
|
|||
};
|
||||
|
||||
this.getErrorPage = function (code: number) {
|
||||
return this.driver
|
||||
.findElement(seleniumWebdriver.By.tagName("h1"))
|
||||
.findElement(seleniumWebdriver.By.xpath("//h1[contains(.,'Error " + code + "')]"));
|
||||
const that = this;
|
||||
return this.driver.wait(seleniumWebdriver.until.elementLocated(seleniumWebdriver.By.tagName("h1")), 2000)
|
||||
.then(function () {
|
||||
return that.driver
|
||||
.findElement(seleniumWebdriver.By.tagName("h1")).getText();
|
||||
})
|
||||
.then(function (txt: string) {
|
||||
Assert.equal(txt, "Error " + code);
|
||||
});
|
||||
};
|
||||
|
||||
this.clickOnButton = function (buttonText: string) {
|
||||
return this.driver
|
||||
const that = this;
|
||||
return this.driver.wait(seleniumWebdriver.until.elementLocated(seleniumWebdriver.By.tagName("button")), 2000)
|
||||
.then(function () {
|
||||
return that.driver
|
||||
.findElement(seleniumWebdriver.By.tagName("button"))
|
||||
.findElement(seleniumWebdriver.By.xpath("//button[contains(.,'" + buttonText + "')]"))
|
||||
.click();
|
||||
});
|
||||
};
|
||||
|
||||
this.loginWithUserPassword = function (username: string, password: string) {
|
||||
|
@ -68,7 +79,7 @@ function CustomWorld() {
|
|||
return that.driver.get(link);
|
||||
})
|
||||
.then(function () {
|
||||
return that.driver.wait(seleniumWebdriver.until.elementLocated(seleniumWebdriver.By.id("secret")), 1000);
|
||||
return that.driver.wait(seleniumWebdriver.until.elementLocated(seleniumWebdriver.By.id("secret")), 5000);
|
||||
})
|
||||
.then(function () {
|
||||
return that.driver.findElement(seleniumWebdriver.By.id("secret")).getText();
|
||||
|
|
|
@ -0,0 +1,71 @@
|
|||
|
||||
import Assert = require("assert");
|
||||
import Sinon = require("sinon");
|
||||
import JQueryMock = require("./mocks/jquery");
|
||||
|
||||
import { Notifier } from "../../../src/client/lib/Notifier";
|
||||
|
||||
describe("test notifier", function() {
|
||||
const SELECTOR = "dummy-selector";
|
||||
const MESSAGE = "This is a message";
|
||||
let jqueryMock: { jquery: JQueryMock.JQueryMock, element: JQueryMock.JQueryElementsMock };
|
||||
|
||||
beforeEach(function() {
|
||||
jqueryMock = JQueryMock.JQueryMock();
|
||||
});
|
||||
|
||||
function should_fade_in_and_out_on_notification(notificationType: string): void {
|
||||
const fadeInReturn = {
|
||||
delay: Sinon.stub()
|
||||
};
|
||||
|
||||
const delayReturn = {
|
||||
fadeOut: Sinon.stub()
|
||||
};
|
||||
|
||||
jqueryMock.element.fadeIn.returns(fadeInReturn);
|
||||
jqueryMock.element.fadeIn.yields();
|
||||
delayReturn.fadeOut.yields();
|
||||
|
||||
fadeInReturn.delay.returns(delayReturn);
|
||||
|
||||
function onFadedInCallback() {
|
||||
Assert(jqueryMock.element.fadeIn.calledOnce);
|
||||
Assert(jqueryMock.element.addClass.calledWith(notificationType));
|
||||
Assert(!jqueryMock.element.removeClass.calledWith(notificationType));
|
||||
}
|
||||
|
||||
function onFadedOutCallback() {
|
||||
Assert(jqueryMock.element.removeClass.calledWith(notificationType));
|
||||
}
|
||||
|
||||
const notifier = new Notifier(SELECTOR, jqueryMock.jquery as any);
|
||||
|
||||
// Call the method by its name... Bad but allows code reuse.
|
||||
(notifier as any)[notificationType](MESSAGE, {
|
||||
onFadedIn: onFadedInCallback,
|
||||
onFadedOut: onFadedOutCallback
|
||||
});
|
||||
|
||||
Assert(jqueryMock.element.fadeIn.calledOnce);
|
||||
Assert(fadeInReturn.delay.calledOnce);
|
||||
Assert(delayReturn.fadeOut.calledOnce);
|
||||
}
|
||||
|
||||
|
||||
it("should fade in and fade out an error message", function() {
|
||||
should_fade_in_and_out_on_notification("error");
|
||||
});
|
||||
|
||||
it("should fade in and fade out an info message", function() {
|
||||
should_fade_in_and_out_on_notification("info");
|
||||
});
|
||||
|
||||
it("should fade in and fade out an warning message", function() {
|
||||
should_fade_in_and_out_on_notification("warning");
|
||||
});
|
||||
|
||||
it("should fade in and fade out an success message", function() {
|
||||
should_fade_in_and_out_on_notification("success");
|
||||
});
|
||||
});
|
|
@ -1,5 +1,5 @@
|
|||
|
||||
import FirstFactorValidator = require("../../../../src/client/firstfactor/FirstFactorValidator");
|
||||
import FirstFactorValidator = require("../../../../src/client/lib/firstfactor/FirstFactorValidator");
|
||||
import JQueryMock = require("../mocks/jquery");
|
||||
import BluebirdPromise = require("bluebird");
|
||||
import Assert = require("assert");
|
||||
|
@ -11,23 +11,23 @@ describe("test FirstFactorValidator", function () {
|
|||
postPromise.done.returns(postPromise);
|
||||
|
||||
const jqueryMock = JQueryMock.JQueryMock();
|
||||
jqueryMock.post.returns(postPromise);
|
||||
jqueryMock.jquery.post.returns(postPromise);
|
||||
|
||||
return FirstFactorValidator.validate("username", "password", jqueryMock as any);
|
||||
return FirstFactorValidator.validate("username", "password", jqueryMock.jquery as any);
|
||||
});
|
||||
|
||||
function should_fail_first_factor_validation(statusCode: number, errorMessage: string) {
|
||||
function should_fail_first_factor_validation(errorMessage: string) {
|
||||
const xhr = {
|
||||
status: statusCode
|
||||
status: 401
|
||||
};
|
||||
const postPromise = JQueryMock.JQueryDeferredMock();
|
||||
postPromise.fail.yields(xhr, errorMessage);
|
||||
postPromise.done.returns(postPromise);
|
||||
|
||||
const jqueryMock = JQueryMock.JQueryMock();
|
||||
jqueryMock.post.returns(postPromise);
|
||||
jqueryMock.jquery.post.returns(postPromise);
|
||||
|
||||
return FirstFactorValidator.validate("username", "password", jqueryMock as any)
|
||||
return FirstFactorValidator.validate("username", "password", jqueryMock.jquery as any)
|
||||
.then(function () {
|
||||
return BluebirdPromise.reject(new Error("First factor validation successfully finished while it should have not."));
|
||||
}, function (err: Error) {
|
||||
|
@ -37,12 +37,8 @@ describe("test FirstFactorValidator", function () {
|
|||
}
|
||||
|
||||
describe("should fail first factor validation", () => {
|
||||
it("should fail with error 500", () => {
|
||||
return should_fail_first_factor_validation(500, "Internal error");
|
||||
});
|
||||
|
||||
it("should fail with error 401", () => {
|
||||
return should_fail_first_factor_validation(401, "Authetication failed. Please check your credentials.");
|
||||
it("should fail with error", () => {
|
||||
return should_fail_first_factor_validation("Authetication failed. Please check your credentials.");
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,87 +0,0 @@
|
|||
|
||||
import Endpoints = require("../../../../src/server/endpoints");
|
||||
import BluebirdPromise = require("bluebird");
|
||||
|
||||
import UISelectors = require("../../../../src/client/firstfactor/UISelectors");
|
||||
import firstfactor from "../../../../src/client/firstfactor/index";
|
||||
import JQueryMock = require("../mocks/jquery");
|
||||
import Assert = require("assert");
|
||||
import sinon = require("sinon");
|
||||
import jslogger = require("js-logger");
|
||||
|
||||
describe("test first factor page", () => {
|
||||
it("should validate first factor", () => {
|
||||
const jQuery = JQueryMock.JQueryMock();
|
||||
const window = {
|
||||
location: {
|
||||
search: "?redirect=https://example.com",
|
||||
href: ""
|
||||
},
|
||||
document: {},
|
||||
};
|
||||
|
||||
const thenSpy = sinon.spy();
|
||||
const FirstFactorValidator: any = {
|
||||
validate: sinon.stub().returns({ then: thenSpy })
|
||||
};
|
||||
|
||||
firstfactor(window as Window, jQuery as any, FirstFactorValidator, jslogger);
|
||||
const readyCallback = jQuery.getCall(0).returnValue.ready.getCall(0).args[0];
|
||||
readyCallback();
|
||||
|
||||
const onSubmitCallback = jQuery.getCall(1).returnValue.on.getCall(0).args[1];
|
||||
jQuery.onCall(2).returns({ val: sinon.stub() });
|
||||
jQuery.onCall(3).returns({ val: sinon.stub() });
|
||||
jQuery.onCall(4).returns({ val: sinon.stub() });
|
||||
jQuery.onCall(5).returns({ val: sinon.stub() });
|
||||
|
||||
onSubmitCallback();
|
||||
|
||||
const successCallback = thenSpy.getCall(0).args[0];
|
||||
successCallback();
|
||||
|
||||
Assert.equal(window.location.href, Endpoints.SECOND_FACTOR_GET);
|
||||
});
|
||||
|
||||
describe("fail to validate first factor", () => {
|
||||
let jQuery: JQueryMock.JQueryMock;
|
||||
beforeEach(function () {
|
||||
jQuery = JQueryMock.JQueryMock();
|
||||
const window = {
|
||||
location: {
|
||||
search: "?redirect=https://example.com",
|
||||
href: ""
|
||||
},
|
||||
document: {},
|
||||
};
|
||||
|
||||
const thenSpy = sinon.spy();
|
||||
const FirstFactorValidator: any = {
|
||||
validate: sinon.stub().returns({ then: thenSpy })
|
||||
};
|
||||
|
||||
firstfactor(window as Window, jQuery as any, FirstFactorValidator, jslogger);
|
||||
const readyCallback = jQuery.getCall(0).returnValue.ready.getCall(0).args[0];
|
||||
readyCallback();
|
||||
|
||||
const onSubmitCallback = jQuery.getCall(1).returnValue.on.getCall(0).args[1];
|
||||
jQuery.onCall(2).returns({ val: sinon.stub() });
|
||||
jQuery.onCall(3).returns({ val: sinon.stub() });
|
||||
jQuery.onCall(4).returns({ val: sinon.stub() });
|
||||
jQuery.onCall(5).returns({ val: sinon.stub() });
|
||||
|
||||
onSubmitCallback();
|
||||
|
||||
const failureCallback = thenSpy.getCall(0).args[1];
|
||||
failureCallback(new Error("Error when validating first factor"));
|
||||
});
|
||||
|
||||
it("should notify the user there is a failure", function () {
|
||||
Assert(jQuery.notify.calledOnce);
|
||||
});
|
||||
|
||||
it("should reset the password field", function () {
|
||||
Assert.equal(jQuery.getCall(4).returnValue.val.getCall(0).args[0], "");
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,33 @@
|
|||
|
||||
import Sinon = require("sinon");
|
||||
import { INotifier } from "../../../../src/client/lib/INotifier";
|
||||
|
||||
export class NotifierStub implements INotifier {
|
||||
successStub: Sinon.SinonStub;
|
||||
errorStub: Sinon.SinonStub;
|
||||
warnStub: Sinon.SinonStub;
|
||||
infoStub: Sinon.SinonStub;
|
||||
|
||||
constructor() {
|
||||
this.successStub = Sinon.stub();
|
||||
this.errorStub = Sinon.stub();
|
||||
this.warnStub = Sinon.stub();
|
||||
this.infoStub = Sinon.stub();
|
||||
}
|
||||
|
||||
success(msg: string) {
|
||||
this.successStub();
|
||||
}
|
||||
|
||||
error(msg: string) {
|
||||
this.errorStub();
|
||||
}
|
||||
|
||||
warning(msg: string) {
|
||||
this.warnStub();
|
||||
}
|
||||
|
||||
info(msg: string) {
|
||||
this.infoStub();
|
||||
}
|
||||
}
|
|
@ -10,17 +10,32 @@ export interface JQueryMock extends sinon.SinonStub {
|
|||
notify: sinon.SinonStub;
|
||||
}
|
||||
|
||||
export interface JQueryElementsMock {
|
||||
ready: sinon.SinonStub;
|
||||
show: sinon.SinonStub;
|
||||
hide: sinon.SinonStub;
|
||||
html: sinon.SinonStub;
|
||||
addClass: sinon.SinonStub;
|
||||
removeClass: sinon.SinonStub;
|
||||
fadeIn: sinon.SinonStub;
|
||||
on: sinon.SinonStub;
|
||||
}
|
||||
|
||||
export interface JQueryDeferredMock {
|
||||
done: sinon.SinonStub;
|
||||
fail: sinon.SinonStub;
|
||||
}
|
||||
|
||||
export function JQueryMock(): JQueryMock {
|
||||
export function JQueryMock(): { jquery: JQueryMock, element: JQueryElementsMock } {
|
||||
const jquery = sinon.stub() as any;
|
||||
const jqueryInstance = {
|
||||
const jqueryInstance: JQueryElementsMock = {
|
||||
ready: sinon.stub(),
|
||||
show: sinon.stub(),
|
||||
hide: sinon.stub(),
|
||||
html: sinon.stub(),
|
||||
addClass: sinon.stub(),
|
||||
removeClass: sinon.stub(),
|
||||
fadeIn: sinon.stub(),
|
||||
on: sinon.stub()
|
||||
};
|
||||
jquery.ajax = sinon.stub();
|
||||
|
@ -28,7 +43,10 @@ export function JQueryMock(): JQueryMock {
|
|||
jquery.post = sinon.stub();
|
||||
jquery.notify = sinon.stub();
|
||||
jquery.returns(jqueryInstance);
|
||||
return jquery;
|
||||
return {
|
||||
jquery: jquery,
|
||||
element: jqueryInstance
|
||||
};
|
||||
}
|
||||
|
||||
export function JQueryDeferredMock(): JQueryDeferredMock {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
|
||||
import TOTPValidator = require("../../../../src/client/secondfactor/TOTPValidator");
|
||||
import TOTPValidator = require("../../../../src/client/lib/secondfactor/TOTPValidator");
|
||||
import JQueryMock = require("../mocks/jquery");
|
||||
import BluebirdPromise = require("bluebird");
|
||||
import Assert = require("assert");
|
||||
|
@ -11,9 +11,9 @@ describe("test TOTPValidator", function () {
|
|||
postPromise.done.returns(postPromise);
|
||||
|
||||
const jqueryMock = JQueryMock.JQueryMock();
|
||||
jqueryMock.ajax.returns(postPromise);
|
||||
jqueryMock.jquery.ajax.returns(postPromise);
|
||||
|
||||
return TOTPValidator.validate("totp_token", jqueryMock as any);
|
||||
return TOTPValidator.validate("totp_token", jqueryMock.jquery as any);
|
||||
});
|
||||
|
||||
it("should fail validating TOTP token", () => {
|
||||
|
@ -24,9 +24,9 @@ describe("test TOTPValidator", function () {
|
|||
postPromise.done.returns(postPromise);
|
||||
|
||||
const jqueryMock = JQueryMock.JQueryMock();
|
||||
jqueryMock.ajax.returns(postPromise);
|
||||
jqueryMock.jquery.ajax.returns(postPromise);
|
||||
|
||||
return TOTPValidator.validate("totp_token", jqueryMock as any)
|
||||
return TOTPValidator.validate("totp_token", jqueryMock.jquery as any)
|
||||
.then(function () {
|
||||
return BluebirdPromise.reject(new Error("Registration successfully finished while it should have not."));
|
||||
}, function (err: Error) {
|
||||
|
|
|
@ -1,12 +1,20 @@
|
|||
|
||||
import U2FValidator = require("../../../../src/client/secondfactor/U2FValidator");
|
||||
import U2FValidator = require("../../../../src/client/lib/secondfactor/U2FValidator");
|
||||
import { INotifier } from "../../../../src/client/lib/INotifier";
|
||||
import JQueryMock = require("../mocks/jquery");
|
||||
import U2FApiMock = require("../mocks/u2f-api");
|
||||
import { SignMessage } from "../../../../src/server/lib/routes/secondfactor/u2f/sign_request/SignMessage";
|
||||
import BluebirdPromise = require("bluebird");
|
||||
import Assert = require("assert");
|
||||
import { NotifierStub } from "../mocks/NotifierStub";
|
||||
|
||||
describe("test U2F validation", function () {
|
||||
let notifier: INotifier;
|
||||
|
||||
beforeEach(function() {
|
||||
notifier = new NotifierStub();
|
||||
});
|
||||
|
||||
it("should validate the U2F device", () => {
|
||||
const signatureRequest: SignMessage = {
|
||||
keyHandle: "keyhandle",
|
||||
|
@ -28,10 +36,10 @@ describe("test U2F validation", function () {
|
|||
postPromise.done.returns(postPromise);
|
||||
|
||||
const jqueryMock = JQueryMock.JQueryMock();
|
||||
jqueryMock.get.returns(getPromise);
|
||||
jqueryMock.ajax.returns(postPromise);
|
||||
jqueryMock.jquery.get.returns(getPromise);
|
||||
jqueryMock.jquery.ajax.returns(postPromise);
|
||||
|
||||
return U2FValidator.validate(jqueryMock as any, u2fClient as any);
|
||||
return U2FValidator.validate(jqueryMock.jquery as any, notifier, u2fClient as any);
|
||||
});
|
||||
|
||||
it("should fail during initial authentication request", () => {
|
||||
|
@ -42,9 +50,9 @@ describe("test U2F validation", function () {
|
|||
getPromise.fail.yields(undefined, "Error while issuing authentication request");
|
||||
|
||||
const jqueryMock = JQueryMock.JQueryMock();
|
||||
jqueryMock.get.returns(getPromise);
|
||||
jqueryMock.jquery.get.returns(getPromise);
|
||||
|
||||
return U2FValidator.validate(jqueryMock as any, u2fClient as any)
|
||||
return U2FValidator.validate(jqueryMock.jquery as any, notifier, u2fClient as any)
|
||||
.catch(function(err: Error) {
|
||||
Assert.equal("Error while issuing authentication request", err.message);
|
||||
return BluebirdPromise.resolve();
|
||||
|
@ -68,9 +76,9 @@ describe("test U2F validation", function () {
|
|||
getPromise.done.returns(getPromise);
|
||||
|
||||
const jqueryMock = JQueryMock.JQueryMock();
|
||||
jqueryMock.get.returns(getPromise);
|
||||
jqueryMock.jquery.get.returns(getPromise);
|
||||
|
||||
return U2FValidator.validate(jqueryMock as any, u2fClient as any)
|
||||
return U2FValidator.validate(jqueryMock.jquery as any, notifier, u2fClient as any)
|
||||
.catch(function(err: Error) {
|
||||
Assert.equal("Device unable to sign", err.message);
|
||||
return BluebirdPromise.resolve();
|
||||
|
@ -98,10 +106,10 @@ describe("test U2F validation", function () {
|
|||
postPromise.done.returns(postPromise);
|
||||
|
||||
const jqueryMock = JQueryMock.JQueryMock();
|
||||
jqueryMock.get.returns(getPromise);
|
||||
jqueryMock.ajax.returns(postPromise);
|
||||
jqueryMock.jquery.get.returns(getPromise);
|
||||
jqueryMock.jquery.ajax.returns(postPromise);
|
||||
|
||||
return U2FValidator.validate(jqueryMock as any, u2fClient as any)
|
||||
return U2FValidator.validate(jqueryMock.jquery as any, notifier, u2fClient as any)
|
||||
.catch(function(err: Error) {
|
||||
Assert.equal("Error while finishing authentication", err.message);
|
||||
return BluebirdPromise.resolve();
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
import sinon = require("sinon");
|
||||
import assert = require("assert");
|
||||
|
||||
import UISelector = require("../../../../src/client/totp-register/ui-selector");
|
||||
import TOTPRegister = require("../../../../src/client/totp-register/totp-register");
|
||||
import UISelector = require("../../../../src/client/lib/totp-register/ui-selector");
|
||||
import TOTPRegister = require("../../../../src/client/lib/totp-register/totp-register");
|
||||
|
||||
describe("test totp-register", function() {
|
||||
let jqueryMock: any;
|
||||
|
|
Loading…
Reference in New Issue