]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
DVR: allow admin to edit owner/creator fields
authorJaroslav Kysela <perex@perex.cz>
Mon, 1 Jun 2015 06:54:56 +0000 (08:54 +0200)
committerJaroslav Kysela <perex@perex.cz>
Mon, 1 Jun 2015 06:54:56 +0000 (08:54 +0200)
src/api/api_dvr.c
src/api/api_idnode.c
src/dvr/dvr_autorec.c
src/dvr/dvr_db.c
src/dvr/dvr_timerec.c
src/idnode.c
src/idnode.h
src/webui/static/app/dvr.js

index ee75c950f785129670eb0594bd477f8848e90fe1..9f0f14debc45d5ab574ee28a7ef3790b145fceb9 100644 (file)
@@ -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
index 32674a0e6362727306ad5c2a418afdf53a85e177..0d0e0a1795815d616d87f00ee536d1dcd8db0a8c 100644 (file)
@@ -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);
     }
index 2939c1520342b869e46be417207d7f168247ac70..f8d5ceb6479dbca286dcc7b812a6a6e22d001337 100644 (file)
@@ -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,
index 20a507e819bc253a54c5b77dda69ee034e9705bb..5ee3ffd437b66620a36c514fc0414b2465ccc2f7 100644 (file)
@@ -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,
index 7e2bfda3b280efd6143b56a60a91edaea8051681..578fdf9b1b5dac23d475fe0569a4a8bd9c540502 100644 (file)
@@ -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,
index 76110ec21e51ec3f3759ffe223c5a993138d5d73..d6011da24d49828b938f8bad9042947d7d536252 100644 (file)
@@ -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;
 }
index add334a2b6e447c7052725efa7b36a63d3887d64..fcd6b6117931d83468c4365a3640c91cf2396a94 100644 (file)
@@ -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);
index d856255c157526ba38aa65006b7de62b76175b3b..810d21891e399e4775e5312f0bb8a5a77a27d927 100644 (file)
@@ -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,