Add access control. (admin, recording and webinterface)

This commit is contained in:
Andreas Öman 2008-09-25 16:38:55 +00:00
parent bbe35021b8
commit f6740b8d17
12 changed files with 196 additions and 65 deletions

View file

@ -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,
};
/**

View file

@ -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
View file

@ -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,
};

View file

@ -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;

View file

@ -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
View file

@ -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
View file

@ -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_ */

View file

@ -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;

View file

@ -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);

View file

@ -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;
}

View file

@ -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();
}

View file

@ -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);