define([
"jquery",
"underscore",
"backbone",
"text!templates/login.html",
"text!templates/alert.html",
"text!templates/loginButtons.html",
"text!templates/loginOptions.html",
"text!templates/login-ldap.html",
], function (
$,
_,
Backbone,
LoginTemplate,
AlertTemplate,
LoginButtonsTemplate,
LoginOptionsTemplate,
LdapLoginTemplate,
) {
"use strict";
/**
* @class SignInView
* @classcategory Views
* @extends Backbone.View
* @screenshot views/SignInView.png
*/
var SignInView = Backbone.View.extend(
/** @lends SignInView.prototype */ {
template: _.template(LoginTemplate),
alertTemplate: _.template(AlertTemplate),
buttonsTemplate: _.template(LoginButtonsTemplate),
loginOptionsTemplate: _.template(LoginOptionsTemplate),
ldapTemplate: _.template(LdapLoginTemplate),
tagName: "div",
className: "sign-in-btns",
ldapError: false,
/* Set to true to only show the LDAP login form */
ldapOnly: false,
/* Set to true if this SignInView is the only thing on the page */
fullPage: false,
/* Set to true if this SignInView is in a modal window */
inPlace: false,
/**
* Set a query string that will be added to the redirect URL
* when the user has logged-in and is returned back to MetacatUI.
* This can be useful to return back to MetacatUI with additional information
* about the state of the app when the user left to sign in.
* @type {string}
* @example
* // This example may tell the view that the register citation modal was open when Sign In was clicked
* "registerCitation=true"
* @default ""
* @since 2.15.0
*/
redirectQueryString: "",
/*A message to display at the top of the view */
topMessage: "",
initialize: function (options) {
if (typeof options !== "undefined") {
this.inPlace = options.inPlace;
this.topMessage = options.topMessage;
this.fullPage = options.fullPage;
this.closeButtons = options.closeButtons === false ? false : true;
}
},
render: function () {
//Don't render a SignIn view if there are no Sign In URLs configured
if (!MetacatUI.appModel.get("signInUrlOrcid")) return this;
var view = this;
if (this.inPlace) {
this.$el.addClass("hidden modal");
this.$el.attr("data-backdrop", "static");
//Add a message to the top, if supplied
if (typeof this.topMessage == "string")
this.$el.prepend(
'<p class="center container">' + this.topMessage + "</p>",
);
else if (typeof this.topMessage == "object")
this.$el.prepend(this.topMessage);
//Copy/paste the contents of the sign-in popup
var signInBtns = $.parseHTML($("#signinPopup").html().trim()),
signInBtnsContainer = $(document.createElement("div"))
.addClass("center container")
.html(signInBtns);
signInBtnsContainer.find("a.signin").each(function (i, a) {
var url = $(a).attr("href");
var redirectUrl = decodeURIComponent(
url.substring(url.indexOf("target=") + 7),
);
var urlWithoutHttp = redirectUrl.substring(
redirectUrl.indexOf("://") + 3,
);
var routeName = urlWithoutHttp.substring(
urlWithoutHttp.indexOf("/") + 1,
);
if (!routeName) {
redirectUrl = redirectUrl + "signinsuccess";
} else if (
_.contains(
MetacatUI.uiRouter.getRouteNames(),
MetacatUI.uiRouter.getRouteName(routeName),
)
) {
redirectUrl =
redirectUrl.substring(0, redirectUrl.indexOf(routeName)) +
"signinsuccess";
}
url =
url.substring(0, url.indexOf("target=") + 7) +
encodeURIComponent(redirectUrl);
$(a).attr("href", url);
});
signInBtnsContainer.find("h1, h2").remove();
this.$el.append(signInBtnsContainer);
//Remove the accordion widget from the ldap login so it gets displayed as a popup window instead
if (this.$("#signinLdap").length) {
this.$("[href='" + "#signinLdap']").addClass("signin");
this.$(".accordion").removeClass("accordion");
}
this.$el.prepend(
$(document.createElement("div"))
.addClass("container")
.prepend(
$(document.createElement("a"))
.text("Close")
.addClass("close")
.prepend(
$(document.createElement("i")).addClass(
"icon icon-on-left icon-remove",
),
),
),
);
//Listen for clicks
this.$("a.signin").on("click", function (e) {
//Get the link URL and change the target to a special route
e.preventDefault();
var link = e.target;
if (link.nodeName != "A") link = $(link).parents("a");
var url = $(link).attr("href");
//Open up a new small window with this URL to allow the user to login
window.open(url, "Login", "height=600,width=700");
//Listen for successful sign-in
window.listenForSignIn = setInterval(function () {
MetacatUI.appUserModel.checkToken(function (data) {
$(".modal.sign-in-btns").modal("hide");
clearInterval(window.listenForSignIn);
if (MetacatUI.appUserModel.get("checked"))
MetacatUI.appUserModel.trigger("change:checked");
else MetacatUI.appUserModel.set("checked", true);
});
}, 750);
});
if (this.closeButtons) {
this.$("a.close").on("click", function (e) {
view.$el.modal("hide");
});
} else {
this.$(".close").remove();
//Create a sign out link
var divider = document.createElement("hr"),
signOutLink = $(document.createElement("a"))
.addClass("error underline")
.text("Sign Out");
//Add the Sign Out link to the view
this.$(".modal-body").append(divider, signOutLink);
//If we're on the EML211EditorView, then show a warning message that unsaved changes will be lost
if (
MetacatUI.appView.currentView &&
MetacatUI.appView.currentView.type == "EML211Editor"
) {
signOutLink.after(
$(document.createElement("p"))
.addClass("error")
.text(" Warning! - All your unsaved changes will be lost."),
);
}
//When the sign out link is clicked, we can just refresh the page.
signOutLink.on("click", function (e) {
window.location.reload();
});
}
} else {
//If it's a full-page sign-in view, then empty it first
if (this.el == MetacatUI.appView.el || this.fullPage) {
this.$el.empty();
var container = document.createElement("div");
container.className = "container login";
if (this.ldapOnly) {
var redirectUrl =
window.location.origin + window.location.pathname;
redirectUrl = redirectUrl.substring(
0,
redirectUrl.lastIndexOf("/"),
);
redirectUrl + "/signinSuccessLdap";
$(container).append(
this.ldapTemplate({
redirectUrl: redirectUrl,
}),
);
this.$el.append(container);
//Hide all the other page elements so it's just the login form
$("#Navbar, #HeaderContainer, #Footer").hide();
} else {
$(container).append(
this.buttonsTemplate({
signInUrl:
MetacatUI.appModel.get("signInUrlOrcid") +
this.getRedirectURL(),
}),
);
this.$el.append(container);
}
} else {
if (this.ldapOnly) {
var redirectUrl = MetacatUI.root + "/signinSuccessLdap";
this.$el.append(
this.ldapTemplate({
redirectUrl: redirectUrl,
}),
);
} else {
let signInUrl =
MetacatUI.appModel.get("signInUrlOrcid") +
this.getRedirectURL();
this.$el.append(
this.buttonsTemplate({
signInUrl: signInUrl,
}),
);
}
}
//Insert the sign in popup screen once
if (!$("#signinPopup").length) {
var target = this.getRedirectURL();
var signInUrl = MetacatUI.appModel.get("signInUrl")
? MetacatUI.appModel.get("signInUrl") + target
: null;
var signInUrlOrcid = MetacatUI.appModel.get("signInUrlOrcid")
? MetacatUI.appModel.get("signInUrlOrcid") + target
: null;
var signInUrlLdap = MetacatUI.appModel.get("signInUrlLdap")
? MetacatUI.appModel.get("signInUrlLdap") + target
: null,
redirectUrl =
window.location.href.indexOf("signinldaperror") > -1
? window.location.href.replace("signinldaperror", "")
: window.location.href;
$("body").append(
this.template({
signInUrl: signInUrl,
signInUrlOrcid: signInUrlOrcid,
signInUrlLdap: signInUrlLdap,
ldapLoginForm: this.ldapTemplate({
redirectUrl: redirectUrl,
}),
currentUrl: window.location.href,
loginOptions: this.loginOptionsTemplate({
signInUrl: signInUrl,
}).trim(),
collapseLdap: !MetacatUI.appUserModel.get("errorLogin"),
redirectUrl: redirectUrl,
}),
);
this.setUpPopup();
}
//If there is an error message in the URL, it means authentication has failed
if (this.ldapError) {
MetacatUI.appUserModel.failedLdapLogin();
this.failedLdapLogin();
}
}
return this;
},
/*
* This function is executed when LDAP authentication fails in the DataONE portal
*/
failedLdapLogin: function () {
//Insert an error message
this.$("form").before(
this.alertTemplate({
classes: "alert-error",
msg: "Incorrect username or password. Please try again.",
}),
);
//If this is a full-page sign-in view, then take the form and insert it into the page
if (this.$el.attr("id") == "Content" && !$("#Content form").length)
$("#Content").html($("#signinLdap").html());
//Else, just show the login in the modal window
else if (!this.ldapOnly) {
$("#signinPopup").modal("show");
}
//Show the LDAP login form
$("#signinLdap").removeClass("collapse").css("height", "auto");
},
setUpPopup: function () {
var view = this;
//Initialize the modal elements
$("#signupPopup, #signinPopup").modal({
show: false,
shown: function () {
//Update the sign-in URLs so we are redirected back to the previous page after authentication
if (MetacatUI.appModel.get("enableCILogonSignIn")) {
$("a.update-sign-in-url").attr(
"href",
MetacatUI.appModel.get("signInUrl") +
encodeURIComponent(window.location.href),
);
}
$("a.update-orcid-sign-in-url").attr(
"href",
MetacatUI.appModel.get("signInUrlOrcid") +
encodeURIComponent(window.location.href),
);
},
});
},
/**
* Constructs and returns a string of the URL that the user should return to when they are done signing in.
* This URL is sent to the DataONE portal service during login, via the `target` URL attribute. The DataONE
* portal will redirect the user back to the `target` URL when sign in is complete.
* @returns {string}
*/
getRedirectURL: function () {
let redirectURL = window.location.href;
if (this.redirectQueryString && this.redirectQueryString.length) {
let currentQueryString = window.location.search;
//If there is a current query string in the window.location, concatenate the
// new query string properly
if (currentQueryString.length) {
//Exclude the "?" character from the query string, if it is there already
if (this.redirectQueryString.charAt(0) == "?") {
this.redirectQueryString = this.redirectQueryString.substring(1);
}
//Add the new query string parameters
redirectURL += "&" + this.redirectQueryString;
} else {
redirectURL += "?" + this.redirectQueryString;
}
}
return redirectURL;
},
onClose: function () {
this.$el.empty();
if (window.listenForSignIn) clearInterval(window.listenForSignIn);
},
},
);
return SignInView;
});