18
18
#include "mgos_service_config.h"
19
19
#include "mgos_rpc.h"
20
20
21
+ #include "common/cs_dbg.h"
21
22
#include "common/mg_str.h"
22
23
#include "mgos_config_util.h"
23
24
#include "mgos_hal.h"
@@ -78,25 +79,6 @@ static void mgos_config_get_handler(struct mg_rpc_request_info *ri,
78
79
(void ) fi ;
79
80
}
80
81
81
- /*
82
- * Called by json_scanf() for the "config" field, and parses all the given
83
- * JSON as sys config
84
- */
85
- static void set_handler (const char * str , int len , void * user_data ) {
86
- struct mgos_config * cfg = (struct mgos_config * ) user_data ;
87
- char * acl_copy = (mgos_sys_config_get_conf_acl () != NULL
88
- ? strdup (mgos_sys_config_get_conf_acl ())
89
- : NULL );
90
- mgos_conf_parse (mg_mk_str_n (str , len ), acl_copy , mgos_config_schema (), cfg );
91
- free (acl_copy );
92
- }
93
-
94
- static void dummy_set_handler (const char * str , int len , void * user_data ) {
95
- (void ) str ;
96
- (void ) len ;
97
- (void ) user_data ;
98
- }
99
-
100
82
static void do_save (struct mg_rpc_request_info * ri ,
101
83
const struct mgos_config * cfg , int level , bool try_once ,
102
84
bool reboot ) {
@@ -136,12 +118,19 @@ static void do_save(struct mg_rpc_request_info *ri,
136
118
static void mgos_config_set_handler (struct mg_rpc_request_info * ri ,
137
119
void * cb_arg , struct mg_rpc_frame_info * fi ,
138
120
struct mg_str args ) {
139
- struct mgos_config * cfg = & mgos_sys_config ;
140
- int level = -1 , save = 1 , try_once = 0 , reboot = 0 , dummy ;
141
- // Parse with dummy config handler first to get other flags.
142
- json_scanf (args .p , args .len , ri -> args_fmt , dummy_set_handler , NULL , & level ,
121
+ int level = -1 ;
122
+ void * cfgp = NULL ;
123
+ struct mgos_config * cfg = NULL ;
124
+ const struct mgos_conf_entry * schema = NULL ;
125
+ struct json_token value = JSON_INVALID_TOKEN ;
126
+ char * key = NULL , * err_msg = NULL ;
127
+ bool save = false, try_once = false, reboot = false, free_config = false;
128
+ json_scanf (args .p , args .len , ri -> args_fmt , & key , & value , & value , & level ,
143
129
& save , & try_once , & reboot );
144
-
130
+ if (value .len == 0 ) {
131
+ mg_rpc_send_errorf (ri , 400 , "%s is required" , "value" );
132
+ goto out ;
133
+ }
145
134
if (level == 0 ) {
146
135
mg_rpc_send_errorf (ri , 400 , "not allowed" );
147
136
goto out ;
@@ -151,13 +140,39 @@ static void mgos_config_set_handler(struct mg_rpc_request_info *ri,
151
140
mg_rpc_send_errorf (ri , 400 , "failed to load config" );
152
141
goto out ;
153
142
}
143
+ free_config = true;
154
144
} else {
155
145
cfg = & mgos_sys_config ;
156
146
level = MGOS_CONFIG_LEVEL_USER ;
157
147
}
158
148
159
- json_scanf (args .p , args .len , ri -> args_fmt , set_handler , cfg , & dummy , & save ,
160
- & try_once , & reboot );
149
+ if (key != NULL ) {
150
+ schema = mgos_conf_find_schema_entry (key , mgos_config_schema ());
151
+ if (schema == NULL ) {
152
+ mg_rpc_send_errorf (ri , 404 , "invalid config key" );
153
+ goto out ;
154
+ }
155
+ cfgp = ((char * ) cfg ) + schema -> offset ;
156
+ } else {
157
+ schema = mgos_config_schema ();
158
+ cfgp = cfg ;
159
+ }
160
+
161
+ /* Include the quotes around the string value. */
162
+ if (value .type == JSON_TYPE_STRING ) {
163
+ value .ptr -- ;
164
+ value .len += 2 ;
165
+ }
166
+ LOG (LL_DEBUG , ("key: '%s' value '%.*s'" , key , (int ) value .len , value .ptr ));
167
+
168
+ /* Note that we always use top-level ACL as it may be
169
+ * more restrictive than on lower levels. */
170
+ if (!mgos_conf_parse_sub_msg (mg_mk_str_n (value .ptr , value .len ), schema ,
171
+ mgos_sys_config_get_conf_acl (), cfgp ,
172
+ & err_msg )) {
173
+ mg_rpc_send_errorf (ri , 400 , "invalid config value: %s" , err_msg );
174
+ goto out ;
175
+ }
161
176
162
177
if (save ) {
163
178
do_save (ri , cfg , level , try_once , reboot );
@@ -166,9 +181,11 @@ static void mgos_config_set_handler(struct mg_rpc_request_info *ri,
166
181
}
167
182
168
183
out :
169
- if (cfg != & mgos_sys_config ) {
184
+ if (free_config ) {
170
185
mgos_conf_free (mgos_config_schema (), cfg );
171
186
}
187
+ free (err_msg );
188
+ free (key );
172
189
(void ) cb_arg ;
173
190
(void ) fi ;
174
191
}
@@ -190,8 +207,9 @@ bool mgos_rpc_service_config_init(void) {
190
207
struct mg_rpc * c = mgos_rpc_get_global ();
191
208
mg_rpc_add_handler (c , "Config.Get" , "{key: %Q, level: %d}" ,
192
209
mgos_config_get_handler , NULL );
210
+ /* value is a synonym for config. */
193
211
mg_rpc_add_handler (c , "Config.Set" ,
194
- "{config: %M , level: %d, "
212
+ "{key: %Q, config: %T, value: %T , level: %d, "
195
213
"save: %B, try_once: %B, reboot: %B}" ,
196
214
mgos_config_set_handler , NULL );
197
215
mg_rpc_add_handler (c , "Config.Save" , "{try_once: %B, reboot: %B}" ,
0 commit comments