From ad7326ea506c68d679e99e9e4634d9e337bd5ab8 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 1 Jun 2015 08:54:56 +0200 Subject: [PATCH] DVR: allow admin to edit owner/creator fields --- src/api/api_dvr.c | 4 +++- src/api/api_idnode.c | 26 ++++++++++++++++++++++---- src/dvr/dvr_autorec.c | 14 ++++++++++++-- src/dvr/dvr_db.c | 18 ++++++++++++++---- src/dvr/dvr_timerec.c | 14 ++++++++++++-- src/idnode.c | 17 +++++++++++++---- src/idnode.h | 4 ++++ src/webui/static/app/dvr.js | 3 ++- 8 files changed, 82 insertions(+), 18 deletions(-) diff --git a/src/api/api_dvr.c b/src/api/api_dvr.c index ee75c950f..9f0f14deb 100644 --- a/src/api/api_dvr.c +++ b/src/api/api_dvr.c @@ -33,8 +33,10 @@ api_dvr_config_grid dvr_config_t *cfg; LIST_FOREACH(cfg, &dvrconfigs, config_link) - if (!idnode_perm((idnode_t *)cfg, perm, NULL)) + if (!idnode_perm((idnode_t *)cfg, perm, NULL)) { idnode_set_add(ins, (idnode_t*)cfg, &conf->filter); + idnode_perm_unset((idnode_t *)cfg); + } } static int diff --git a/src/api/api_idnode.c b/src/api/api_idnode.c index 32674a0e6..0d0e0a179 100644 --- a/src/api/api_idnode.c +++ b/src/api/api_idnode.c @@ -122,6 +122,7 @@ api_idnode_grid htsmsg_t *list, *e; htsmsg_t *flist = api_idnode_flist_conf(args, "list"); api_idnode_grid_conf_t conf = { 0 }; + idnode_t *in; idnode_set_t ins = { 0 }; api_idnode_grid_callback_t cb = opaque; @@ -141,7 +142,10 @@ api_idnode_grid for (i = conf.start; i < ins.is_count && conf.limit != 0; i++) { e = htsmsg_create_map(); htsmsg_add_str(e, "uuid", idnode_uuid_as_str(ins.is_array[i])); - idnode_read0(ins.is_array[i], e, flist, 0); + in = ins.is_array[i]; + idnode_perm_set(in, perm); + idnode_read0(in, e, flist, 0); + idnode_perm_unset(in); htsmsg_add_msg(list, NULL, e); if (conf.limit > 0) conf.limit--; } @@ -200,9 +204,11 @@ api_idnode_load_by_class e = idnode_serialize0(in, flist, 0); htsmsg_destroy(flist); } - + if (e) htsmsg_add_msg(l, NULL, e); + + idnode_perm_unset(in); } free(is->is_array); free(is); @@ -267,6 +273,7 @@ api_idnode_load htsmsg_add_msg(m, "meta", idclass_serialize0(in->in_class, flist, 0)); htsmsg_add_msg(l, NULL, m); count++; + idnode_perm_unset(in); } if (count) @@ -285,6 +292,7 @@ api_idnode_load if (meta > 0) htsmsg_add_msg(m, "meta", idclass_serialize0(in->in_class, flist, 0)); htsmsg_add_msg(l, NULL, m); + idnode_perm_unset(in); } } } @@ -331,6 +339,7 @@ api_idnode_save goto exit; } idnode_update(in, msg); + idnode_perm_unset(in); err = 0; /* Multiple */ @@ -350,6 +359,7 @@ api_idnode_save } count++; idnode_update(in, conf); + idnode_perm_unset(in); } if (count) err = 0; @@ -399,7 +409,10 @@ api_idnode_tree /* Root node */ if (isroot && node) { - htsmsg_t *m = idnode_serialize(node); + htsmsg_t *m; + idnode_perm_set(node, perm); + m = idnode_serialize(node); + idnode_perm_unset(node); htsmsg_add_u32(m, "leaf", idnode_is_leaf(node)); htsmsg_add_msg(*resp, NULL, m); @@ -410,7 +423,11 @@ api_idnode_tree int i; idnode_set_sort_by_title(v); for(i = 0; i < v->is_count; i++) { - htsmsg_t *m = idnode_serialize(v->is_array[i]); + idnode_t *in = v->is_array[i]; + htsmsg_t *m; + idnode_perm_set(in, perm); + m = idnode_serialize(v->is_array[i]); + idnode_perm_unset(in); htsmsg_add_u32(m, "leaf", idnode_is_leaf(v->is_array[i])); htsmsg_add_msg(*resp, NULL, m); } @@ -498,6 +515,7 @@ api_idnode_handler err = EPERM; } else { handler(perm, in); + idnode_perm_unset(in); } htsmsg_destroy(msg); } diff --git a/src/dvr/dvr_autorec.c b/src/dvr/dvr_autorec.c index 2939c1520..f8d5ceb64 100644 --- a/src/dvr/dvr_autorec.c +++ b/src/dvr/dvr_autorec.c @@ -881,6 +881,16 @@ dvr_autorec_entry_class_dedup_list ( void *o ) return strtab2htsmsg(tab); } +static uint32_t +dvr_autorec_entry_class_owner_opts(void *o) +{ + dvr_autorec_entry_t *dae = (dvr_autorec_entry_t *)o; + if (dae && dae->dae_id.in_access && + !access_verify2(dae->dae_id.in_access, ACCESS_ADMIN)) + return 0; + return PO_RDONLY; +} + const idclass_t dvr_autorec_entry_class = { .ic_class = "dvrautorec", .ic_caption = "DVR Auto-Record Entry", @@ -1065,14 +1075,14 @@ const idclass_t dvr_autorec_entry_class = { .id = "owner", .name = "Owner", .off = offsetof(dvr_autorec_entry_t, dae_owner), - .opts = PO_RDONLY, + .get_opts = dvr_autorec_entry_class_owner_opts, }, { .type = PT_STR, .id = "creator", .name = "Creator", .off = offsetof(dvr_autorec_entry_t, dae_creator), - .opts = PO_RDONLY, + .get_opts = dvr_autorec_entry_class_owner_opts, }, { .type = PT_STR, diff --git a/src/dvr/dvr_db.c b/src/dvr/dvr_db.c index 20a507e81..5ee3ffd43 100644 --- a/src/dvr/dvr_db.c +++ b/src/dvr/dvr_db.c @@ -1389,6 +1389,16 @@ dvr_entry_class_start_opts(void *o) return 0; } +static uint32_t +dvr_entry_class_owner_opts(void *o) +{ + dvr_entry_t *de = (dvr_entry_t *)o; + if (de && de->de_id.in_access && + !access_verify2(de->de_id.in_access, ACCESS_ADMIN)) + return 0; + return PO_RDONLY; +} + static uint32_t dvr_entry_class_start_extra_opts(void *o) { @@ -1977,7 +1987,7 @@ const idclass_t dvr_entry_class = { .set = dvr_entry_class_start_extra_set, .list = dvr_entry_class_extra_list, .get_opts = dvr_entry_class_start_extra_opts, - .opts = PO_DURATION | PO_SORTKEY, + .opts = PO_SORTKEY, }, { .type = PT_TIME, @@ -1999,7 +2009,7 @@ const idclass_t dvr_entry_class = { .name = "Extra Stop Time", .off = offsetof(dvr_entry_t, de_stop_extra), .list = dvr_entry_class_extra_list, - .opts = PO_DURATION | PO_SORTKEY, + .opts = PO_SORTKEY, }, { .type = PT_TIME, @@ -2127,14 +2137,14 @@ const idclass_t dvr_entry_class = { .id = "owner", .name = "Owner", .off = offsetof(dvr_entry_t, de_owner), - .opts = PO_RDONLY, + .get_opts = dvr_entry_class_owner_opts, }, { .type = PT_STR, .id = "creator", .name = "Creator", .off = offsetof(dvr_entry_t, de_creator), - .opts = PO_RDONLY, + .get_opts = dvr_entry_class_owner_opts, }, { .type = PT_STR, diff --git a/src/dvr/dvr_timerec.c b/src/dvr/dvr_timerec.c index 7e2bfda3b..578fdf9b1 100644 --- a/src/dvr/dvr_timerec.c +++ b/src/dvr/dvr_timerec.c @@ -532,6 +532,16 @@ dvr_timerec_entry_class_weekdays_rend(void *o) return dvr_autorec_entry_class_weekdays_rend(dte->dte_weekdays); } +static uint32_t +dvr_timerec_entry_class_owner_opts(void *o) +{ + dvr_timerec_entry_t *dte = (dvr_timerec_entry_t *)o; + if (dte && dte->dte_id.in_access && + !access_verify2(dte->dte_id.in_access, ACCESS_ADMIN)) + return 0; + return PO_RDONLY; +} + const idclass_t dvr_timerec_entry_class = { .ic_class = "dvrtimerec", .ic_caption = "DVR Time-Record Entry", @@ -635,14 +645,14 @@ const idclass_t dvr_timerec_entry_class = { .id = "owner", .name = "Owner", .off = offsetof(dvr_timerec_entry_t, dte_creator), - .opts = PO_RDONLY, + .get_opts = dvr_timerec_entry_class_owner_opts, }, { .type = PT_STR, .id = "creator", .name = "Creator", .off = offsetof(dvr_timerec_entry_t, dte_creator), - .opts = PO_RDONLY, + .get_opts = dvr_timerec_entry_class_owner_opts, }, { .type = PT_STR, diff --git a/src/idnode.c b/src/idnode.c index 76110ec21..d6011da24 100644 --- a/src/idnode.c +++ b/src/idnode.c @@ -559,13 +559,22 @@ int idnode_perm(idnode_t *self, struct access *a, htsmsg_t *msg_to_write) { const idclass_t *ic = self->in_class; + int r; while (ic) { if (ic->ic_perm) - return self->in_class->ic_perm(self, a, msg_to_write); - if (ic->ic_perm_def) - return access_verify2(a, self->in_class->ic_perm_def); - ic = ic->ic_super; + r = self->in_class->ic_perm(self, a, msg_to_write); + else if (ic->ic_perm_def) + r = access_verify2(a, self->in_class->ic_perm_def); + else { + ic = ic->ic_super; + continue; + } + if (!r) { + self->in_access = a; + return 0; + } + return r; } return 0; } diff --git a/src/idnode.h b/src/idnode.h index add334a2b..fcd6b6117 100644 --- a/src/idnode.h +++ b/src/idnode.h @@ -87,6 +87,8 @@ struct idnode { RB_ENTRY(idnode) in_domain_link; ///< Root class link (domain) idnodes_rb_t *in_domain; ///< Domain nodes const idclass_t *in_class; ///< Class definition + struct access *in_access; ///< Actual permissions + }; /* @@ -178,6 +180,8 @@ int idnode_write0 (idnode_t *self, htsmsg_t *m, int optmask, int dosave); #define idnode_update(in, m) idnode_write0(in, m, PO_RDONLY | PO_WRONCE, 1) int idnode_perm(idnode_t *self, struct access *a, htsmsg_t *msg_to_write); +static inline void idnode_perm_set(idnode_t *self, struct access *a) { self->in_access = a; } +static inline void idnode_perm_unset(idnode_t *self) { self->in_access = NULL; } const char *idnode_get_str (idnode_t *self, const char *key ); int idnode_get_u32 (idnode_t *self, const char *key, uint32_t *u32); diff --git a/src/webui/static/app/dvr.js b/src/webui/static/app/dvr.js index d856255c1..810d21891 100644 --- a/src/webui/static/app/dvr.js +++ b/src/webui/static/app/dvr.js @@ -156,6 +156,7 @@ tvheadend.dvr_upcoming = function(panel, index) { var actions = tvheadend.dvrRowActions(); var list = 'disp_title,start,start_extra,stop,stop_extra,' + 'channel,config_name,comment'; + var elist = tvheadend.accessUpdate.admin ? list + ',owner,creator' : list; var abortButton = { name: 'abort', @@ -217,7 +218,7 @@ tvheadend.dvr_upcoming = function(panel, index) { }, edit: { params: { - list: list + list: elist } }, del: true, -- 2.47.2