Comparison

plugins/mod_pubsub/pubsub.lib.lua @ 9244:b3b156bd9914

mod_pubsub: Use field mapping in util.dataforms
author Kim Alvefur <zash@zash.se>
date Sat, 01 Sep 2018 03:01:55 +0200
parent 9235:7fbcabee6df1
child 9245:cc32aae5c7da
comparison
equal deleted inserted replaced
9243:a4c52e304e6f 9244:b3b156bd9914
51 name = "FORM_TYPE"; 51 name = "FORM_TYPE";
52 value = "http://jabber.org/protocol/pubsub#node_config"; 52 value = "http://jabber.org/protocol/pubsub#node_config";
53 }; 53 };
54 { 54 {
55 type = "text-single"; 55 type = "text-single";
56 name = "pubsub#title"; 56 name = "title";
57 var = "pubsub#title";
57 label = "Title"; 58 label = "Title";
58 }; 59 };
59 { 60 {
60 type = "text-single"; 61 type = "text-single";
61 name = "pubsub#description"; 62 name = "description";
63 var = "pubsub#description";
62 label = "Description"; 64 label = "Description";
63 }; 65 };
64 { 66 {
65 type = "text-single"; 67 type = "text-single";
66 name = "pubsub#type"; 68 name = "payload_type";
69 var = "pubsub#type";
67 label = "The type of node data, usually specified by the namespace of the payload (if any)"; 70 label = "The type of node data, usually specified by the namespace of the payload (if any)";
68 }; 71 };
69 { 72 {
70 type = "text-single"; 73 type = "text-single";
71 name = "pubsub#max_items"; 74 name = "max_items";
75 var = "pubsub#max_items";
72 label = "Max # of items to persist"; 76 label = "Max # of items to persist";
73 }; 77 };
74 { 78 {
75 type = "boolean"; 79 type = "boolean";
76 name = "pubsub#persist_items"; 80 name = "persist_items";
81 var = "pubsub#persist_items";
77 label = "Persist items to storage"; 82 label = "Persist items to storage";
78 }; 83 };
79 { 84 {
80 type = "list-single"; 85 type = "list-single";
81 name = "pubsub#access_model"; 86 name = "access_model";
87 var = "pubsub#access_model";
82 label = "Specify the subscriber model"; 88 label = "Specify the subscriber model";
83 options = { 89 options = {
84 "authorize", 90 "authorize",
85 "open", 91 "open",
86 "presence", 92 "presence",
88 "whitelist", 94 "whitelist",
89 }; 95 };
90 }; 96 };
91 { 97 {
92 type = "list-single"; 98 type = "list-single";
93 name = "pubsub#publish_model"; 99 name = "publish_model";
100 var = "pubsub#publish_model";
94 label = "Specify the publisher model"; 101 label = "Specify the publisher model";
95 options = { 102 options = {
96 "publishers"; 103 "publishers";
97 "subscribers"; 104 "subscribers";
98 "open"; 105 "open";
100 }; 107 };
101 { 108 {
102 type = "boolean"; 109 type = "boolean";
103 value = true; 110 value = true;
104 label = "Whether to deliver event notifications"; 111 label = "Whether to deliver event notifications";
105 name = "pubsub#deliver_notifications"; 112 name = "notify_items";
113 var = "pubsub#deliver_notifications";
106 }; 114 };
107 { 115 {
108 type = "boolean"; 116 type = "boolean";
109 value = true; 117 value = true;
110 label = "Whether to deliver payloads with event notifications"; 118 label = "Whether to deliver payloads with event notifications";
111 name = "pubsub#deliver_payloads"; 119 name = "include_payload";
120 var = "pubsub#deliver_payloads";
112 }; 121 };
113 { 122 {
114 type = "list-single"; 123 type = "list-single";
115 name = "pubsub#notification_type"; 124 name = "notification_type";
125 var = "pubsub#notification_type";
116 label = "Specify the delivery style for notifications"; 126 label = "Specify the delivery style for notifications";
117 options = { 127 options = {
118 { label = "Messages of type normal", value = "normal" }, 128 { label = "Messages of type normal", value = "normal" },
119 { label = "Messages of type headline", value = "headline", default = true }, 129 { label = "Messages of type headline", value = "headline", default = true },
120 }; 130 };
121 }; 131 };
122 { 132 {
123 type = "boolean"; 133 type = "boolean";
124 label = "Whether to notify subscribers when the node is deleted"; 134 label = "Whether to notify subscribers when the node is deleted";
125 name = "pubsub#notify_delete"; 135 name = "notify_delete";
136 var = "pubsub#notify_delete";
126 value = true; 137 value = true;
127 }; 138 };
128 { 139 {
129 type = "boolean"; 140 type = "boolean";
130 label = "Whether to notify subscribers when items are removed from the node"; 141 label = "Whether to notify subscribers when items are removed from the node";
131 name = "pubsub#notify_retract"; 142 name = "notify_retract";
143 var = "pubsub#notify_retract";
132 value = true; 144 value = true;
133 }; 145 };
134 }; 146 };
135 147
136 local subscribe_options_form = dataform { 148 local subscribe_options_form = dataform {
163 { 175 {
164 type = "text-single"; 176 type = "text-single";
165 name = "pubsub#type"; 177 name = "pubsub#type";
166 }; 178 };
167 }; 179 };
168
169 local config_field_map = {
170 title = "pubsub#title";
171 description = "pubsub#description";
172 payload_type = "pubsub#type";
173 max_items = "pubsub#max_items";
174 persist_items = "pubsub#persist_items";
175 notification_type = "pubsub#notification_type";
176 access_model = "pubsub#access_model";
177 publish_model = "pubsub#publish_model";
178 notify_items = "pubsub#deliver_notifications";
179 notify_delete = "pubsub#notify_delete";
180 notify_retract = "pubsub#notify_retract";
181 include_payload = "pubsub#deliver_payloads";
182 };
183 local reverse_config_field_map = {};
184 for k, v in pairs(config_field_map) do reverse_config_field_map[v] = k; end
185
186 -- util.pubsub is meant to be agnostic to XEP-0060
187 local function config_to_xep0060(node_config)
188 return {
189 ["pubsub#title"] = node_config["title"];
190 ["pubsub#description"] = node_config["description"];
191 ["pubsub#type"] = node_config["payload_type"];
192 ["pubsub#max_items"] = tostring(node_config["max_items"]);
193 ["pubsub#persist_items"] = node_config["persist_items"];
194 ["pubsub#notification_type"] = node_config["notification_type"];
195 ["pubsub#access_model"] = node_config["access_model"];
196 ["pubsub#publish_model"] = node_config["publish_model"];
197 ["pubsub#deliver_notifications"] = node_config["notify_items"];
198 ["pubsub#notify_delete"] = node_config["notify_delete"];
199 ["pubsub#notify_retract"] = node_config["notify_retract"];
200 ["pubsub#deliver_payloads"] = node_config["include_payload"];
201 }
202 end
203
204 local function config_from_xep0060(config, strict)
205 local ret = {};
206 for config_field, config_value in pairs(config) do
207 local mapped_name = reverse_config_field_map[config_field];
208 if mapped_name then
209 -- FIXME: The intention is to add "subtype" support to
210 -- util.dataforms, which will remove the need for this
211 -- ugly hack
212 if mapped_name == "max_items" then
213 config_value = tonumber(config_value);
214 end
215 ret[mapped_name] = config_value;
216 elseif strict and config_field ~= "FORM_TYPE" then
217 return nil, "unknown-field", config_field;
218 end
219 end
220 return ret;
221 end
222 180
223 local service_method_feature_map = { 181 local service_method_feature_map = {
224 add_subscription = { "subscribe", "subscription-options" }; 182 add_subscription = { "subscribe", "subscription-options" };
225 create = { "create-nodes", "instant-nodes", "item-ids", "create-and-configure" }; 183 create = { "create-nodes", "instant-nodes", "item-ids", "create-and-configure" };
226 delete = { "delete-nodes" }; 184 delete = { "delete-nodes" };
443 local form_data, err = node_config_form:data(config_form); 401 local form_data, err = node_config_form:data(config_form);
444 if not form_data then 402 if not form_data then
445 origin.send(st.error_reply(stanza, "modify", "bad-request", err)); 403 origin.send(st.error_reply(stanza, "modify", "bad-request", err));
446 return true; 404 return true;
447 end 405 end
448 config = config_from_xep0060(form_data); 406 config = form_data;
449 end 407 end
450 if node then 408 if node then
451 ok, ret = service:create(node, stanza.attr.from, config); 409 ok, ret = service:create(node, stanza.attr.from, config);
452 if ok then 410 if ok then
453 reply = st.reply(stanza); 411 reply = st.reply(stanza);
596 local required_config = nil; 554 local required_config = nil;
597 local publish_options = stanza.tags[1]:get_child("publish-options"); 555 local publish_options = stanza.tags[1]:get_child("publish-options");
598 if publish_options then 556 if publish_options then
599 -- Ensure that the node configuration matches the values in publish-options 557 -- Ensure that the node configuration matches the values in publish-options
600 local publish_options_form = publish_options:get_child("x", "jabber:x:data"); 558 local publish_options_form = publish_options:get_child("x", "jabber:x:data");
601 required_config = config_from_xep0060(node_config_form:data(publish_options_form), true); 559 required_config = node_config_form:data(publish_options_form);
602 end 560 end
603 local item = publish:get_child("item"); 561 local item = publish:get_child("item");
604 local id = (item and item.attr.id); 562 local id = (item and item.attr.id);
605 if not id then 563 if not id then
606 id = uuid_generate(); 564 id = uuid_generate();
677 if not ok then 635 if not ok then
678 origin.send(pubsub_error_reply(stanza, node_config)); 636 origin.send(pubsub_error_reply(stanza, node_config));
679 return true; 637 return true;
680 end 638 end
681 639
682 local pubsub_form_data = config_to_xep0060(node_config);
683 local reply = st.reply(stanza) 640 local reply = st.reply(stanza)
684 :tag("pubsub", { xmlns = xmlns_pubsub_owner }) 641 :tag("pubsub", { xmlns = xmlns_pubsub_owner })
685 :tag("configure", { node = node }) 642 :tag("configure", { node = node })
686 :add_child(node_config_form:form(pubsub_form_data)); 643 :add_child(node_config_form:form(node_config));
687 origin.send(reply); 644 origin.send(reply);
688 return true; 645 return true;
689 end 646 end
690 647
691 function handlers.owner_set_configure(origin, stanza, config, service) 648 function handlers.owner_set_configure(origin, stanza, config, service)
706 local ok, old_config = service:get_node_config(node, stanza.attr.from); 663 local ok, old_config = service:get_node_config(node, stanza.attr.from);
707 if not ok then 664 if not ok then
708 origin.send(pubsub_error_reply(stanza, old_config)); 665 origin.send(pubsub_error_reply(stanza, old_config));
709 return true; 666 return true;
710 end 667 end
711 local form_data, err = node_config_form:data(config_form, old_config); 668 local new_config, err = node_config_form:data(config_form, old_config);
712 if not form_data then 669 if not new_config then
713 origin.send(st.error_reply(stanza, "modify", "bad-request", err)); 670 origin.send(st.error_reply(stanza, "modify", "bad-request", err));
714 return true; 671 return true;
715 end 672 end
716 local new_config = config_from_xep0060(form_data);
717 local ok, err = service:set_node_config(node, stanza.attr.from, new_config); 673 local ok, err = service:set_node_config(node, stanza.attr.from, new_config);
718 if not ok then 674 if not ok then
719 origin.send(pubsub_error_reply(stanza, err)); 675 origin.send(pubsub_error_reply(stanza, err));
720 return true; 676 return true;
721 end 677 end
722 origin.send(st.reply(stanza)); 678 origin.send(st.reply(stanza));
723 return true; 679 return true;
724 end 680 end
725 681
726 function handlers.owner_get_default(origin, stanza, default, service) -- luacheck: ignore 212/default 682 function handlers.owner_get_default(origin, stanza, default, service) -- luacheck: ignore 212/default
727 local pubsub_form_data = config_to_xep0060(service.node_defaults);
728 local reply = st.reply(stanza) 683 local reply = st.reply(stanza)
729 :tag("pubsub", { xmlns = xmlns_pubsub_owner }) 684 :tag("pubsub", { xmlns = xmlns_pubsub_owner })
730 :tag("default") 685 :tag("default")
731 :add_child(node_config_form:form(pubsub_form_data)); 686 :add_child(node_config_form:form(service.node_defaults));
732 origin.send(reply); 687 origin.send(reply);
733 return true; 688 return true;
734 end 689 end
735 690
736 function handlers.owner_get_affiliations(origin, stanza, affiliations, service) 691 function handlers.owner_get_affiliations(origin, stanza, affiliations, service)