From 2c7cc8c453025a4e60a8e896bb31bdd2fa9cd056 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Fri, 12 Sep 2014 16:40:27 +0200 Subject: [PATCH] WEBUI: add the logged user status, allow logout and login Finally! It's here. I was missing it. The login/logout link might need more work to follow the other extjs button look... --- src/http.c | 10 ++-- src/webui/comet.c | 6 ++- src/webui/static/app/ext.css | 18 +++++++ src/webui/static/app/tvheadend.js | 84 ++++++++++++++++++++++++++++++- src/webui/webui.c | 28 +++++++++++ 5 files changed, 140 insertions(+), 6 deletions(-) diff --git a/src/http.c b/src/http.c index 0ad98b6a..15297e69 100644 --- a/src/http.c +++ b/src/http.c @@ -324,9 +324,13 @@ http_error(http_connection_t *hc, int error) "\r\n" "%d %s\r\n" "\r\n" - "

%d %s

\r\n" - "\r\n", - error, errtxt, error, errtxt); + "

%d %s

\r\n", + error, errtxt, error, errtxt); + + if (error == HTTP_STATUS_UNAUTHORIZED) + htsbuf_qprintf(&hc->hc_reply, "

Default Login

"); + + htsbuf_qprintf(&hc->hc_reply, "\r\n"); http_send_reply(hc, error, "text/html", NULL, NULL, 0); } diff --git a/src/webui/comet.c b/src/webui/comet.c index 574a9fa2..f8a2231a 100644 --- a/src/webui/comet.c +++ b/src/webui/comet.c @@ -139,11 +139,13 @@ static void comet_access_update(http_connection_t *hc, comet_mailbox_t *cmb) { htsmsg_t *m = htsmsg_create_map(); + const char *username = hc->hc_access ? (hc->hc_access->aa_username ?: "") : ""; htsmsg_add_str(m, "notificationClass", "accessUpdate"); - htsmsg_add_u32(m, "dvr", !http_access_verify(hc, ACCESS_RECORDER)); - htsmsg_add_u32(m, "admin", !http_access_verify(hc, ACCESS_ADMIN)); + htsmsg_add_str(m, "username", username); + htsmsg_add_u32(m, "dvr", !http_access_verify(hc, ACCESS_RECORDER)); + htsmsg_add_u32(m, "admin", !http_access_verify(hc, ACCESS_ADMIN)); if(cmb->cmb_messages == NULL) cmb->cmb_messages = htsmsg_create_list(); diff --git a/src/webui/static/app/ext.css b/src/webui/static/app/ext.css index 79bb55d4..d9f08263 100644 --- a/src/webui/static/app/ext.css +++ b/src/webui/static/app/ext.css @@ -24,6 +24,24 @@ text-shadow: 0 -2px rgba(0, 0, 0, 0.2); } + +.x-tab-strip li.x-tab-login { + margin-left: 16px; +} + +.x-tab-strip span.x-tab-strip-login { + vertical-align: middle; + white-space: nowrap; + padding:4px 0px; +} + +.x-tab-strip span.x-tab-strip-login-cmd { + vertical-align: middle; + cursor:pointer; + padding:4px 0; + float: right; +} + .x-tree-col { float: left; overflow: hidden; diff --git a/src/webui/static/app/tvheadend.js b/src/webui/static/app/tvheadend.js index 85b05008..2b0cc48a 100644 --- a/src/webui/static/app/tvheadend.js +++ b/src/webui/static/app/tvheadend.js @@ -311,6 +311,8 @@ function accessUpdate(o) { if (!tvheadend.capabilities) return; + tvheadend.rootTabPanel.setLogin(o.username); + if (o.dvr == true && tvheadend.dvrpanel == null) { tvheadend.dvrpanel = tvheadend.dvr(); tvheadend.rootTabPanel.add(tvheadend.dvrpanel); @@ -463,6 +465,86 @@ tvheadend.log = function(msg, style) { e.scrollIntoView('systemlog'); }; +/** + * + */ +tvheadend.RootTabPanel = Ext.extend(Ext.TabPanel, { + + onRender: function(ct, position) { + tvheadend.RootTabPanel.superclass.onRender.call(this, ct, position); + + /* Create login components */ + var before = this.strip.dom.childNodes[this.strip.dom.childNodes.length-1]; + + if (!this.loginTpl) { + var tt = new Ext.Template( + '
  • ', + '
  • ' + ); + tt.disableFormats = true; + tt.compile(); + tvheadend.RootTabPanel.prototype.loginTpl = tt; + } + var item = new Ext.Component(); + var p = this.getTemplateArgs(item); + var before = this.strip.dom.childNodes[this.strip.dom.childNodes.length-1]; + item.tabEl = this.loginTpl.insertBefore(before, p); + this.loginItem = item; + + if (!this.loginCmdTpl) { + var tt = new Ext.Template( + '
  • ', + '
  • ' + ); + tt.disableFormats = true; + tt.compile(); + tvheadend.RootTabPanel.prototype.loginCmdTpl = tt; + } + var item = new Ext.Component(); + var p = this.getTemplateArgs(item); + var el = this.loginCmdTpl.insertBefore(before, p); + item.tabEl = Ext.get(el); + item.tabEl.select('a').on('click', this.onLoginCmdClicked, this, {preventDefault: true}); + this.loginCmdItem = item; + + this.on('beforetabchange', function(tp, p) { + if (p == this.loginItem || p == this.loginCmdItem) + return false; + }); + + this.setLogin(''); + }, + + getComponent: function(comp) { + if (comp === this.loginItem.id || comp == this.loginItem) + return this.loginItem; + if (comp === this.loginCmdItem.id || comp == this.loginCmdItem) + return this.loginCmdItem; + return tvheadend.RootTabPanel.superclass.getComponent.call(this, comp); + }, + + setLogin: function(login) { + this.login = login; + if (login) { + text = 'Logged in as ' + login + ''; + cmd = '(logout)'; + } else { + text = 'No verified access'; + cmd = '(login)'; + } + var el = this.loginItem.tabEl; + var fly = Ext.fly(this.loginItem.tabEl); + var t = fly.child('span.x-tab-strip-login', true); + Ext.fly(this.loginItem.tabEl).child('span.x-tab-strip-login', true).innerHTML = text; + Ext.fly(this.loginCmdItem.tabEl).child('span.x-tab-strip-login-cmd', true).innerHTML = cmd; + }, + + onLoginCmdClicked: function(e) { + window.location.href = this.login ? 'logout' : 'login'; + } + +}); + /** * */ @@ -484,7 +566,7 @@ tvheadend.app = function() { html: '' }); - tvheadend.rootTabPanel = new Ext.TabPanel({ + tvheadend.rootTabPanel = new tvheadend.RootTabPanel({ region: 'center', activeTab: 0, items: [tvheadend.epg()] diff --git a/src/webui/webui.c b/src/webui/webui.c index 82234845..e6c2c0b5 100644 --- a/src/webui/webui.c +++ b/src/webui/webui.c @@ -163,6 +163,32 @@ page_root2(http_connection_t *hc, const char *remain, void *opaque) return 0; } +static int +page_login(http_connection_t *hc, const char *remain, void *opaque) +{ + if (hc->hc_access != NULL && + hc->hc_access->aa_username != NULL && + hc->hc_access->aa_username != '\0') { + http_redirect(hc, "/", &hc->hc_req_args); + return 0; + } else { + return HTTP_STATUS_UNAUTHORIZED; + } +} + +static int +page_logout(http_connection_t *hc, const char *remain, void *opaque) +{ + if (hc->hc_access == NULL || + hc->hc_access->aa_username == NULL || + hc->hc_access->aa_username == '\0') { + http_redirect(hc, "/", &hc->hc_req_args); + return 0; + } else { + return HTTP_STATUS_UNAUTHORIZED; + } +} + /** * Static download of a file from the filesystem */ @@ -1303,6 +1329,8 @@ webui_init(int xspf) http_path_add("", NULL, page_root2, ACCESS_WEB_INTERFACE); http_path_add("/", NULL, page_root, ACCESS_WEB_INTERFACE); + http_path_add("/login", NULL, page_login, ACCESS_WEB_INTERFACE); + http_path_add("/logout", NULL, page_logout, ACCESS_WEB_INTERFACE); http_path_add_modify("/play", NULL, page_play, ACCESS_WEB_INTERFACE, page_play_path_modify); http_path_add("/dvrfile", NULL, page_dvrfile, ACCESS_WEB_INTERFACE);