mirror of
https://github.com/gristlabs/grist-core.git
synced 2024-10-27 20:44:07 +00:00
130 lines
4.3 KiB
JavaScript
130 lines
4.3 KiB
JavaScript
|
/* global window */
|
||
|
|
||
|
|
||
|
// External dependencies
|
||
|
const Promise = require('bluebird');
|
||
|
const ko = require('knockout');
|
||
|
|
||
|
// Grist client libs
|
||
|
const dispose = require('../lib/dispose');
|
||
|
const ProfileForm = require('./ProfileForm');
|
||
|
|
||
|
/**
|
||
|
* Login - Handles dom and settings for the login box.
|
||
|
* @param {app} app - The app instance.
|
||
|
*/
|
||
|
function Login(app) {
|
||
|
this.app = app;
|
||
|
this.comm = this.app.comm;
|
||
|
|
||
|
// When logged in, an object containing user profile properties.
|
||
|
this._profile = ko.observable();
|
||
|
this.isLoggedIn = ko.observable(false);
|
||
|
this.emailObs = this.autoDispose(ko.computed(() => ((this._profile() && this._profile().email) || '')));
|
||
|
this.nameObs = this.autoDispose(ko.computed(() => ((this._profile() && this._profile().name) || '')));
|
||
|
this.buttonText = this.autoDispose(ko.computed(() =>
|
||
|
this.isLoggedIn() ? this.emailObs() : 'Log in'));
|
||
|
|
||
|
// Instantialized with createLoginForm() and createProfileForm()
|
||
|
this.profileForm = null;
|
||
|
}
|
||
|
dispose.makeDisposable(Login);
|
||
|
|
||
|
/**
|
||
|
* Returns the current profile object.
|
||
|
*/
|
||
|
Login.prototype.getProfile = function() {
|
||
|
return this._profile();
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Opens the Cognito login form in a new browser window to allow the user to log in.
|
||
|
* The login tokens are sent back to the server to which this client belongs.
|
||
|
*/
|
||
|
Login.prototype.login = function() {
|
||
|
if (window.isRunningUnderElectron) {
|
||
|
// Under electron, we open the login URL (it opens in a user's default browser).
|
||
|
// With null for redirectUrl, it will close automatically when login completes.
|
||
|
return this.comm.getLoginUrl(null)
|
||
|
.then((loginUrl) => window.open(loginUrl));
|
||
|
} else {
|
||
|
// In hosted / dev version, we redirect to the login URL, and it will redirect back to the
|
||
|
// starting URL when login completes.
|
||
|
return this.comm.getLoginUrl(window.location.href)
|
||
|
.then((loginUrl) => { window.location.href = loginUrl; });
|
||
|
}
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Tells the server to log out, and also opens a new window to the logout URL to get Cognito to
|
||
|
* clear its cookies. The new window will hit our page which will close the window automatically.
|
||
|
*/
|
||
|
Login.prototype.logout = function() {
|
||
|
// We both log out the server, and for hosted version, visit a logout URL to clear AWS cookies.
|
||
|
if (window.isRunningUnderElectron) {
|
||
|
// Under electron, only clear the server state. Don't open the user's default browser
|
||
|
// to clear cookies there because it serves dubious purpose and is annoying to the user.
|
||
|
return this.comm.logout(null);
|
||
|
} else {
|
||
|
// In hosted / dev version, we redirect to the logout URL, which will clear cookies and
|
||
|
// redirect back to the starting URL when logout completes.
|
||
|
return this.comm.logout(window.location.href)
|
||
|
.then((logoutUrl) => { window.location.href = logoutUrl; });
|
||
|
}
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Retrieves the updated user profile from DynamoDB and creates the profile form.
|
||
|
* Also sends the fetched user profile to the server to keep it up to date.
|
||
|
*/
|
||
|
Login.prototype.createProfileForm = function() {
|
||
|
// ProfileForm disposes itself, no need to handle disposal.
|
||
|
this.profileForm = ProfileForm.create(this);
|
||
|
};
|
||
|
|
||
|
// Called when the user logs out in this or another tab.
|
||
|
Login.prototype.onLogout = function() {
|
||
|
this._profile(null);
|
||
|
this.isLoggedIn(false);
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Update the internally-stored profile given a profile object from the server.
|
||
|
*/
|
||
|
Login.prototype.updateProfileFromServer = function(profileObj) {
|
||
|
this._profile(profileObj);
|
||
|
this.isLoggedIn(Boolean(this._profile.peek()));
|
||
|
};
|
||
|
|
||
|
Login.prototype.setProfileItem = function(key, val) {
|
||
|
return this.comm.updateProfile({[key]: val});
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Returns an array of tableIds in the basket of the current document. If the current
|
||
|
* document has no basket, an empty array is returned.
|
||
|
*/
|
||
|
Login.prototype.getBasketTables = function(docComm) {
|
||
|
return docComm.getBasketTables();
|
||
|
};
|
||
|
|
||
|
// Execute func if the user is logged in. Otherwise, prompt the user to log in
|
||
|
// and then execute the function. Attempts refresh if the token is expired.
|
||
|
Login.prototype.tryWithLogin = function(func) {
|
||
|
return Promise.try(() => {
|
||
|
if (!this.isLoggedIn()) {
|
||
|
return this.login();
|
||
|
}
|
||
|
})
|
||
|
.then(() => func())
|
||
|
.catch(err => {
|
||
|
if (err.code === 'LoginClosedError') {
|
||
|
console.log("Login#tryWithLogin", err);
|
||
|
} else {
|
||
|
throw err;
|
||
|
}
|
||
|
});
|
||
|
};
|
||
|
|
||
|
module.exports = Login;
|