160 lines
5.4 KiB
JavaScript
160 lines
5.4 KiB
JavaScript
|
import bootstrap from "bootstrap.native";
|
||
|
import tpl_login_panel from "./templates/loginpanel.js";
|
||
|
import { Model } from '@converse/skeletor/src/model.js';
|
||
|
import { View } from "@converse/skeletor/src/view";
|
||
|
import { __ } from '../../i18n';
|
||
|
import { _converse, api, converse } from "@converse/headless/core";
|
||
|
|
||
|
const u = converse.env.utils;
|
||
|
const { Strophe } = converse.env;
|
||
|
|
||
|
const REPORTABLE_STATUSES = [
|
||
|
0, // ERROR'
|
||
|
1, // CONNECTING
|
||
|
2, // CONNFAIL
|
||
|
3, // AUTHENTICATING
|
||
|
4, // AUTHFAIL
|
||
|
7, // DISCONNECTING
|
||
|
10 // RECONNECTING
|
||
|
];
|
||
|
|
||
|
const PRETTY_CONNECTION_STATUS = {
|
||
|
0: 'Error',
|
||
|
1: 'Connecting',
|
||
|
2: 'Connection failure',
|
||
|
3: 'Authenticating',
|
||
|
4: 'Authentication failure',
|
||
|
5: 'Connected',
|
||
|
6: 'Disconnected',
|
||
|
7: 'Disconnecting',
|
||
|
8: 'Attached',
|
||
|
9: 'Redirect',
|
||
|
10: 'Reconnecting'
|
||
|
};
|
||
|
|
||
|
const CONNECTION_STATUS_CSS_CLASS = {
|
||
|
'Error': 'error',
|
||
|
'Connecting': 'info',
|
||
|
'Connection failure': 'error',
|
||
|
'Authenticating': 'info',
|
||
|
'Authentication failure': 'error',
|
||
|
'Connected': 'info',
|
||
|
'Disconnected': 'error',
|
||
|
'Disconnecting': 'warn',
|
||
|
'Attached': 'info',
|
||
|
'Redirect': 'info',
|
||
|
'Reconnecting': 'warn'
|
||
|
};
|
||
|
|
||
|
|
||
|
export const LoginPanelModel = Model.extend({
|
||
|
defaults: {
|
||
|
// Passed-by-reference. Fine in this case because there's
|
||
|
// only one such model.
|
||
|
'errors': [],
|
||
|
}
|
||
|
});
|
||
|
|
||
|
|
||
|
export const LoginPanel = View.extend({
|
||
|
tagName: 'div',
|
||
|
id: "converse-login-panel",
|
||
|
className: 'controlbox-pane fade-in row no-gutters',
|
||
|
events: {
|
||
|
'submit form#converse-login': 'authenticate',
|
||
|
'change input': 'validate'
|
||
|
},
|
||
|
|
||
|
initialize () {
|
||
|
this.listenTo(this.model, 'change', this.render)
|
||
|
this.listenTo(_converse.connfeedback, 'change', this.render);
|
||
|
this.render();
|
||
|
},
|
||
|
|
||
|
toHTML () {
|
||
|
const connection_status = _converse.connfeedback.get('connection_status');
|
||
|
let feedback_class, pretty_status;
|
||
|
if (REPORTABLE_STATUSES.includes(connection_status)) {
|
||
|
pretty_status = PRETTY_CONNECTION_STATUS[connection_status];
|
||
|
feedback_class = CONNECTION_STATUS_CSS_CLASS[pretty_status];
|
||
|
}
|
||
|
return tpl_login_panel(
|
||
|
Object.assign(this.model.toJSON(), {
|
||
|
'_converse': _converse,
|
||
|
'ANONYMOUS': _converse.ANONYMOUS,
|
||
|
'EXTERNAL': _converse.EXTERNAL,
|
||
|
'LOGIN': _converse.LOGIN,
|
||
|
'PREBIND': _converse.PREBIND,
|
||
|
'auto_login': api.settings.get('auto_login'),
|
||
|
'authentication': api.settings.get("authentication"),
|
||
|
'connection_status': connection_status,
|
||
|
'conn_feedback_class': feedback_class,
|
||
|
'conn_feedback_subject': pretty_status,
|
||
|
'conn_feedback_message': _converse.connfeedback.get('message'),
|
||
|
'placeholder_username': (api.settings.get('locked_domain') || api.settings.get('default_domain')) &&
|
||
|
__('Username') || __('user@domain'),
|
||
|
'show_trust_checkbox': api.settings.get('allow_user_trust_override')
|
||
|
})
|
||
|
);
|
||
|
},
|
||
|
|
||
|
initPopovers () {
|
||
|
Array.from(this.el.querySelectorAll('[data-title]')).forEach(el => {
|
||
|
new bootstrap.Popover(el, {
|
||
|
'trigger': api.settings.get("view_mode") === 'mobile' && 'click' || 'hover',
|
||
|
'dismissible': api.settings.get("view_mode") === 'mobile' && true || false,
|
||
|
'container': this.el.parentElement.parentElement.parentElement
|
||
|
})
|
||
|
});
|
||
|
},
|
||
|
|
||
|
validate () {
|
||
|
const form = this.el.querySelector('form');
|
||
|
const jid_element = form.querySelector('input[name=jid]');
|
||
|
if (jid_element.value &&
|
||
|
!api.settings.get('locked_domain') &&
|
||
|
!api.settings.get('default_domain') &&
|
||
|
!u.isValidJID(jid_element.value)) {
|
||
|
jid_element.setCustomValidity(__('Please enter a valid XMPP address'));
|
||
|
return false;
|
||
|
}
|
||
|
jid_element.setCustomValidity('');
|
||
|
return true;
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* Authenticate the user based on a form submission event.
|
||
|
* @param { Event } ev
|
||
|
*/
|
||
|
authenticate (ev) {
|
||
|
if (ev && ev.preventDefault) { ev.preventDefault(); }
|
||
|
if (api.settings.get("authentication") === _converse.ANONYMOUS) {
|
||
|
return this.connect(_converse.jid, null);
|
||
|
}
|
||
|
if (!this.validate()) { return; }
|
||
|
|
||
|
const form_data = new FormData(ev.target);
|
||
|
_converse.config.save({'trusted': form_data.get('trusted') && true || false});
|
||
|
|
||
|
let jid = form_data.get('jid');
|
||
|
if (api.settings.get('locked_domain')) {
|
||
|
const last_part = '@' + api.settings.get('locked_domain');
|
||
|
if (jid.endsWith(last_part)) {
|
||
|
jid = jid.substr(0, jid.length - last_part.length);
|
||
|
}
|
||
|
jid = Strophe.escapeNode(jid) + last_part;
|
||
|
} else if (api.settings.get('default_domain') && !jid.includes('@')) {
|
||
|
jid = jid + '@' + api.settings.get('default_domain');
|
||
|
}
|
||
|
this.connect(jid, form_data.get('password'));
|
||
|
},
|
||
|
|
||
|
connect (jid, password) {
|
||
|
if (["converse/login", "converse/register"].includes(_converse.router.history.getFragment())) {
|
||
|
_converse.router.navigate('', {'replace': true});
|
||
|
}
|
||
|
_converse.connection && _converse.connection.reset();
|
||
|
api.user.login(jid, password);
|
||
|
}
|
||
|
});
|