Fossil SCM
/json/user/save now returns the same as user/get, returning the new/updated state.
Commit
bf5de622e86f3fe731a44ece84f319b10f3c5c57
Parent
fa3f629060ed45a…
1 file changed
+39
-11
+39
-11
| --- src/json_user.c | ||
| +++ src/json_user.c | ||
| @@ -99,10 +99,33 @@ | ||
| 99 | 99 | u = cson_sqlite3_row_to_object(q.pStmt); |
| 100 | 100 | } |
| 101 | 101 | db_finalize(&q); |
| 102 | 102 | return u; |
| 103 | 103 | } |
| 104 | + | |
| 105 | +/* | |
| 106 | +** Identical to _load_user_by_name(), but expects a user ID. Returns | |
| 107 | +** NULL if no user found with that ID. | |
| 108 | +*/ | |
| 109 | +static cson_value * json_load_user_by_id(int uid){ | |
| 110 | + cson_value * u = NULL; | |
| 111 | + Stmt q; | |
| 112 | + db_prepare(&q,"SELECT uid AS uid," | |
| 113 | + " login AS name," | |
| 114 | + " cap AS capabilities," | |
| 115 | + " info AS info," | |
| 116 | + " mtime AS mtime" | |
| 117 | + " FROM user" | |
| 118 | + " WHERE uid=%d", | |
| 119 | + uid); | |
| 120 | + if( (SQLITE_ROW == db_step(&q)) ){ | |
| 121 | + u = cson_sqlite3_row_to_object(q.pStmt); | |
| 122 | + } | |
| 123 | + db_finalize(&q); | |
| 124 | + return u; | |
| 125 | +} | |
| 126 | + | |
| 104 | 127 | |
| 105 | 128 | /* |
| 106 | 129 | ** Impl of /json/user/get. Requires admin rights. |
| 107 | 130 | */ |
| 108 | 131 | static cson_value * json_user_get(){ |
| @@ -140,10 +163,15 @@ | ||
| 140 | 163 | ** optional and their db fields will not be updated if those fields |
| 141 | 164 | ** are not included in pUser. |
| 142 | 165 | ** |
| 143 | 166 | ** If uid is specified then name may refer to a _new_ name |
| 144 | 167 | ** for a user, otherwise the name must refer to an existing user. |
| 168 | +** If uid=-1 then the name must be specified and a new user is | |
| 169 | +** created (failes if one already exists). | |
| 170 | +** | |
| 171 | +** If uid is not set, this function might modify pUser to contain the | |
| 172 | +** db-found (or inserted) user ID. | |
| 145 | 173 | ** |
| 146 | 174 | ** On error g.json's error state is set one of the FSL_JSON_E_xxx |
| 147 | 175 | ** values from FossilJsonCodes is returned. |
| 148 | 176 | ** |
| 149 | 177 | ** On success the db record for the given user is updated. |
| @@ -215,28 +243,21 @@ | ||
| 215 | 243 | return json_set_err(FSL_JSON_E_RESOURCE_NOT_FOUND, |
| 216 | 244 | "No login found for user [%s].", zName); |
| 217 | 245 | } |
| 218 | 246 | cson_object_set( pUser, "uid", cson_value_new_integer(uid) ); |
| 219 | 247 | } |
| 220 | - /* | |
| 221 | - Todo: reserve the uid=-1 to mean that the user should be created | |
| 222 | - by this request. | |
| 223 | - | |
| 224 | - Todo: when changing an existing user's name we need to invalidate | |
| 225 | - or recalculate the login hash because the user's name is part of | |
| 226 | - the hash. | |
| 227 | - */ | |
| 228 | 248 | |
| 229 | 249 | /* Maintenance note: all error-returns from here on out should go |
| 230 | - via goto error in order to clean up. | |
| 250 | + via 'goto error' in order to clean up. | |
| 231 | 251 | */ |
| 232 | 252 | |
| 233 | 253 | if(uid != g.userUid){ |
| 234 | 254 | /* |
| 235 | 255 | TODO: do not allow an admin user to modify a setup user |
| 236 | 256 | unless the admin is also a setup user. setup.c uses |
| 237 | - that logic. | |
| 257 | + that logic. There is a corner case for a NEW Setup user | |
| 258 | + which the admin is just installing. Hmm. | |
| 238 | 259 | */ |
| 239 | 260 | if(!g.perm.Admin && !g.perm.Setup){ |
| 240 | 261 | json_set_err(FSL_JSON_E_DENIED, |
| 241 | 262 | "Changing another user's data requires " |
| 242 | 263 | "'a' or 's' privileges."); |
| @@ -328,10 +349,12 @@ | ||
| 328 | 349 | a JSON form of it... */ |
| 329 | 350 | cson_object * u = cson_new_object(); |
| 330 | 351 | char const * str = NULL; |
| 331 | 352 | char b = -1; |
| 332 | 353 | int i = -1; |
| 354 | + int uid = -1; | |
| 355 | + cson_value * payload = NULL; | |
| 333 | 356 | #define PROP(LK) str = json_find_option_cstr(LK,NULL,NULL); \ |
| 334 | 357 | if(str){ cson_object_set(u, LK, json_new_string(str)); } (void)0 |
| 335 | 358 | PROP("name"); |
| 336 | 359 | PROP("password"); |
| 337 | 360 | PROP("info"); |
| @@ -349,9 +372,14 @@ | ||
| 349 | 372 | #undef PROP |
| 350 | 373 | if( g.json.reqPayload.o ){ |
| 351 | 374 | cson_object_merge( u, g.json.reqPayload.o, CSON_MERGE_NO_RECURSE ); |
| 352 | 375 | } |
| 353 | 376 | json_user_update_from_json( u ); |
| 377 | + if(!g.json.resultCode){ | |
| 378 | + uid = cson_value_get_integer( cson_object_get(u, "uid") ); | |
| 379 | + assert((uid>0) && "Something went wrong in json_user_update_from_json()"); | |
| 380 | + payload = json_load_user_by_id(uid); | |
| 381 | + } | |
| 354 | 382 | cson_free_object(u); |
| 355 | - return NULL; | |
| 383 | + return payload; | |
| 356 | 384 | } |
| 357 | 385 | #endif /* FOSSIL_ENABLE_JSON */ |
| 358 | 386 |
| --- src/json_user.c | |
| +++ src/json_user.c | |
| @@ -99,10 +99,33 @@ | |
| 99 | u = cson_sqlite3_row_to_object(q.pStmt); |
| 100 | } |
| 101 | db_finalize(&q); |
| 102 | return u; |
| 103 | } |
| 104 | |
| 105 | /* |
| 106 | ** Impl of /json/user/get. Requires admin rights. |
| 107 | */ |
| 108 | static cson_value * json_user_get(){ |
| @@ -140,10 +163,15 @@ | |
| 140 | ** optional and their db fields will not be updated if those fields |
| 141 | ** are not included in pUser. |
| 142 | ** |
| 143 | ** If uid is specified then name may refer to a _new_ name |
| 144 | ** for a user, otherwise the name must refer to an existing user. |
| 145 | ** |
| 146 | ** On error g.json's error state is set one of the FSL_JSON_E_xxx |
| 147 | ** values from FossilJsonCodes is returned. |
| 148 | ** |
| 149 | ** On success the db record for the given user is updated. |
| @@ -215,28 +243,21 @@ | |
| 215 | return json_set_err(FSL_JSON_E_RESOURCE_NOT_FOUND, |
| 216 | "No login found for user [%s].", zName); |
| 217 | } |
| 218 | cson_object_set( pUser, "uid", cson_value_new_integer(uid) ); |
| 219 | } |
| 220 | /* |
| 221 | Todo: reserve the uid=-1 to mean that the user should be created |
| 222 | by this request. |
| 223 | |
| 224 | Todo: when changing an existing user's name we need to invalidate |
| 225 | or recalculate the login hash because the user's name is part of |
| 226 | the hash. |
| 227 | */ |
| 228 | |
| 229 | /* Maintenance note: all error-returns from here on out should go |
| 230 | via goto error in order to clean up. |
| 231 | */ |
| 232 | |
| 233 | if(uid != g.userUid){ |
| 234 | /* |
| 235 | TODO: do not allow an admin user to modify a setup user |
| 236 | unless the admin is also a setup user. setup.c uses |
| 237 | that logic. |
| 238 | */ |
| 239 | if(!g.perm.Admin && !g.perm.Setup){ |
| 240 | json_set_err(FSL_JSON_E_DENIED, |
| 241 | "Changing another user's data requires " |
| 242 | "'a' or 's' privileges."); |
| @@ -328,10 +349,12 @@ | |
| 328 | a JSON form of it... */ |
| 329 | cson_object * u = cson_new_object(); |
| 330 | char const * str = NULL; |
| 331 | char b = -1; |
| 332 | int i = -1; |
| 333 | #define PROP(LK) str = json_find_option_cstr(LK,NULL,NULL); \ |
| 334 | if(str){ cson_object_set(u, LK, json_new_string(str)); } (void)0 |
| 335 | PROP("name"); |
| 336 | PROP("password"); |
| 337 | PROP("info"); |
| @@ -349,9 +372,14 @@ | |
| 349 | #undef PROP |
| 350 | if( g.json.reqPayload.o ){ |
| 351 | cson_object_merge( u, g.json.reqPayload.o, CSON_MERGE_NO_RECURSE ); |
| 352 | } |
| 353 | json_user_update_from_json( u ); |
| 354 | cson_free_object(u); |
| 355 | return NULL; |
| 356 | } |
| 357 | #endif /* FOSSIL_ENABLE_JSON */ |
| 358 |
| --- src/json_user.c | |
| +++ src/json_user.c | |
| @@ -99,10 +99,33 @@ | |
| 99 | u = cson_sqlite3_row_to_object(q.pStmt); |
| 100 | } |
| 101 | db_finalize(&q); |
| 102 | return u; |
| 103 | } |
| 104 | |
| 105 | /* |
| 106 | ** Identical to _load_user_by_name(), but expects a user ID. Returns |
| 107 | ** NULL if no user found with that ID. |
| 108 | */ |
| 109 | static cson_value * json_load_user_by_id(int uid){ |
| 110 | cson_value * u = NULL; |
| 111 | Stmt q; |
| 112 | db_prepare(&q,"SELECT uid AS uid," |
| 113 | " login AS name," |
| 114 | " cap AS capabilities," |
| 115 | " info AS info," |
| 116 | " mtime AS mtime" |
| 117 | " FROM user" |
| 118 | " WHERE uid=%d", |
| 119 | uid); |
| 120 | if( (SQLITE_ROW == db_step(&q)) ){ |
| 121 | u = cson_sqlite3_row_to_object(q.pStmt); |
| 122 | } |
| 123 | db_finalize(&q); |
| 124 | return u; |
| 125 | } |
| 126 | |
| 127 | |
| 128 | /* |
| 129 | ** Impl of /json/user/get. Requires admin rights. |
| 130 | */ |
| 131 | static cson_value * json_user_get(){ |
| @@ -140,10 +163,15 @@ | |
| 163 | ** optional and their db fields will not be updated if those fields |
| 164 | ** are not included in pUser. |
| 165 | ** |
| 166 | ** If uid is specified then name may refer to a _new_ name |
| 167 | ** for a user, otherwise the name must refer to an existing user. |
| 168 | ** If uid=-1 then the name must be specified and a new user is |
| 169 | ** created (failes if one already exists). |
| 170 | ** |
| 171 | ** If uid is not set, this function might modify pUser to contain the |
| 172 | ** db-found (or inserted) user ID. |
| 173 | ** |
| 174 | ** On error g.json's error state is set one of the FSL_JSON_E_xxx |
| 175 | ** values from FossilJsonCodes is returned. |
| 176 | ** |
| 177 | ** On success the db record for the given user is updated. |
| @@ -215,28 +243,21 @@ | |
| 243 | return json_set_err(FSL_JSON_E_RESOURCE_NOT_FOUND, |
| 244 | "No login found for user [%s].", zName); |
| 245 | } |
| 246 | cson_object_set( pUser, "uid", cson_value_new_integer(uid) ); |
| 247 | } |
| 248 | |
| 249 | /* Maintenance note: all error-returns from here on out should go |
| 250 | via 'goto error' in order to clean up. |
| 251 | */ |
| 252 | |
| 253 | if(uid != g.userUid){ |
| 254 | /* |
| 255 | TODO: do not allow an admin user to modify a setup user |
| 256 | unless the admin is also a setup user. setup.c uses |
| 257 | that logic. There is a corner case for a NEW Setup user |
| 258 | which the admin is just installing. Hmm. |
| 259 | */ |
| 260 | if(!g.perm.Admin && !g.perm.Setup){ |
| 261 | json_set_err(FSL_JSON_E_DENIED, |
| 262 | "Changing another user's data requires " |
| 263 | "'a' or 's' privileges."); |
| @@ -328,10 +349,12 @@ | |
| 349 | a JSON form of it... */ |
| 350 | cson_object * u = cson_new_object(); |
| 351 | char const * str = NULL; |
| 352 | char b = -1; |
| 353 | int i = -1; |
| 354 | int uid = -1; |
| 355 | cson_value * payload = NULL; |
| 356 | #define PROP(LK) str = json_find_option_cstr(LK,NULL,NULL); \ |
| 357 | if(str){ cson_object_set(u, LK, json_new_string(str)); } (void)0 |
| 358 | PROP("name"); |
| 359 | PROP("password"); |
| 360 | PROP("info"); |
| @@ -349,9 +372,14 @@ | |
| 372 | #undef PROP |
| 373 | if( g.json.reqPayload.o ){ |
| 374 | cson_object_merge( u, g.json.reqPayload.o, CSON_MERGE_NO_RECURSE ); |
| 375 | } |
| 376 | json_user_update_from_json( u ); |
| 377 | if(!g.json.resultCode){ |
| 378 | uid = cson_value_get_integer( cson_object_get(u, "uid") ); |
| 379 | assert((uid>0) && "Something went wrong in json_user_update_from_json()"); |
| 380 | payload = json_load_user_by_id(uid); |
| 381 | } |
| 382 | cson_free_object(u); |
| 383 | return payload; |
| 384 | } |
| 385 | #endif /* FOSSIL_ENABLE_JSON */ |
| 386 |