Fossil SCM

/json/user/save now accepts uid=-1 to mean create-user. Fixed a bug where when renaming a user _and_ setting his password, the password was incorrectly hashed against the old name.

stephan 2011-11-05 02:40 trunk
Commit fa3f629060ed45ac0edd6a7529da64e8ee15f8b9
1 file changed +62 -30
+62 -30
--- src/json_user.c
+++ src/json_user.c
@@ -75,18 +75,41 @@
7575
json_set_err(FSL_JSON_E_UNKNOWN,
7676
"Could not convert user list to JSON.");
7777
}
7878
return payV;
7979
}
80
+
81
+/*
82
+** Creates a new JSON Object based on the db state of
83
+** the given user name. On error (no record found)
84
+** it returns NULL, else the caller owns the returned
85
+** object.
86
+*/
87
+static cson_value * json_load_user_by_name(char const * zName){
88
+ cson_value * u = NULL;
89
+ Stmt q;
90
+ db_prepare(&q,"SELECT uid AS uid,"
91
+ " login AS name,"
92
+ " cap AS capabilities,"
93
+ " info AS info,"
94
+ " mtime AS mtime"
95
+ " FROM user"
96
+ " WHERE login=%Q",
97
+ zName);
98
+ if( (SQLITE_ROW == db_step(&q)) ){
99
+ u = cson_sqlite3_row_to_object(q.pStmt);
100
+ }
101
+ db_finalize(&q);
102
+ return u;
103
+}
80104
81105
/*
82106
** Impl of /json/user/get. Requires admin rights.
83107
*/
84108
static cson_value * json_user_get(){
85109
cson_value * payV = NULL;
86110
char const * pUser = NULL;
87
- Stmt q;
88111
if(!g.perm.Admin){
89112
json_set_err(FSL_JSON_E_DENIED,
90113
"Requires 'a' privileges.");
91114
return NULL;
92115
}
@@ -100,27 +123,14 @@
100123
}
101124
if(!pUser || !*pUser){
102125
json_set_err(FSL_JSON_E_MISSING_ARGS,"Missing 'name' property.");
103126
return NULL;
104127
}
105
- db_prepare(&q,"SELECT uid AS uid,"
106
- " login AS name,"
107
- " cap AS capabilities,"
108
- " info AS info,"
109
- " mtime AS mtime"
110
- " FROM user"
111
- " WHERE login=%Q",
112
- pUser);
113
- if( (SQLITE_ROW == db_step(&q)) ){
114
- payV = cson_sqlite3_row_to_object(q.pStmt);
115
- if(!payV){
116
- json_set_err(FSL_JSON_E_UNKNOWN,"Could not convert user row to JSON.");
117
- }
118
- }else{
128
+ payV = json_load_user_by_name(pUser);
129
+ if(!payV){
119130
json_set_err(FSL_JSON_E_RESOURCE_NOT_FOUND,"User not found.");
120131
}
121
- db_finalize(&q);
122132
return payV;
123133
}
124134
125135
/*
126136
** Expects pUser to contain fossil user fields in JSON form: name,
@@ -145,11 +155,11 @@
145155
**
146156
** - Admin non-Setup users cannot change the information for Setup
147157
** users.
148158
**
149159
*/
150
-int json_user_update_from_json( cson_object const * pUser ){
160
+int json_user_update_from_json( cson_object * pUser ){
151161
#define CSTR(X) cson_string_cstr(cson_value_get_string( cson_object_get(pUser, X ) ))
152162
char const * zName = CSTR("name");
153163
char const * zNameNew = zName;
154164
char * zNameFree = NULL;
155165
char const * zInfo = CSTR("info");
@@ -176,17 +186,38 @@
176186
if(!zNameFree){
177187
return json_set_err(FSL_JSON_E_RESOURCE_NOT_FOUND,
178188
"No login found for uid %d.", uid);
179189
}
180190
zName = zNameFree;
191
+ }else if(-1==uid){
192
+ /* try to create a new user */
193
+ if(!g.perm.Admin && !g.perm.Setup){
194
+ return json_set_err(FSL_JSON_E_DENIED,
195
+ "Requires 'a' or 's' privileges.");
196
+ } else if(!zName || !*zName){
197
+ return json_set_err(FSL_JSON_E_MISSING_ARGS,
198
+ "No name specified for new user.");
199
+ }else if( db_exists("SELECT 1 FROM user WHERE login=%Q", zName) ){
200
+ return json_set_err(FSL_JSON_E_RESOURCE_ALREADY_EXISTS,
201
+ "User %s already exists.", zName);
202
+ }else{
203
+ Stmt ins = empty_Stmt;
204
+ db_prepare(&ins, "INSERT INTO user (login) VALUES(%Q)",zName);
205
+ db_step( &ins );
206
+ db_finalize(&ins);
207
+ uid = db_int(0,"SELECT uid FROM user WHERE login=%Q", zName);
208
+ assert(uid>0);
209
+ zNameNew = zName;
210
+ cson_object_set( pUser, "uid", cson_value_new_integer(uid) );
211
+ }
181212
}else{
182
- uid = db_int(0,"SELECT uid FROM user WHERE login=%Q",
183
- zName);
213
+ uid = db_int(0,"SELECT uid FROM user WHERE login=%Q", zName);
184214
if(uid<=0){
185215
return json_set_err(FSL_JSON_E_RESOURCE_NOT_FOUND,
186216
"No login found for user [%s].", zName);
187217
}
218
+ cson_object_set( pUser, "uid", cson_value_new_integer(uid) );
188219
}
189220
/*
190221
Todo: reserve the uid=-1 to mean that the user should be created
191222
by this request.
192223
@@ -213,20 +244,18 @@
213244
}
214245
215246
blob_append(&sql, "UPDATE USER SET",-1 );
216247
blob_append(&sql, " mtime=cast(strftime('%s') AS INTEGER)", -1);
217248
218
- if((uid>0) && zName){
219
- /* Only change the name if the uid is explicitly set and name
220
- would actually change. */
221
- if( zNameNew && (zName != zNameNew)
249
+ if((uid>0) && zNameNew){
250
+ /* Check for name change... */
251
+ if( (!g.perm.Admin && !g.perm.Setup)
252
+ && zNameNew && (zName != zNameNew)
222253
&& (0!=strcmp(zNameNew,zName))){
223
- if(!g.perm.Admin && !g.perm.Setup) {
224
- json_set_err( FSL_JSON_E_DENIED,
225
- "Modifying user names requires 'a' or 's' privileges.");
226
- goto error;
227
- }
254
+ json_set_err( FSL_JSON_E_DENIED,
255
+ "Modifying user names requires 'a' or 's' privileges.");
256
+ goto error;
228257
}
229258
forceLogout = cson_value_true()
230259
/* reminders: 1) does not allocate.
231260
2) we do this because changing a name
232261
invalidates any login token because the old name
@@ -242,11 +271,11 @@
242271
}
243272
244273
if( zPW ){
245274
char * zPWHash = NULL;
246275
++gotFields;
247
- zPWHash = sha1_shared_secret(zPW, zName, NULL);
276
+ zPWHash = sha1_shared_secret(zPW, zNameNew ? zNameNew : zName, NULL);
248277
blob_appendf(&sql, ", pw=%Q", zPWHash);
249278
free(zPWHash);
250279
}
251280
252281
if( zInfo ){
@@ -266,11 +295,14 @@
266295
goto error;
267296
}
268297
assert(uid>0);
269298
blob_appendf(&sql, " WHERE uid=%d", uid);
270299
free( zNameFree );
271
- /*puts(blob_str(&sql));*/
300
+#if 0
301
+ puts(blob_str(&sql));
302
+ cson_output_FILE( cson_object_value(pUser), stdout, NULL );
303
+#endif
272304
db_prepare(&q, "%s", blob_str(&sql));
273305
blob_reset(&sql);
274306
db_exec(&q);
275307
db_finalize(&q);
276308
return 0;
277309
--- src/json_user.c
+++ src/json_user.c
@@ -75,18 +75,41 @@
75 json_set_err(FSL_JSON_E_UNKNOWN,
76 "Could not convert user list to JSON.");
77 }
78 return payV;
79 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
80
81 /*
82 ** Impl of /json/user/get. Requires admin rights.
83 */
84 static cson_value * json_user_get(){
85 cson_value * payV = NULL;
86 char const * pUser = NULL;
87 Stmt q;
88 if(!g.perm.Admin){
89 json_set_err(FSL_JSON_E_DENIED,
90 "Requires 'a' privileges.");
91 return NULL;
92 }
@@ -100,27 +123,14 @@
100 }
101 if(!pUser || !*pUser){
102 json_set_err(FSL_JSON_E_MISSING_ARGS,"Missing 'name' property.");
103 return NULL;
104 }
105 db_prepare(&q,"SELECT uid AS uid,"
106 " login AS name,"
107 " cap AS capabilities,"
108 " info AS info,"
109 " mtime AS mtime"
110 " FROM user"
111 " WHERE login=%Q",
112 pUser);
113 if( (SQLITE_ROW == db_step(&q)) ){
114 payV = cson_sqlite3_row_to_object(q.pStmt);
115 if(!payV){
116 json_set_err(FSL_JSON_E_UNKNOWN,"Could not convert user row to JSON.");
117 }
118 }else{
119 json_set_err(FSL_JSON_E_RESOURCE_NOT_FOUND,"User not found.");
120 }
121 db_finalize(&q);
122 return payV;
123 }
124
125 /*
126 ** Expects pUser to contain fossil user fields in JSON form: name,
@@ -145,11 +155,11 @@
145 **
146 ** - Admin non-Setup users cannot change the information for Setup
147 ** users.
148 **
149 */
150 int json_user_update_from_json( cson_object const * pUser ){
151 #define CSTR(X) cson_string_cstr(cson_value_get_string( cson_object_get(pUser, X ) ))
152 char const * zName = CSTR("name");
153 char const * zNameNew = zName;
154 char * zNameFree = NULL;
155 char const * zInfo = CSTR("info");
@@ -176,17 +186,38 @@
176 if(!zNameFree){
177 return json_set_err(FSL_JSON_E_RESOURCE_NOT_FOUND,
178 "No login found for uid %d.", uid);
179 }
180 zName = zNameFree;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
181 }else{
182 uid = db_int(0,"SELECT uid FROM user WHERE login=%Q",
183 zName);
184 if(uid<=0){
185 return json_set_err(FSL_JSON_E_RESOURCE_NOT_FOUND,
186 "No login found for user [%s].", zName);
187 }
 
188 }
189 /*
190 Todo: reserve the uid=-1 to mean that the user should be created
191 by this request.
192
@@ -213,20 +244,18 @@
213 }
214
215 blob_append(&sql, "UPDATE USER SET",-1 );
216 blob_append(&sql, " mtime=cast(strftime('%s') AS INTEGER)", -1);
217
218 if((uid>0) && zName){
219 /* Only change the name if the uid is explicitly set and name
220 would actually change. */
221 if( zNameNew && (zName != zNameNew)
222 && (0!=strcmp(zNameNew,zName))){
223 if(!g.perm.Admin && !g.perm.Setup) {
224 json_set_err( FSL_JSON_E_DENIED,
225 "Modifying user names requires 'a' or 's' privileges.");
226 goto error;
227 }
228 }
229 forceLogout = cson_value_true()
230 /* reminders: 1) does not allocate.
231 2) we do this because changing a name
232 invalidates any login token because the old name
@@ -242,11 +271,11 @@
242 }
243
244 if( zPW ){
245 char * zPWHash = NULL;
246 ++gotFields;
247 zPWHash = sha1_shared_secret(zPW, zName, NULL);
248 blob_appendf(&sql, ", pw=%Q", zPWHash);
249 free(zPWHash);
250 }
251
252 if( zInfo ){
@@ -266,11 +295,14 @@
266 goto error;
267 }
268 assert(uid>0);
269 blob_appendf(&sql, " WHERE uid=%d", uid);
270 free( zNameFree );
271 /*puts(blob_str(&sql));*/
 
 
 
272 db_prepare(&q, "%s", blob_str(&sql));
273 blob_reset(&sql);
274 db_exec(&q);
275 db_finalize(&q);
276 return 0;
277
--- src/json_user.c
+++ src/json_user.c
@@ -75,18 +75,41 @@
75 json_set_err(FSL_JSON_E_UNKNOWN,
76 "Could not convert user list to JSON.");
77 }
78 return payV;
79 }
80
81 /*
82 ** Creates a new JSON Object based on the db state of
83 ** the given user name. On error (no record found)
84 ** it returns NULL, else the caller owns the returned
85 ** object.
86 */
87 static cson_value * json_load_user_by_name(char const * zName){
88 cson_value * u = NULL;
89 Stmt q;
90 db_prepare(&q,"SELECT uid AS uid,"
91 " login AS name,"
92 " cap AS capabilities,"
93 " info AS info,"
94 " mtime AS mtime"
95 " FROM user"
96 " WHERE login=%Q",
97 zName);
98 if( (SQLITE_ROW == db_step(&q)) ){
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(){
109 cson_value * payV = NULL;
110 char const * pUser = NULL;
 
111 if(!g.perm.Admin){
112 json_set_err(FSL_JSON_E_DENIED,
113 "Requires 'a' privileges.");
114 return NULL;
115 }
@@ -100,27 +123,14 @@
123 }
124 if(!pUser || !*pUser){
125 json_set_err(FSL_JSON_E_MISSING_ARGS,"Missing 'name' property.");
126 return NULL;
127 }
128 payV = json_load_user_by_name(pUser);
129 if(!payV){
 
 
 
 
 
 
 
 
 
 
 
 
130 json_set_err(FSL_JSON_E_RESOURCE_NOT_FOUND,"User not found.");
131 }
 
132 return payV;
133 }
134
135 /*
136 ** Expects pUser to contain fossil user fields in JSON form: name,
@@ -145,11 +155,11 @@
155 **
156 ** - Admin non-Setup users cannot change the information for Setup
157 ** users.
158 **
159 */
160 int json_user_update_from_json( cson_object * pUser ){
161 #define CSTR(X) cson_string_cstr(cson_value_get_string( cson_object_get(pUser, X ) ))
162 char const * zName = CSTR("name");
163 char const * zNameNew = zName;
164 char * zNameFree = NULL;
165 char const * zInfo = CSTR("info");
@@ -176,17 +186,38 @@
186 if(!zNameFree){
187 return json_set_err(FSL_JSON_E_RESOURCE_NOT_FOUND,
188 "No login found for uid %d.", uid);
189 }
190 zName = zNameFree;
191 }else if(-1==uid){
192 /* try to create a new user */
193 if(!g.perm.Admin && !g.perm.Setup){
194 return json_set_err(FSL_JSON_E_DENIED,
195 "Requires 'a' or 's' privileges.");
196 } else if(!zName || !*zName){
197 return json_set_err(FSL_JSON_E_MISSING_ARGS,
198 "No name specified for new user.");
199 }else if( db_exists("SELECT 1 FROM user WHERE login=%Q", zName) ){
200 return json_set_err(FSL_JSON_E_RESOURCE_ALREADY_EXISTS,
201 "User %s already exists.", zName);
202 }else{
203 Stmt ins = empty_Stmt;
204 db_prepare(&ins, "INSERT INTO user (login) VALUES(%Q)",zName);
205 db_step( &ins );
206 db_finalize(&ins);
207 uid = db_int(0,"SELECT uid FROM user WHERE login=%Q", zName);
208 assert(uid>0);
209 zNameNew = zName;
210 cson_object_set( pUser, "uid", cson_value_new_integer(uid) );
211 }
212 }else{
213 uid = db_int(0,"SELECT uid FROM user WHERE login=%Q", zName);
 
214 if(uid<=0){
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
@@ -213,20 +244,18 @@
244 }
245
246 blob_append(&sql, "UPDATE USER SET",-1 );
247 blob_append(&sql, " mtime=cast(strftime('%s') AS INTEGER)", -1);
248
249 if((uid>0) && zNameNew){
250 /* Check for name change... */
251 if( (!g.perm.Admin && !g.perm.Setup)
252 && zNameNew && (zName != zNameNew)
253 && (0!=strcmp(zNameNew,zName))){
254 json_set_err( FSL_JSON_E_DENIED,
255 "Modifying user names requires 'a' or 's' privileges.");
256 goto error;
 
 
257 }
258 forceLogout = cson_value_true()
259 /* reminders: 1) does not allocate.
260 2) we do this because changing a name
261 invalidates any login token because the old name
@@ -242,11 +271,11 @@
271 }
272
273 if( zPW ){
274 char * zPWHash = NULL;
275 ++gotFields;
276 zPWHash = sha1_shared_secret(zPW, zNameNew ? zNameNew : zName, NULL);
277 blob_appendf(&sql, ", pw=%Q", zPWHash);
278 free(zPWHash);
279 }
280
281 if( zInfo ){
@@ -266,11 +295,14 @@
295 goto error;
296 }
297 assert(uid>0);
298 blob_appendf(&sql, " WHERE uid=%d", uid);
299 free( zNameFree );
300 #if 0
301 puts(blob_str(&sql));
302 cson_output_FILE( cson_object_value(pUser), stdout, NULL );
303 #endif
304 db_prepare(&q, "%s", blob_str(&sql));
305 blob_reset(&sql);
306 db_exec(&q);
307 db_finalize(&q);
308 return 0;
309

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button