ACL: add per entry (user) stream profile selection
This commit is contained in:
parent
b1edb29e83
commit
599150006b
7 changed files with 123 additions and 16 deletions
68
src/access.c
68
src/access.c
|
@ -171,6 +171,8 @@ access_copy(access_t *src)
|
|||
dst->aa_username = strdup(src->aa_username);
|
||||
if (src->aa_representative)
|
||||
dst->aa_representative = strdup(src->aa_representative);
|
||||
if (src->aa_profiles)
|
||||
dst->aa_profiles = htsmsg_copy(src->aa_profiles);
|
||||
if (src->aa_dvrcfgs)
|
||||
dst->aa_dvrcfgs = htsmsg_copy(src->aa_dvrcfgs);
|
||||
if (src->aa_chtags)
|
||||
|
@ -188,6 +190,7 @@ access_destroy(access_t *a)
|
|||
return;
|
||||
free(a->aa_username);
|
||||
free(a->aa_representative);
|
||||
htsmsg_destroy(a->aa_profiles);
|
||||
htsmsg_destroy(a->aa_dvrcfgs);
|
||||
htsmsg_destroy(a->aa_chtags);
|
||||
free(a);
|
||||
|
@ -335,6 +338,12 @@ access_update(access_t *a, access_entry_t *ae)
|
|||
}
|
||||
}
|
||||
|
||||
if(ae->ae_profile && ae->ae_profile->pro_name[0] != '\0') {
|
||||
if (a->aa_profiles == NULL)
|
||||
a->aa_profiles = htsmsg_create_list();
|
||||
htsmsg_add_str(a->aa_profiles, NULL, idnode_uuid_as_str(&ae->ae_profile->pro_id));
|
||||
}
|
||||
|
||||
if(ae->ae_dvr_config && ae->ae_dvr_config->dvr_config_name[0] != '\0') {
|
||||
if (a->aa_dvrcfgs == NULL)
|
||||
a->aa_dvrcfgs = htsmsg_create_list();
|
||||
|
@ -757,6 +766,8 @@ access_entry_destroy(access_entry_t *ae)
|
|||
TAILQ_REMOVE(&access_entries, ae, ae_link);
|
||||
idnode_unlink(&ae->ae_id);
|
||||
|
||||
if (ae->ae_profile)
|
||||
LIST_REMOVE(ae, ae_profile_link);
|
||||
if (ae->ae_dvr_config)
|
||||
LIST_REMOVE(ae, ae_dvr_config_link);
|
||||
if (ae->ae_chtag)
|
||||
|
@ -775,6 +786,22 @@ access_entry_destroy(access_entry_t *ae)
|
|||
free(ae);
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
void
|
||||
access_destroy_by_profile(profile_t *pro, int delconf)
|
||||
{
|
||||
access_entry_t *ae;
|
||||
|
||||
while ((ae = LIST_FIRST(&pro->pro_accesses)) != NULL) {
|
||||
LIST_REMOVE(ae, ae_profile_link);
|
||||
ae->ae_dvr_config = NULL;
|
||||
if (delconf)
|
||||
access_entry_save(ae);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
|
@ -785,7 +812,7 @@ access_destroy_by_dvr_config(dvr_config_t *cfg, int delconf)
|
|||
|
||||
while ((ae = LIST_FIRST(&cfg->dvr_accesses)) != NULL) {
|
||||
LIST_REMOVE(ae, ae_dvr_config_link);
|
||||
ae->ae_dvr_config = NULL;
|
||||
ae->ae_profile = profile_find_by_name(NULL, NULL);
|
||||
if (delconf)
|
||||
access_entry_save(ae);
|
||||
}
|
||||
|
@ -1026,6 +1053,37 @@ access_entry_dvr_config_get(void *o)
|
|||
return &ret;
|
||||
}
|
||||
|
||||
static int
|
||||
access_entry_profile_set(void *o, const void *v)
|
||||
{
|
||||
access_entry_t *ae = (access_entry_t *)o;
|
||||
profile_t *pro = v ? profile_find_by_uuid(v) : NULL;
|
||||
if (pro == NULL && ae->ae_profile) {
|
||||
LIST_REMOVE(ae, ae_profile_link);
|
||||
ae->ae_profile = NULL;
|
||||
return 1;
|
||||
} else if (ae->ae_profile != pro) {
|
||||
if (ae->ae_profile)
|
||||
LIST_REMOVE(ae, ae_profile_link);
|
||||
ae->ae_profile = pro;
|
||||
LIST_INSERT_HEAD(&pro->pro_accesses, ae, ae_profile_link);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const void *
|
||||
access_entry_profile_get(void *o)
|
||||
{
|
||||
static const char *ret;
|
||||
access_entry_t *ae = (access_entry_t *)o;
|
||||
if (ae->ae_profile)
|
||||
ret = idnode_uuid_as_str(&ae->ae_profile->pro_id);
|
||||
else
|
||||
ret = "";
|
||||
return &ret;
|
||||
}
|
||||
|
||||
const idclass_t access_entry_class = {
|
||||
.ic_class = "access",
|
||||
.ic_caption = "Access",
|
||||
|
@ -1091,6 +1149,14 @@ const idclass_t access_entry_class = {
|
|||
.name = "Advanced Streaming",
|
||||
.off = offsetof(access_entry_t, ae_adv_streaming),
|
||||
},
|
||||
{
|
||||
.type = PT_STR,
|
||||
.id = "profile",
|
||||
.name = "Streaming Profile",
|
||||
.set = access_entry_profile_set,
|
||||
.get = access_entry_profile_get,
|
||||
.list = profile_class_get_list,
|
||||
},
|
||||
{
|
||||
.type = PT_BOOL,
|
||||
.id = "dvr",
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "idnode.h"
|
||||
#include "htsmsg.h"
|
||||
|
||||
struct profile;
|
||||
struct dvr_config;
|
||||
struct channel_tag;
|
||||
|
||||
|
@ -57,6 +58,9 @@ typedef struct access_entry {
|
|||
int ae_streaming;
|
||||
int ae_adv_streaming;
|
||||
|
||||
struct profile *ae_profile;
|
||||
LIST_ENTRY(access_entry) ae_profile_link;
|
||||
|
||||
uint32_t ae_conn_limit;
|
||||
|
||||
int ae_dvr;
|
||||
|
@ -83,6 +87,7 @@ typedef struct access {
|
|||
char *aa_username;
|
||||
char *aa_representative;
|
||||
uint32_t aa_rights;
|
||||
htsmsg_t *aa_profiles;
|
||||
htsmsg_t *aa_dvrcfgs;
|
||||
uint32_t aa_chmin;
|
||||
uint32_t aa_chmax;
|
||||
|
@ -185,6 +190,8 @@ access_entry_save(access_entry_t *ae);
|
|||
*
|
||||
*/
|
||||
void
|
||||
access_destroy_by_profile(struct profile *pro, int delconf);
|
||||
void
|
||||
access_destroy_by_dvr_config(struct dvr_config *cfg, int delconf);
|
||||
void
|
||||
access_destroy_by_channel_tag(struct channel_tag *ct, int delconf);
|
||||
|
|
|
@ -1783,18 +1783,14 @@ htsp_method_subscribe(htsp_connection_t *htsp, htsmsg_t *in)
|
|||
}
|
||||
#endif
|
||||
|
||||
#if ENABLE_LIBAV
|
||||
profile_t *pro;
|
||||
const char *profile_id = htsmsg_get_str(in, "profile");
|
||||
profile_t *pro = NULL;
|
||||
if (profile_id) {
|
||||
pro = profile_find_by_uuid(profile_id);
|
||||
if (pro == NULL)
|
||||
pro = profile_find_by_name(profile_id, "htsp");
|
||||
if (pro)
|
||||
profile_id = pro->pro_name;
|
||||
}
|
||||
|
||||
#else
|
||||
profile_t *pro = profile_find_by_name("htsp", NULL);
|
||||
#endif
|
||||
pro = profile_find_by_list(htsp->htsp_granted_access->aa_profiles, profile_id, "htsp");
|
||||
|
||||
hs->hs_work = profile_work(pro, st, &hs->hs_work_destroy);
|
||||
if (hs->hs_work) {
|
||||
|
|
|
@ -83,6 +83,7 @@ profile_create
|
|||
return NULL;
|
||||
}
|
||||
LIST_INIT(&pro->pro_dvr_configs);
|
||||
LIST_INIT(&pro->pro_accesses);
|
||||
if (idnode_insert(&pro->pro_id, uuid, pb->clazz, 0)) {
|
||||
if (uuid)
|
||||
tvherror("profile", "invalid uuid '%s'", uuid);
|
||||
|
@ -114,6 +115,7 @@ profile_delete(profile_t *pro, int delconf)
|
|||
TAILQ_REMOVE(&profiles, pro, pro_link);
|
||||
idnode_unlink(&pro->pro_id);
|
||||
dvr_config_destroy_by_profile(pro, delconf);
|
||||
access_destroy_by_profile(pro, delconf);
|
||||
if (pro->pro_free)
|
||||
pro->pro_free(pro);
|
||||
free(pro->pro_name);
|
||||
|
@ -308,13 +310,13 @@ profile_find_by_name(const char *name, const char *alt)
|
|||
return profile_default;
|
||||
|
||||
TAILQ_FOREACH(pro, &profiles, pro_link) {
|
||||
if (!strcmp(pro->pro_name, name))
|
||||
if (pro->pro_enabled && !strcmp(pro->pro_name, name))
|
||||
return pro;
|
||||
}
|
||||
|
||||
if (alt) {
|
||||
TAILQ_FOREACH(pro, &profiles, pro_link) {
|
||||
if (!strcmp(pro->pro_name, alt))
|
||||
if (pro->pro_enabled && !strcmp(pro->pro_name, alt))
|
||||
return pro;
|
||||
}
|
||||
}
|
||||
|
@ -322,6 +324,35 @@ profile_find_by_name(const char *name, const char *alt)
|
|||
return profile_default;
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
profile_t *
|
||||
profile_find_by_list(htsmsg_t *uuids, const char *name, const char *alt)
|
||||
{
|
||||
profile_t *pro, *res = NULL;
|
||||
htsmsg_field_t *f;
|
||||
const char *uuid, *uuid2;
|
||||
|
||||
pro = profile_find_by_name(name, alt);
|
||||
uuid = idnode_uuid_as_str(&pro->pro_id);
|
||||
if (uuids) {
|
||||
HTSMSG_FOREACH(f, uuids) {
|
||||
uuid2 = htsmsg_field_get_str(f) ?: "";
|
||||
if (strcmp(uuid, uuid2) == 0)
|
||||
return res;
|
||||
if (!res) {
|
||||
res = profile_find_by_uuid(uuid2);
|
||||
if (!res->pro_enabled)
|
||||
res = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!res)
|
||||
res = profile_find_by_name(NULL, NULL);
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
|
|
|
@ -64,6 +64,7 @@ typedef struct profile {
|
|||
TAILQ_ENTRY(profile) pro_link;
|
||||
|
||||
LIST_HEAD(,dvr_config) pro_dvr_configs;
|
||||
LIST_HEAD(,access_entry) pro_accesses;
|
||||
|
||||
int pro_enabled;
|
||||
int pro_shield;
|
||||
|
@ -104,6 +105,7 @@ void profile_chain_close(profile_chain_t *prch);
|
|||
static inline profile_t *profile_find_by_uuid(const char *uuid)
|
||||
{ return (profile_t*)idnode_find(uuid, &profile_class, NULL); }
|
||||
profile_t *profile_find_by_name(const char *name, const char *alt);
|
||||
profile_t *profile_find_by_list(htsmsg_t *uuids, const char *name, const char *alt);
|
||||
|
||||
htsmsg_t * profile_class_get_list(void *o);
|
||||
|
||||
|
|
|
@ -4,9 +4,10 @@
|
|||
|
||||
tvheadend.acleditor = function(panel, index)
|
||||
{
|
||||
var list = 'enabled,username,password,prefix,streaming,adv_streaming,' +
|
||||
'dvr,dvr_config,webui,admin,conn_limit,channel_min,channel_max,' +
|
||||
'channel_tag,comment';
|
||||
var list = 'enabled,username,password,prefix,' +
|
||||
'streaming,adv_streaming,profile,' +
|
||||
'dvr,dvr_config,webui,admin,conn_limit,' +
|
||||
'channel_min,channel_max,channel_tag,comment';
|
||||
|
||||
tvheadend.idnode_grid(panel, {
|
||||
url: 'api/access/entry',
|
||||
|
|
|
@ -719,7 +719,9 @@ http_stream_service(http_connection_t *hc, service_t *service, int weight)
|
|||
if(http_access_verify(hc, ACCESS_ADVANCED_STREAMING))
|
||||
return HTTP_STATUS_UNAUTHORIZED;
|
||||
|
||||
if(!(pro = profile_find_by_name(http_arg_get(&hc->hc_req_args, "profile"), "service")))
|
||||
if(!(pro = profile_find_by_list(hc->hc_access->aa_profiles,
|
||||
http_arg_get(&hc->hc_req_args, "profile"),
|
||||
"service")))
|
||||
return HTTP_STATUS_NOT_ALLOWED;
|
||||
|
||||
if((tcp_id = http_stream_preop(hc)) == NULL)
|
||||
|
@ -831,7 +833,9 @@ http_stream_channel(http_connection_t *hc, channel_t *ch, int weight)
|
|||
if (http_access_verify_channel(hc, ACCESS_STREAMING, ch, 1))
|
||||
return HTTP_STATUS_UNAUTHORIZED;
|
||||
|
||||
if(!(pro = profile_find_by_name(http_arg_get(&hc->hc_req_args, "profile"), "channel")))
|
||||
if(!(pro = profile_find_by_list(hc->hc_access->aa_profiles,
|
||||
http_arg_get(&hc->hc_req_args, "profile"),
|
||||
"channel")))
|
||||
return HTTP_STATUS_NOT_ALLOWED;
|
||||
|
||||
if((tcp_id = http_stream_preop(hc)) == NULL)
|
||||
|
|
Loading…
Add table
Reference in a new issue