Fossil SCM

Fixed a minor mem leak. Got /json/user/save mostly working.

stephan 2011-10-21 15:25 json-multitag-test
Commit 080acb91be7b3cdc9dbab582d1ca5f87d2d0ac7f
2 files changed +94 -26 +3 -1
+94 -26
--- src/json_user.c
+++ src/json_user.c
@@ -120,24 +120,53 @@
120120
db_finalize(&q);
121121
return payV;
122122
}
123123
124124
/*
125
-** Don't use - not yet finished.
125
+** Expects pUser to contain fossil user fields in JSON form: name,
126
+** uid, info, capabilities, password.
127
+**
128
+** At least one of (name, uid) must be included. All others are
129
+** optional and their db fields will not be updated if those fields
130
+** are not included in pUser.
131
+**
132
+** If uid is specified then name may refer to a _new_ name
133
+** for a user, otherwise the name must refer to an existing user.
134
+**
135
+** On error g.json's error state is set one of the FSL_JSON_E_xxx
136
+** values from FossilJsonCodes is returned.
137
+**
138
+** On success the db record for the given user is updated.
139
+**
140
+** Requires either Admin, Setup, or Password access. Non-admin/setup
141
+** users can only change their own information.
142
+**
143
+** TODOs:
144
+**
145
+** - Admin non-Setup users cannot change the information for Setup
146
+** users.
147
+**
126148
*/
127149
int json_user_update_from_json( cson_object const * pUser ){
128150
#define CSTR(X) cson_string_cstr(cson_value_get_string( cson_object_get(pUser, X ) ))
129151
char const * zName = CSTR("name");
152
+ char const * zNameOrig = zName;
130153
char * zNameFree = NULL;
131154
char const * zInfo = CSTR("info");
132155
char const * zCap = CSTR("capabilities");
133156
char const * zPW = CSTR("password");
134157
int gotFields = 0;
135158
#undef CSTR
136
- cson_int_t const uid = cson_value_get_integer( cson_object_get(pUser, "uid") );
159
+ cson_int_t uid = cson_value_get_integer( cson_object_get(pUser, "uid") );
137160
Blob sql = empty_blob;
138161
Stmt q = empty_Stmt;
162
+
163
+ if(!g.perm.Admin && !g.perm.Setup && !g.perm.Password){
164
+ return json_set_err( FSL_JSON_E_DENIED,
165
+ "Password change requires 'a', 's', "
166
+ "or 'p' permissions.");
167
+ }
139168
140169
if(uid<=0 && (!zName||!*zName)){
141170
return json_set_err(FSL_JSON_E_MISSING_ARGS,
142171
"One of 'uid' or 'name' is required.");
143172
}else if(uid>0){
@@ -145,52 +174,91 @@
145174
if(!zNameFree){
146175
return json_set_err(FSL_JSON_E_RESOURCE_NOT_FOUND,
147176
"No login found for uid %d.", uid);
148177
}
149178
zName = zNameFree;
179
+ }else{
180
+ uid = db_int(0,"SELECT uid FROM user WHERE login=%Q",
181
+ zName);
182
+ if(uid<=0){
183
+ return json_set_err(FSL_JSON_E_RESOURCE_NOT_FOUND,
184
+ "No login found for user [%s].", zName);
185
+ }
150186
}
151
-
152
- /*
153
- TODO: do not allow an admin user to modify a setup user
154
- unless the admin is also a setup user. setup.c uses
155
- that logic.
187
+ /* Maintenance note: all error-returns from here on out should go
188
+ via goto error in order to clean up.
156189
*/
157190
158
- blob_append(&sql, "UPDATE USER SET ",-1 );
159
- if( zInfo ){
160
- blob_appendf(&sql, " info=%Q", zInfo);
191
+ if(uid != g.userUid){
192
+ /*
193
+ TODO: do not allow an admin user to modify a setup user
194
+ unless the admin is also a setup user. setup.c uses
195
+ that logic.
196
+ */
197
+ if(!g.perm.Admin && !g.perm.Setup){
198
+ json_set_err(FSL_JSON_E_DENIED,
199
+ "Changing another user's data requires "
200
+ "'a' or 's' privileges.");
201
+ }
202
+ }
203
+
204
+ blob_append(&sql, "UPDATE USER SET",-1 );
205
+ blob_append(&sql, " mtime=cast(strftime('%s') AS INTEGER)", -1);
206
+
207
+ if((uid>0) && zName
208
+ && zNameOrig && (zName != zNameOrig)
209
+ && (0!=strcmp(zNameOrig,zName))){
210
+ /* Only change the name if the uid is explicitly set and name
211
+ would actually change. */
212
+ if(!g.perm.Admin && !g.perm.Setup) {
213
+ json_set_err( FSL_JSON_E_DENIED,
214
+ "Modifying user names requires 'a' or 's' privileges.");
215
+ goto error;
216
+ }
217
+ blob_appendf(&sql, ", login=%Q", zNameOrig);
161218
++gotFields;
162219
}
220
+
163221
if( zCap ){
164
- blob_appendf(&sql, "%c cap=%Q", (gotFields ? ',' : ' '), zCap);
222
+ blob_appendf(&sql, ", cap=%Q", zCap);
165223
++gotFields;
166224
}
225
+
167226
if( zPW ){
168
- assert( zName != NULL);
169
- blob_appendf(&sql, "%c password=coalesce(shared_secret(%Q,%Q,"
170
- "(SELECT value FROM config WHERE name='project-code')),pw),",
171
- (gotFields ? ',' : ' '), zPW, zName);
227
+ char * zPWHash = NULL;
228
+ ++gotFields;
229
+ zPWHash = sha1_shared_secret(zPW, zName, NULL);
230
+ blob_appendf(&sql, ", pw=%Q", zPWHash);
231
+ free(zPWHash);
232
+ }
233
+
234
+ if( zInfo ){
235
+ blob_appendf(&sql, ", info=%Q", zInfo);
172236
++gotFields;
173237
}
174238
175239
if(!gotFields){
176
- free( zNameFree );
177
- blob_reset(&sql);
178
- return FSL_JSON_E_MISSING_ARGS;
240
+ json_set_err( FSL_JSON_E_MISSING_ARGS,
241
+ "Required user data are missing.");
242
+ goto error;
179243
}
180244
blob_append(&sql, " WHERE", -1);
181
- if(uid>0){
182
- blob_appendf(&sql, " uid=%d", uid);
183
- }else{
184
- blob_appendf(&sql, " login=%Q", zName);
185
- }
245
+ assert(uid>0);
246
+ blob_appendf(&sql, " uid=%d", uid);
186247
free( zNameFree );
187
-
188
- puts(blob_str(&sql));
248
+ /*puts(blob_str(&sql));*/
249
+ db_prepare(&q, "%s", blob_str(&sql));
189250
blob_reset(&sql);
190
- assert(0 && "This is going to require extra work for login groups.");
251
+ db_exec(&q);
252
+ db_finalize(&q);
191253
return 0;
254
+
255
+ error:
256
+ assert(0 != g.json.resultCode);
257
+ free(zNameFree);
258
+ blob_reset(&sql);
259
+ return g.json.resultCode;
192260
}
193261
194262
195263
/*
196264
** Don't use - not yet finished.
197265
--- src/json_user.c
+++ src/json_user.c
@@ -120,24 +120,53 @@
120 db_finalize(&q);
121 return payV;
122 }
123
124 /*
125 ** Don't use - not yet finished.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
126 */
127 int json_user_update_from_json( cson_object const * pUser ){
128 #define CSTR(X) cson_string_cstr(cson_value_get_string( cson_object_get(pUser, X ) ))
129 char const * zName = CSTR("name");
 
130 char * zNameFree = NULL;
131 char const * zInfo = CSTR("info");
132 char const * zCap = CSTR("capabilities");
133 char const * zPW = CSTR("password");
134 int gotFields = 0;
135 #undef CSTR
136 cson_int_t const uid = cson_value_get_integer( cson_object_get(pUser, "uid") );
137 Blob sql = empty_blob;
138 Stmt q = empty_Stmt;
 
 
 
 
 
 
139
140 if(uid<=0 && (!zName||!*zName)){
141 return json_set_err(FSL_JSON_E_MISSING_ARGS,
142 "One of 'uid' or 'name' is required.");
143 }else if(uid>0){
@@ -145,52 +174,91 @@
145 if(!zNameFree){
146 return json_set_err(FSL_JSON_E_RESOURCE_NOT_FOUND,
147 "No login found for uid %d.", uid);
148 }
149 zName = zNameFree;
 
 
 
 
 
 
 
150 }
151
152 /*
153 TODO: do not allow an admin user to modify a setup user
154 unless the admin is also a setup user. setup.c uses
155 that logic.
156 */
157
158 blob_append(&sql, "UPDATE USER SET ",-1 );
159 if( zInfo ){
160 blob_appendf(&sql, " info=%Q", zInfo);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
161 ++gotFields;
162 }
 
163 if( zCap ){
164 blob_appendf(&sql, "%c cap=%Q", (gotFields ? ',' : ' '), zCap);
165 ++gotFields;
166 }
 
167 if( zPW ){
168 assert( zName != NULL);
169 blob_appendf(&sql, "%c password=coalesce(shared_secret(%Q,%Q,"
170 "(SELECT value FROM config WHERE name='project-code')),pw),",
171 (gotFields ? ',' : ' '), zPW, zName);
 
 
 
 
 
172 ++gotFields;
173 }
174
175 if(!gotFields){
176 free( zNameFree );
177 blob_reset(&sql);
178 return FSL_JSON_E_MISSING_ARGS;
179 }
180 blob_append(&sql, " WHERE", -1);
181 if(uid>0){
182 blob_appendf(&sql, " uid=%d", uid);
183 }else{
184 blob_appendf(&sql, " login=%Q", zName);
185 }
186 free( zNameFree );
187
188 puts(blob_str(&sql));
189 blob_reset(&sql);
190 assert(0 && "This is going to require extra work for login groups.");
 
191 return 0;
 
 
 
 
 
 
192 }
193
194
195 /*
196 ** Don't use - not yet finished.
197
--- src/json_user.c
+++ src/json_user.c
@@ -120,24 +120,53 @@
120 db_finalize(&q);
121 return payV;
122 }
123
124 /*
125 ** Expects pUser to contain fossil user fields in JSON form: name,
126 ** uid, info, capabilities, password.
127 **
128 ** At least one of (name, uid) must be included. All others are
129 ** optional and their db fields will not be updated if those fields
130 ** are not included in pUser.
131 **
132 ** If uid is specified then name may refer to a _new_ name
133 ** for a user, otherwise the name must refer to an existing user.
134 **
135 ** On error g.json's error state is set one of the FSL_JSON_E_xxx
136 ** values from FossilJsonCodes is returned.
137 **
138 ** On success the db record for the given user is updated.
139 **
140 ** Requires either Admin, Setup, or Password access. Non-admin/setup
141 ** users can only change their own information.
142 **
143 ** TODOs:
144 **
145 ** - Admin non-Setup users cannot change the information for Setup
146 ** users.
147 **
148 */
149 int json_user_update_from_json( cson_object const * pUser ){
150 #define CSTR(X) cson_string_cstr(cson_value_get_string( cson_object_get(pUser, X ) ))
151 char const * zName = CSTR("name");
152 char const * zNameOrig = zName;
153 char * zNameFree = NULL;
154 char const * zInfo = CSTR("info");
155 char const * zCap = CSTR("capabilities");
156 char const * zPW = CSTR("password");
157 int gotFields = 0;
158 #undef CSTR
159 cson_int_t uid = cson_value_get_integer( cson_object_get(pUser, "uid") );
160 Blob sql = empty_blob;
161 Stmt q = empty_Stmt;
162
163 if(!g.perm.Admin && !g.perm.Setup && !g.perm.Password){
164 return json_set_err( FSL_JSON_E_DENIED,
165 "Password change requires 'a', 's', "
166 "or 'p' permissions.");
167 }
168
169 if(uid<=0 && (!zName||!*zName)){
170 return json_set_err(FSL_JSON_E_MISSING_ARGS,
171 "One of 'uid' or 'name' is required.");
172 }else if(uid>0){
@@ -145,52 +174,91 @@
174 if(!zNameFree){
175 return json_set_err(FSL_JSON_E_RESOURCE_NOT_FOUND,
176 "No login found for uid %d.", uid);
177 }
178 zName = zNameFree;
179 }else{
180 uid = db_int(0,"SELECT uid FROM user WHERE login=%Q",
181 zName);
182 if(uid<=0){
183 return json_set_err(FSL_JSON_E_RESOURCE_NOT_FOUND,
184 "No login found for user [%s].", zName);
185 }
186 }
187 /* Maintenance note: all error-returns from here on out should go
188 via goto error in order to clean up.
 
 
 
189 */
190
191 if(uid != g.userUid){
192 /*
193 TODO: do not allow an admin user to modify a setup user
194 unless the admin is also a setup user. setup.c uses
195 that logic.
196 */
197 if(!g.perm.Admin && !g.perm.Setup){
198 json_set_err(FSL_JSON_E_DENIED,
199 "Changing another user's data requires "
200 "'a' or 's' privileges.");
201 }
202 }
203
204 blob_append(&sql, "UPDATE USER SET",-1 );
205 blob_append(&sql, " mtime=cast(strftime('%s') AS INTEGER)", -1);
206
207 if((uid>0) && zName
208 && zNameOrig && (zName != zNameOrig)
209 && (0!=strcmp(zNameOrig,zName))){
210 /* Only change the name if the uid is explicitly set and name
211 would actually change. */
212 if(!g.perm.Admin && !g.perm.Setup) {
213 json_set_err( FSL_JSON_E_DENIED,
214 "Modifying user names requires 'a' or 's' privileges.");
215 goto error;
216 }
217 blob_appendf(&sql, ", login=%Q", zNameOrig);
218 ++gotFields;
219 }
220
221 if( zCap ){
222 blob_appendf(&sql, ", cap=%Q", zCap);
223 ++gotFields;
224 }
225
226 if( zPW ){
227 char * zPWHash = NULL;
228 ++gotFields;
229 zPWHash = sha1_shared_secret(zPW, zName, NULL);
230 blob_appendf(&sql, ", pw=%Q", zPWHash);
231 free(zPWHash);
232 }
233
234 if( zInfo ){
235 blob_appendf(&sql, ", info=%Q", zInfo);
236 ++gotFields;
237 }
238
239 if(!gotFields){
240 json_set_err( FSL_JSON_E_MISSING_ARGS,
241 "Required user data are missing.");
242 goto error;
243 }
244 blob_append(&sql, " WHERE", -1);
245 assert(uid>0);
246 blob_appendf(&sql, " uid=%d", uid);
 
 
 
247 free( zNameFree );
248 /*puts(blob_str(&sql));*/
249 db_prepare(&q, "%s", blob_str(&sql));
250 blob_reset(&sql);
251 db_exec(&q);
252 db_finalize(&q);
253 return 0;
254
255 error:
256 assert(0 != g.json.resultCode);
257 free(zNameFree);
258 blob_reset(&sql);
259 return g.json.resultCode;
260 }
261
262
263 /*
264 ** Don't use - not yet finished.
265
+3 -1
--- src/login.c
+++ src/login.c
@@ -227,11 +227,13 @@
227227
** subsequently stored in user.cookie for later validation.
228228
**
229229
** The returned memory should be free()d after use.
230230
*/
231231
char * login_gen_user_cookie_value(char const *zUsername, char const * zHash){
232
- char *zCode = abbreviated_project_code(db_get("project-code",""));
232
+ char * zProjCode = db_get("project-code",NULL);
233
+ char *zCode = abbreviated_project_code(zProjCode);
234
+ free(zProjCode);
233235
assert((zUsername && *zUsername) && "Invalid user data.");
234236
return mprintf("%s/%z/%s", zHash, zCode, zUsername);
235237
}
236238
237239
/*
238240
--- src/login.c
+++ src/login.c
@@ -227,11 +227,13 @@
227 ** subsequently stored in user.cookie for later validation.
228 **
229 ** The returned memory should be free()d after use.
230 */
231 char * login_gen_user_cookie_value(char const *zUsername, char const * zHash){
232 char *zCode = abbreviated_project_code(db_get("project-code",""));
 
 
233 assert((zUsername && *zUsername) && "Invalid user data.");
234 return mprintf("%s/%z/%s", zHash, zCode, zUsername);
235 }
236
237 /*
238
--- src/login.c
+++ src/login.c
@@ -227,11 +227,13 @@
227 ** subsequently stored in user.cookie for later validation.
228 **
229 ** The returned memory should be free()d after use.
230 */
231 char * login_gen_user_cookie_value(char const *zUsername, char const * zHash){
232 char * zProjCode = db_get("project-code",NULL);
233 char *zCode = abbreviated_project_code(zProjCode);
234 free(zProjCode);
235 assert((zUsername && *zUsername) && "Invalid user data.");
236 return mprintf("%s/%z/%s", zHash, zCode, zUsername);
237 }
238
239 /*
240

Keyboard Shortcuts

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