Add access control. (admin, recording and webinterface)
This commit is contained in:
parent
bbe35021b8
commit
f6740b8d17
12 changed files with 196 additions and 65 deletions
2
access.c
2
access.c
|
@ -310,6 +310,8 @@ static const dtable_class_t access_dtc = {
|
|||
.dtc_record_create = access_record_create,
|
||||
.dtc_record_update = access_record_update,
|
||||
.dtc_record_delete = access_record_delete,
|
||||
.dtc_read_access = ACCESS_ADMIN,
|
||||
.dtc_write_access = ACCESS_ADMIN,
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -778,6 +778,8 @@ static const dtable_class_t channel_tags_dtc = {
|
|||
.dtc_record_create = channel_tag_record_create,
|
||||
.dtc_record_update = channel_tag_record_update,
|
||||
.dtc_record_delete = channel_tag_record_delete,
|
||||
.dtc_read_access = ACCESS_ADMIN,
|
||||
.dtc_write_access = ACCESS_ADMIN,
|
||||
};
|
||||
|
||||
|
||||
|
|
2
cwc.c
2
cwc.c
|
@ -1207,6 +1207,8 @@ static const dtable_class_t cwc_dtc = {
|
|||
.dtc_record_create = cwc_entry_create,
|
||||
.dtc_record_update = cwc_entry_update,
|
||||
.dtc_record_delete = cwc_entry_delete,
|
||||
.dtc_read_access = ACCESS_ADMIN,
|
||||
.dtc_write_access = ACCESS_ADMIN,
|
||||
};
|
||||
|
||||
|
||||
|
|
4
dtable.h
4
dtable.h
|
@ -22,6 +22,7 @@
|
|||
#include <libhts/htsmsg.h>
|
||||
#include <libhts/htsbuf.h>
|
||||
|
||||
#include "access.h"
|
||||
|
||||
typedef struct dtable_class {
|
||||
const char *dtc_name;
|
||||
|
@ -37,6 +38,9 @@ typedef struct dtable_class {
|
|||
|
||||
int (*dtc_record_delete)(void *opaque, const char *id);
|
||||
|
||||
int dtc_read_access;
|
||||
int dtc_write_access;
|
||||
|
||||
} dtable_class_t;
|
||||
|
||||
|
||||
|
|
|
@ -322,6 +322,8 @@ static const dtable_class_t autorec_dtc = {
|
|||
.dtc_record_create = autorec_record_create,
|
||||
.dtc_record_update = autorec_record_update,
|
||||
.dtc_record_delete = autorec_record_delete,
|
||||
.dtc_read_access = ACCESS_RECORDER,
|
||||
.dtc_write_access = ACCESS_RECORDER,
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
12
http.c
12
http.c
|
@ -295,6 +295,15 @@ http_redirect(http_connection_t *hc, const char *location)
|
|||
http_send_reply(hc, HTTP_STATUS_FOUND, "text/html", NULL, location, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return non-zero if no access
|
||||
*/
|
||||
int
|
||||
http_access_verify(http_connection_t *hc, int mask)
|
||||
{
|
||||
return access_verify(hc->hc_username, hc->hc_password,
|
||||
(struct sockaddr *)hc->hc_peer, mask);
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute url callback
|
||||
|
@ -306,8 +315,7 @@ static void
|
|||
http_exec(http_connection_t *hc, http_path_t *hp, char *remain)
|
||||
{
|
||||
int err;
|
||||
if(access_verify(hc->hc_username, hc->hc_password,
|
||||
(struct sockaddr *)hc->hc_peer, hp->hp_accessmask)) {
|
||||
if(http_access_verify(hc, hp->hp_accessmask)) {
|
||||
http_error(hc, HTTP_STATUS_UNAUTHORIZED);
|
||||
return;
|
||||
}
|
||||
|
|
2
http.h
2
http.h
|
@ -135,4 +135,6 @@ http_path_t *http_path_add(const char *path, void *opaque,
|
|||
|
||||
void http_server_init(void);
|
||||
|
||||
int http_access_verify(http_connection_t *hc, int mask);
|
||||
|
||||
#endif /* HTTP_H_ */
|
||||
|
|
|
@ -132,6 +132,23 @@ comet_mailbox_create(void)
|
|||
return cmb;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
static void
|
||||
comet_access_update(http_connection_t *hc, comet_mailbox_t *cmb)
|
||||
{
|
||||
htsmsg_t *m = htsmsg_create();
|
||||
|
||||
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));
|
||||
|
||||
if(cmb->cmb_messages == NULL)
|
||||
cmb->cmb_messages = htsmsg_create_array();
|
||||
htsmsg_add_msg(cmb->cmb_messages, NULL, htsmsg_copy(m));
|
||||
}
|
||||
|
||||
/**
|
||||
* Poll callback
|
||||
|
@ -154,9 +171,10 @@ comet_mailbox_poll(http_connection_t *hc, const char *remain, void *opaque)
|
|||
if(!strcmp(cmb->cmb_boxid, cometid))
|
||||
break;
|
||||
|
||||
if(cmb == NULL)
|
||||
if(cmb == NULL) {
|
||||
cmb = comet_mailbox_create();
|
||||
|
||||
comet_access_update(hc, cmb);
|
||||
}
|
||||
time(&reqtime);
|
||||
|
||||
ts.tv_sec = reqtime + 10;
|
||||
|
|
|
@ -170,11 +170,17 @@ extjs_tablemgr(http_connection_t *hc, const char *remain, void *opaque)
|
|||
if(tablename == NULL || (dt = dtable_find(tablename)) == NULL)
|
||||
return 404;
|
||||
|
||||
if(http_access_verify(hc, dt->dt_dtc->dtc_read_access))
|
||||
return HTTP_STATUS_UNAUTHORIZED;
|
||||
|
||||
in = entries != NULL ? htsmsg_json_deserialize(entries) : NULL;
|
||||
|
||||
pthread_mutex_lock(&global_lock);
|
||||
|
||||
if(!strcmp(op, "create")) {
|
||||
if(http_access_verify(hc, dt->dt_dtc->dtc_write_access))
|
||||
goto noaccess;
|
||||
|
||||
out = dtable_record_create(dt);
|
||||
|
||||
} else if(!strcmp(op, "get")) {
|
||||
|
@ -184,12 +190,18 @@ extjs_tablemgr(http_connection_t *hc, const char *remain, void *opaque)
|
|||
htsmsg_add_msg(out, "entries", array);
|
||||
|
||||
} else if(!strcmp(op, "update")) {
|
||||
if(http_access_verify(hc, dt->dt_dtc->dtc_write_access))
|
||||
goto noaccess;
|
||||
|
||||
if(in == NULL)
|
||||
goto bad;
|
||||
|
||||
dtable_record_update_by_array(dt, in);
|
||||
|
||||
} else if(!strcmp(op, "delete")) {
|
||||
if(http_access_verify(hc, dt->dt_dtc->dtc_write_access))
|
||||
goto noaccess;
|
||||
|
||||
if(in == NULL)
|
||||
goto bad;
|
||||
|
||||
|
@ -199,6 +211,10 @@ extjs_tablemgr(http_connection_t *hc, const char *remain, void *opaque)
|
|||
bad:
|
||||
pthread_mutex_unlock(&global_lock);
|
||||
return HTTP_STATUS_BAD_REQUEST;
|
||||
|
||||
noaccess:
|
||||
pthread_mutex_unlock(&global_lock);
|
||||
return HTTP_STATUS_BAD_REQUEST;
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&global_lock);
|
||||
|
@ -324,6 +340,11 @@ extjs_dvbtree(http_connection_t *hc, const char *remain, void *opaque)
|
|||
out = htsmsg_create_array();
|
||||
pthread_mutex_lock(&global_lock);
|
||||
|
||||
if(http_access_verify(hc, ACCESS_ADMIN)) {
|
||||
pthread_mutex_unlock(&global_lock);
|
||||
return HTTP_STATUS_UNAUTHORIZED;
|
||||
}
|
||||
|
||||
if(!strcmp(s, "root")) {
|
||||
/**
|
||||
* List of all adapters
|
||||
|
@ -389,6 +410,11 @@ extjs_dvbnetworks(http_connection_t *hc, const char *remain, void *opaque)
|
|||
|
||||
pthread_mutex_lock(&global_lock);
|
||||
|
||||
if(http_access_verify(hc, ACCESS_ADMIN)) {
|
||||
pthread_mutex_unlock(&global_lock);
|
||||
return HTTP_STATUS_UNAUTHORIZED;
|
||||
}
|
||||
|
||||
if((tda = dvb_adapter_find_by_identifier(a)) == NULL) {
|
||||
pthread_mutex_unlock(&global_lock);
|
||||
return HTTP_STATUS_BAD_REQUEST;
|
||||
|
@ -441,6 +467,11 @@ extjs_dvbadapter(http_connection_t *hc, const char *remain, void *opaque)
|
|||
|
||||
pthread_mutex_lock(&global_lock);
|
||||
|
||||
if(http_access_verify(hc, ACCESS_ADMIN)) {
|
||||
pthread_mutex_unlock(&global_lock);
|
||||
return HTTP_STATUS_UNAUTHORIZED;
|
||||
}
|
||||
|
||||
if(!strcmp(op, "load")) {
|
||||
r = htsmsg_create();
|
||||
htsmsg_add_str(r, "id", tda->tda_identifier);
|
||||
|
@ -613,6 +644,11 @@ extjs_channel(http_connection_t *hc, const char *remain, void *opaque)
|
|||
|
||||
pthread_mutex_lock(&global_lock);
|
||||
|
||||
if(http_access_verify(hc, ACCESS_ADMIN)) {
|
||||
pthread_mutex_unlock(&global_lock);
|
||||
return HTTP_STATUS_UNAUTHORIZED;
|
||||
}
|
||||
|
||||
ch = s ? channel_find_by_identifier(atoi(s)) : NULL;
|
||||
if(ch == NULL) {
|
||||
pthread_mutex_unlock(&global_lock);
|
||||
|
@ -722,6 +758,15 @@ extjs_xmltv(http_connection_t *hc, const char *remain, void *opaque)
|
|||
htsmsg_t *out, *array, *e, *r;
|
||||
const char *s;
|
||||
|
||||
pthread_mutex_lock(&global_lock);
|
||||
|
||||
if(http_access_verify(hc, ACCESS_ADMIN)) {
|
||||
pthread_mutex_unlock(&global_lock);
|
||||
return HTTP_STATUS_UNAUTHORIZED;
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&global_lock);
|
||||
|
||||
if(!strcmp(op, "listChannels")) {
|
||||
|
||||
out = htsmsg_create();
|
||||
|
@ -936,6 +981,11 @@ extjs_dvr(http_connection_t *hc, const char *remain, void *opaque)
|
|||
|
||||
pthread_mutex_lock(&global_lock);
|
||||
|
||||
if(http_access_verify(hc, ACCESS_RECORDER)) {
|
||||
pthread_mutex_unlock(&global_lock);
|
||||
return HTTP_STATUS_UNAUTHORIZED;
|
||||
}
|
||||
|
||||
if(!strcmp(op, "recordEvent")) {
|
||||
s = http_arg_get(&hc->hc_req_args, "eventId");
|
||||
|
||||
|
@ -1047,10 +1097,16 @@ extjs_dvrlist(http_connection_t *hc, const char *remain, void *opaque)
|
|||
else
|
||||
limit = 20; /* XXX */
|
||||
|
||||
pthread_mutex_lock(&global_lock);
|
||||
|
||||
if(http_access_verify(hc, ACCESS_RECORDER)) {
|
||||
pthread_mutex_unlock(&global_lock);
|
||||
return HTTP_STATUS_UNAUTHORIZED;
|
||||
}
|
||||
|
||||
out = htsmsg_create();
|
||||
array = htsmsg_create_array();
|
||||
|
||||
pthread_mutex_lock(&global_lock);
|
||||
|
||||
dvr_query(&dqr);
|
||||
|
||||
|
|
|
@ -1,32 +1,8 @@
|
|||
tvheadend.dvrStore = new Ext.data.JsonStore({
|
||||
root: 'entries',
|
||||
totalProperty: 'totalCount',
|
||||
fields: [
|
||||
{name: 'id'},
|
||||
{name: 'channel'},
|
||||
{name: 'title'},
|
||||
{name: 'description'},
|
||||
{name: 'chicon'},
|
||||
{name: 'start', type: 'date', dateFormat: 'U' /* unix time */},
|
||||
{name: 'end', type: 'date', dateFormat: 'U' /* unix time */},
|
||||
{name: 'status'},
|
||||
{name: 'schedstate'},
|
||||
{name: 'creator'},
|
||||
{name: 'duration'},
|
||||
{name: 'filesize'},
|
||||
{name: 'url'},
|
||||
],
|
||||
url: 'dvrlist',
|
||||
autoLoad: true,
|
||||
id: 'id',
|
||||
remoteSort: true,
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
tvheadend.dvrDetails = function(entry) {
|
||||
|
||||
var content = '';
|
||||
|
@ -196,19 +172,6 @@ tvheadend.dvrlog = function() {
|
|||
/**
|
||||
*
|
||||
*/
|
||||
tvheadend.autorecRecord = Ext.data.Record.create([
|
||||
'enabled','title','channel','tag','creator','contentgrp','comment'
|
||||
]);
|
||||
|
||||
|
||||
tvheadend.autorecStore = new Ext.data.JsonStore({
|
||||
root: 'entries',
|
||||
fields: tvheadend.autorecRecord,
|
||||
url: "tablemgr",
|
||||
autoLoad: true,
|
||||
id: 'id',
|
||||
baseParams: {table: "autorec", op: "get"}
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
|
@ -285,6 +248,46 @@ tvheadend.autoreceditor = function() {
|
|||
*/
|
||||
tvheadend.dvr = function() {
|
||||
|
||||
|
||||
tvheadend.dvrStore = new Ext.data.JsonStore({
|
||||
root: 'entries',
|
||||
totalProperty: 'totalCount',
|
||||
fields: [
|
||||
{name: 'id'},
|
||||
{name: 'channel'},
|
||||
{name: 'title'},
|
||||
{name: 'description'},
|
||||
{name: 'chicon'},
|
||||
{name: 'start', type: 'date', dateFormat: 'U' /* unix time */},
|
||||
{name: 'end', type: 'date', dateFormat: 'U' /* unix time */},
|
||||
{name: 'status'},
|
||||
{name: 'schedstate'},
|
||||
{name: 'creator'},
|
||||
{name: 'duration'},
|
||||
{name: 'filesize'},
|
||||
{name: 'url'},
|
||||
],
|
||||
url: 'dvrlist',
|
||||
autoLoad: true,
|
||||
id: 'id',
|
||||
remoteSort: true,
|
||||
});
|
||||
|
||||
|
||||
tvheadend.autorecRecord = Ext.data.Record.create([
|
||||
'enabled','title','channel','tag','creator','contentgrp','comment'
|
||||
]);
|
||||
|
||||
|
||||
tvheadend.autorecStore = new Ext.data.JsonStore({
|
||||
root: 'entries',
|
||||
fields: tvheadend.autorecRecord,
|
||||
url: "tablemgr",
|
||||
autoLoad: true,
|
||||
id: 'id',
|
||||
baseParams: {table: "autorec", op: "get"}
|
||||
});
|
||||
|
||||
var panel = new Ext.TabPanel({
|
||||
activeTab:0,
|
||||
autoScroll:true,
|
||||
|
@ -293,7 +296,6 @@ tvheadend.dvr = function() {
|
|||
new tvheadend.autoreceditor
|
||||
]
|
||||
});
|
||||
|
||||
return panel;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,40 @@
|
|||
|
||||
|
||||
/**
|
||||
* This function creates top level tabs based on access so users without
|
||||
* access to subsystems won't see them.
|
||||
*
|
||||
* Obviosuly, access is verified in the server too.
|
||||
*/
|
||||
function accessUpdate(o) {
|
||||
|
||||
|
||||
if(o.dvr == true && tvheadend.dvrpanel == null) {
|
||||
tvheadend.dvrpanel = new tvheadend.dvr;
|
||||
tvheadend.rootTabPanel.add(tvheadend.dvrpanel);
|
||||
}
|
||||
|
||||
if(o.admin == true && tvheadend.confpanel == null) {
|
||||
tvheadend.confpanel = new Ext.TabPanel({
|
||||
activeTab:0,
|
||||
autoScroll:true,
|
||||
title: 'Configuration',
|
||||
items: [new tvheadend.chconf,
|
||||
new tvheadend.xmltv,
|
||||
new tvheadend.cteditor,
|
||||
new tvheadend.dvrsettings,
|
||||
new tvheadend.dvb,
|
||||
new tvheadend.acleditor,
|
||||
new tvheadend.cwceditor]
|
||||
});
|
||||
tvheadend.rootTabPanel.add(tvheadend.confpanel);
|
||||
}
|
||||
|
||||
|
||||
tvheadend.rootTabPanel.doLayout();
|
||||
|
||||
console.log(o);
|
||||
}
|
||||
|
||||
/**
|
||||
* Comet interfaces
|
||||
|
@ -14,6 +49,11 @@ tvheadend.comet_poller = function() {
|
|||
var m = response.messages[x];
|
||||
|
||||
switch(m.notificationClass) {
|
||||
|
||||
case 'accessUpdate':
|
||||
accessUpdate(m);
|
||||
break;
|
||||
|
||||
case 'channeltags':
|
||||
if(m.reload != null)
|
||||
tvheadend.channelTags.reload();
|
||||
|
@ -102,17 +142,11 @@ tvheadend.app = function() {
|
|||
// public methods
|
||||
init: function() {
|
||||
|
||||
var confpanel = new Ext.TabPanel({
|
||||
activeTab:0,
|
||||
autoScroll:true,
|
||||
title: 'Configuration',
|
||||
items: [new tvheadend.chconf,
|
||||
new tvheadend.xmltv,
|
||||
new tvheadend.cteditor,
|
||||
new tvheadend.dvrsettings,
|
||||
new tvheadend.dvb,
|
||||
new tvheadend.acleditor,
|
||||
new tvheadend.cwceditor]
|
||||
|
||||
tvheadend.rootTabPanel = new Ext.TabPanel({
|
||||
region:'center',
|
||||
activeTab:0,
|
||||
items:[new tvheadend.epg]
|
||||
});
|
||||
|
||||
var viewport = new Ext.Viewport({
|
||||
|
@ -129,18 +163,11 @@ tvheadend.app = function() {
|
|||
collapsible: true,
|
||||
title:'System log',
|
||||
margins:'0 0 0 0'
|
||||
},new Ext.TabPanel({
|
||||
region:'center',
|
||||
activeTab:0,
|
||||
items:[
|
||||
new tvheadend.epg,
|
||||
new tvheadend.dvr,
|
||||
confpanel
|
||||
]
|
||||
})
|
||||
},tvheadend.rootTabPanel
|
||||
]
|
||||
});
|
||||
|
||||
|
||||
|
||||
new tvheadend.comet_poller;
|
||||
Ext.QuickTips.init();
|
||||
}
|
||||
|
|
|
@ -123,6 +123,12 @@ page_dvrfile(http_connection_t *hc, const char *remain, void *opaque)
|
|||
return 404;
|
||||
|
||||
pthread_mutex_lock(&global_lock);
|
||||
|
||||
if(http_access_verify(hc, ACCESS_RECORDER)) {
|
||||
pthread_mutex_unlock(&global_lock);
|
||||
return HTTP_STATUS_UNAUTHORIZED;
|
||||
}
|
||||
|
||||
de = dvr_entry_find_by_id(atoi(remain));
|
||||
if(de == NULL || de->de_filename == NULL) {
|
||||
pthread_mutex_unlock(&global_lock);
|
||||
|
|
Loading…
Add table
Reference in a new issue