Fossil SCM

More checking of user permissions on the Security Audit page.

drh 2017-07-01 22:17 trunk
Commit 564e42dfe577d60983345042dea1d358f080151e31afa2edf366e51d96d10017
2 files changed +61 -7 +63 -48
--- src/security_audit.c
+++ src/security_audit.c
@@ -187,31 +187,85 @@
187187
@ Anonymous users can create or edit wiki, but moderator
188188
@ approval is required before the edits become permanent.
189189
}
190190
}
191191
192
- /* The push-unversioned privilege should only be provided to
192
+ /* Administrative privilege should only be provided to
193193
** specific individuals, not to entire classes of people.
194
+ ** And not too many people should have administrator privilege.
194195
*/
195196
z = db_text(0, "SELECT group_concat(login,' AND ') FROM user"
196
- " WHERE cap GLOB '*y*'"
197
+ " WHERE cap GLOB '*[as]*'"
197198
" AND login in ('anonymous','nobody','reader','developer')");
198199
if( z && z[0] ){
199200
@ <li><p>
200
- @ The "Write-Unver" privilege is granted to an entire class of users
201
+ @ Adminstrative privilege is granted to an entire class of users
201202
@ (%h(z)). Ideally, the Write-Unver privilege should only be
202203
@ granted to specific individuals.
203204
}
205
+ n = db_int(0,"SELECT count(*) FROM user WHERE cap GLOB '*[as]*'");
206
+ if( n==0 ){
207
+ @ <li><p>
208
+ @ No users have administrator privilege.
209
+ }else{
210
+ z = db_text(0,
211
+ "SELECT group_concat("
212
+ "printf('<a href=''setup_uedit?id=%%d''>%%s</a>',uid,login),"
213
+ "', ')"
214
+ " FROM user"
215
+ " WHERE cap GLOB '*[as]*'"
216
+ );
217
+ @ <li><p>
218
+ @ Users with administrator privilege are: %s(z)
219
+ fossil_free(z);
220
+ if( n>3 ){
221
+ @ <p><b>Caution</b>:
222
+ @ Administrator privilege is granted to
223
+ @ <a href='setup_ulist?with=as'>%d(n) users</a>.
224
+ @ Ideally, administator privilege ('s' or 'a') should only
225
+ @ be granted to one or two users.
226
+ }
227
+ }
204228
205
- /* Check to see if push-unversioned is granted to many people.
229
+ /* The push-unversioned privilege should only be provided to
230
+ ** specific individuals, not to entire classes of people.
231
+ ** And no too many people should have this privilege.
206232
*/
233
+ z = db_text(0,
234
+ "SELECT group_concat("
235
+ "printf('<a href=''setup_uedit?id=%%d''>%%s</a>',uid,login),"
236
+ "' and ')"
237
+ " FROM user"
238
+ " WHERE cap GLOB '*y*'"
239
+ " AND login in ('anonymous','nobody','reader','developer')"
240
+ );
241
+ if( z && z[0] ){
242
+ @ <li><p>
243
+ @ The "Write-Unver" privilege is granted to an entire class of users
244
+ @ (%s(z)). Ideally, the Write-Unver privilege should only be
245
+ @ granted to specific individuals.
246
+ fossil_free(z);
247
+ }
207248
n = db_int(0,"SELECT count(*) FROM user WHERE cap GLOB '*y*'");
208249
if( n>3 ){
209250
@ <li><p>
210
- @ The "Write-Unver" privilege is granted to %d(n) users.
211
- @ Ideally, the Write-Unver privilege should only
212
- @ be granted to one or two users.
251
+ }else if( n>0 ){
252
+ z = db_text(0,
253
+ "SELECT group_concat("
254
+ "printf('<a href=''setup_uedit?id=%%d''>%%s</a>',uid,login),', ')"
255
+ " FROM user WHERE cap GLOB '*y*'"
256
+ );
257
+ @ <li><p>
258
+ @ Users with "Write-Unver" privilege: %s(z)
259
+ fossil_free(z);
260
+ if( n>3 ){
261
+ @ <p><b>Caution:</b>
262
+ @ The "Write-Unver" privilege ('y') is granted to an excessive
263
+ @ number of users (%d(n)).
264
+ @ Ideally, the Write-Unver privilege should only
265
+ @ be granted to one or two users.
266
+ }
213267
}
214268
215269
/* Notify if REMOTE_USER or HTTP_AUTHENTICATION is used for login.
216270
*/
217271
if( db_get_boolean("remote_user_ok", 0) ){
218272
--- src/security_audit.c
+++ src/security_audit.c
@@ -187,31 +187,85 @@
187 @ Anonymous users can create or edit wiki, but moderator
188 @ approval is required before the edits become permanent.
189 }
190 }
191
192 /* The push-unversioned privilege should only be provided to
193 ** specific individuals, not to entire classes of people.
 
194 */
195 z = db_text(0, "SELECT group_concat(login,' AND ') FROM user"
196 " WHERE cap GLOB '*y*'"
197 " AND login in ('anonymous','nobody','reader','developer')");
198 if( z && z[0] ){
199 @ <li><p>
200 @ The "Write-Unver" privilege is granted to an entire class of users
201 @ (%h(z)). Ideally, the Write-Unver privilege should only be
202 @ granted to specific individuals.
203 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
204
205 /* Check to see if push-unversioned is granted to many people.
 
 
206 */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
207 n = db_int(0,"SELECT count(*) FROM user WHERE cap GLOB '*y*'");
208 if( n>3 ){
209 @ <li><p>
210 @ The "Write-Unver" privilege is granted to %d(n) users.
211 @ Ideally, the Write-Unver privilege should only
212 @ be granted to one or two users.
 
 
 
 
 
 
 
 
 
 
 
 
 
213 }
214
215 /* Notify if REMOTE_USER or HTTP_AUTHENTICATION is used for login.
216 */
217 if( db_get_boolean("remote_user_ok", 0) ){
218
--- src/security_audit.c
+++ src/security_audit.c
@@ -187,31 +187,85 @@
187 @ Anonymous users can create or edit wiki, but moderator
188 @ approval is required before the edits become permanent.
189 }
190 }
191
192 /* Administrative privilege should only be provided to
193 ** specific individuals, not to entire classes of people.
194 ** And not too many people should have administrator privilege.
195 */
196 z = db_text(0, "SELECT group_concat(login,' AND ') FROM user"
197 " WHERE cap GLOB '*[as]*'"
198 " AND login in ('anonymous','nobody','reader','developer')");
199 if( z && z[0] ){
200 @ <li><p>
201 @ Adminstrative privilege is granted to an entire class of users
202 @ (%h(z)). Ideally, the Write-Unver privilege should only be
203 @ granted to specific individuals.
204 }
205 n = db_int(0,"SELECT count(*) FROM user WHERE cap GLOB '*[as]*'");
206 if( n==0 ){
207 @ <li><p>
208 @ No users have administrator privilege.
209 }else{
210 z = db_text(0,
211 "SELECT group_concat("
212 "printf('<a href=''setup_uedit?id=%%d''>%%s</a>',uid,login),"
213 "', ')"
214 " FROM user"
215 " WHERE cap GLOB '*[as]*'"
216 );
217 @ <li><p>
218 @ Users with administrator privilege are: %s(z)
219 fossil_free(z);
220 if( n>3 ){
221 @ <p><b>Caution</b>:
222 @ Administrator privilege is granted to
223 @ <a href='setup_ulist?with=as'>%d(n) users</a>.
224 @ Ideally, administator privilege ('s' or 'a') should only
225 @ be granted to one or two users.
226 }
227 }
228
229 /* The push-unversioned privilege should only be provided to
230 ** specific individuals, not to entire classes of people.
231 ** And no too many people should have this privilege.
232 */
233 z = db_text(0,
234 "SELECT group_concat("
235 "printf('<a href=''setup_uedit?id=%%d''>%%s</a>',uid,login),"
236 "' and ')"
237 " FROM user"
238 " WHERE cap GLOB '*y*'"
239 " AND login in ('anonymous','nobody','reader','developer')"
240 );
241 if( z && z[0] ){
242 @ <li><p>
243 @ The "Write-Unver" privilege is granted to an entire class of users
244 @ (%s(z)). Ideally, the Write-Unver privilege should only be
245 @ granted to specific individuals.
246 fossil_free(z);
247 }
248 n = db_int(0,"SELECT count(*) FROM user WHERE cap GLOB '*y*'");
249 if( n>3 ){
250 @ <li><p>
251 }else if( n>0 ){
252 z = db_text(0,
253 "SELECT group_concat("
254 "printf('<a href=''setup_uedit?id=%%d''>%%s</a>',uid,login),', ')"
255 " FROM user WHERE cap GLOB '*y*'"
256 );
257 @ <li><p>
258 @ Users with "Write-Unver" privilege: %s(z)
259 fossil_free(z);
260 if( n>3 ){
261 @ <p><b>Caution:</b>
262 @ The "Write-Unver" privilege ('y') is granted to an excessive
263 @ number of users (%d(n)).
264 @ Ideally, the Write-Unver privilege should only
265 @ be granted to one or two users.
266 }
267 }
268
269 /* Notify if REMOTE_USER or HTTP_AUTHENTICATION is used for login.
270 */
271 if( db_get_boolean("remote_user_ok", 0) ){
272
+63 -48
--- src/setup.c
+++ src/setup.c
@@ -139,66 +139,75 @@
139139
/*
140140
** WEBPAGE: setup_ulist
141141
**
142142
** Show a list of users. Clicking on any user jumps to the edit
143143
** screen for that user. Requires Admin privileges.
144
+**
145
+** Query parameters:
146
+**
147
+** with=CAP Only show users that have one or more capabilities in CAP.
144148
*/
145149
void setup_ulist(void){
146150
Stmt s;
147151
double rNow;
152
+ const char *zWith = P("with");
148153
149154
login_check_credentials();
150155
if( !g.perm.Admin ){
151156
login_needed(0);
152157
return;
153158
}
154159
155
- style_submenu_element("Add", "setup_uedit");
156
- style_submenu_element("Log", "access_log");
157
- style_submenu_element("Help", "setup_ulist_notes");
158
- style_header("User List");
159
- @ <table border=1 cellpadding=2 cellspacing=0 class='userTable'>
160
- @ <thead><tr>
161
- @ <th>UID <th>Category
162
- @ <th>Capabilities (<a href='%R/setup_ucap_list'>key</a>)
163
- @ <th>Info <th>Last Change</tr></thead>
164
- @ <tbody>
165
- db_prepare(&s,
166
- "SELECT uid, login, cap, date(mtime,'unixepoch')"
167
- " FROM user"
168
- " WHERE login IN ('anonymous','nobody','developer','reader')"
169
- " ORDER BY login"
170
- );
171
- while( db_step(&s)==SQLITE_ROW ){
172
- int uid = db_column_int(&s, 0);
173
- const char *zLogin = db_column_text(&s, 1);
174
- const char *zCap = db_column_text(&s, 2);
175
- const char *zDate = db_column_text(&s, 4);
176
- @ <tr>
177
- @ <td><a href='setup_uedit?id=%d(uid)'>%d(uid)</a>
178
- @ <td><a href='setup_uedit?id=%d(uid)'>%h(zLogin)</a>
179
- @ <td>%h(zCap)
180
-
181
- if( fossil_strcmp(zLogin,"anonymous")==0 ){
182
- @ <td>All logged-in users
183
- }else if( fossil_strcmp(zLogin,"developer")==0 ){
184
- @ <td>Users with '<b>v</b>' capability
185
- }else if( fossil_strcmp(zLogin,"nobody")==0 ){
186
- @ <td>All users without login
187
- }else if( fossil_strcmp(zLogin,"reader")==0 ){
188
- @ <td>Users with '<b>u</b>' capability
189
- }else{
190
- @ <td>
191
- }
192
- if( zDate && zDate[0] ){
193
- @ <td>%h(zDate)
194
- }else{
195
- @ <td>
196
- }
197
- @ </tr>
198
- }
199
- db_finalize(&s);
160
+ if( zWith==0 || zWith[0]==0 ){
161
+ style_submenu_element("Add", "setup_uedit");
162
+ style_submenu_element("Log", "access_log");
163
+ style_submenu_element("Help", "setup_ulist_notes");
164
+ style_header("User List");
165
+ @ <table border=1 cellpadding=2 cellspacing=0 class='userTable'>
166
+ @ <thead><tr>
167
+ @ <th>UID <th>Category
168
+ @ <th>Capabilities (<a href='%R/setup_ucap_list'>key</a>)
169
+ @ <th>Info <th>Last Change</tr></thead>
170
+ @ <tbody>
171
+ db_prepare(&s,
172
+ "SELECT uid, login, cap, date(mtime,'unixepoch')"
173
+ " FROM user"
174
+ " WHERE login IN ('anonymous','nobody','developer','reader')"
175
+ " ORDER BY login"
176
+ );
177
+ while( db_step(&s)==SQLITE_ROW ){
178
+ int uid = db_column_int(&s, 0);
179
+ const char *zLogin = db_column_text(&s, 1);
180
+ const char *zCap = db_column_text(&s, 2);
181
+ const char *zDate = db_column_text(&s, 4);
182
+ @ <tr>
183
+ @ <td><a href='setup_uedit?id=%d(uid)'>%d(uid)</a>
184
+ @ <td><a href='setup_uedit?id=%d(uid)'>%h(zLogin)</a>
185
+ @ <td>%h(zCap)
186
+
187
+ if( fossil_strcmp(zLogin,"anonymous")==0 ){
188
+ @ <td>All logged-in users
189
+ }else if( fossil_strcmp(zLogin,"developer")==0 ){
190
+ @ <td>Users with '<b>v</b>' capability
191
+ }else if( fossil_strcmp(zLogin,"nobody")==0 ){
192
+ @ <td>All users without login
193
+ }else if( fossil_strcmp(zLogin,"reader")==0 ){
194
+ @ <td>Users with '<b>u</b>' capability
195
+ }else{
196
+ @ <td>
197
+ }
198
+ if( zDate && zDate[0] ){
199
+ @ <td>%h(zDate)
200
+ }else{
201
+ @ <td>
202
+ }
203
+ @ </tr>
204
+ }
205
+ db_finalize(&s);
206
+ }else{
207
+ style_header("Users With Capabilities \"%h\"", zWith);
208
+ }
200209
@ </tbody></table>
201210
@ <div class='section'>Users</div>
202211
@ <table border=1 cellpadding=2 cellspacing=0 class='userTable' id='userlist'>
203212
@ <thead><tr>
204213
@ <th>ID<th>Login Name<th>Caps<th>Info<th>Date<th>Expire<th>Last Login</tr></thead>
@@ -213,20 +222,25 @@
213222
" SELECT uname, mtime FROM accesslog WHERE success"
214223
" UNION ALL"
215224
" SELECT login AS uname, rcvfrom.mtime AS mtime FROM rcvfrom JOIN user USING(uid))"
216225
" GROUP BY 1;"
217226
);
227
+ }
228
+ if( zWith && zWith[0] ){
229
+ zWith = mprintf(" AND cap GLOB '*[%q]*'", zWith);
230
+ }else{
231
+ zWith = "";
218232
}
219233
db_prepare(&s,
220234
"SELECT uid, login, cap, info, date(mtime,'unixepoch'), lower(login) AS sortkey, "
221235
" CASE WHEN info LIKE '%%expires 20%%'"
222236
" THEN substr(info,instr(lower(info),'expires')+8,10)"
223237
" END AS exp,"
224238
"atime"
225239
" FROM user LEFT JOIN lastAccess ON login=uname"
226
- " WHERE login NOT IN ('anonymous','nobody','developer','reader')"
227
- " ORDER BY sortkey"
240
+ " WHERE login NOT IN ('anonymous','nobody','developer','reader') %s"
241
+ " ORDER BY sortkey", zWith/*safe-for-%s*/
228242
);
229243
rNow = db_double(0.0, "SELECT julianday('now');");
230244
while( db_step(&s)==SQLITE_ROW ){
231245
int uid = db_column_int(&s, 0);
232246
const char *zLogin = db_column_text(&s, 1);
@@ -425,11 +439,12 @@
425439
zOldCaps = db_text(0, "SELECT cap FROM user WHERE uid=%d",uid);
426440
higherUser = zOldCaps && strchr(zOldCaps,'s');
427441
}
428442
429443
if( P("can") ){
430
- cgi_redirect("setup_ulist"); /* User pressed the Cancel button */
444
+ /* User pressed the cancel button */
445
+ cgi_redirect("setup_ulist");
431446
return;
432447
}
433448
434449
/* If we have all the necessary information, write the new or
435450
** modified user record. After writing the user record, redirect
436451
--- src/setup.c
+++ src/setup.c
@@ -139,66 +139,75 @@
139 /*
140 ** WEBPAGE: setup_ulist
141 **
142 ** Show a list of users. Clicking on any user jumps to the edit
143 ** screen for that user. Requires Admin privileges.
 
 
 
 
144 */
145 void setup_ulist(void){
146 Stmt s;
147 double rNow;
 
148
149 login_check_credentials();
150 if( !g.perm.Admin ){
151 login_needed(0);
152 return;
153 }
154
155 style_submenu_element("Add", "setup_uedit");
156 style_submenu_element("Log", "access_log");
157 style_submenu_element("Help", "setup_ulist_notes");
158 style_header("User List");
159 @ <table border=1 cellpadding=2 cellspacing=0 class='userTable'>
160 @ <thead><tr>
161 @ <th>UID <th>Category
162 @ <th>Capabilities (<a href='%R/setup_ucap_list'>key</a>)
163 @ <th>Info <th>Last Change</tr></thead>
164 @ <tbody>
165 db_prepare(&s,
166 "SELECT uid, login, cap, date(mtime,'unixepoch')"
167 " FROM user"
168 " WHERE login IN ('anonymous','nobody','developer','reader')"
169 " ORDER BY login"
170 );
171 while( db_step(&s)==SQLITE_ROW ){
172 int uid = db_column_int(&s, 0);
173 const char *zLogin = db_column_text(&s, 1);
174 const char *zCap = db_column_text(&s, 2);
175 const char *zDate = db_column_text(&s, 4);
176 @ <tr>
177 @ <td><a href='setup_uedit?id=%d(uid)'>%d(uid)</a>
178 @ <td><a href='setup_uedit?id=%d(uid)'>%h(zLogin)</a>
179 @ <td>%h(zCap)
180
181 if( fossil_strcmp(zLogin,"anonymous")==0 ){
182 @ <td>All logged-in users
183 }else if( fossil_strcmp(zLogin,"developer")==0 ){
184 @ <td>Users with '<b>v</b>' capability
185 }else if( fossil_strcmp(zLogin,"nobody")==0 ){
186 @ <td>All users without login
187 }else if( fossil_strcmp(zLogin,"reader")==0 ){
188 @ <td>Users with '<b>u</b>' capability
189 }else{
190 @ <td>
191 }
192 if( zDate && zDate[0] ){
193 @ <td>%h(zDate)
194 }else{
195 @ <td>
196 }
197 @ </tr>
198 }
199 db_finalize(&s);
 
 
 
 
200 @ </tbody></table>
201 @ <div class='section'>Users</div>
202 @ <table border=1 cellpadding=2 cellspacing=0 class='userTable' id='userlist'>
203 @ <thead><tr>
204 @ <th>ID<th>Login Name<th>Caps<th>Info<th>Date<th>Expire<th>Last Login</tr></thead>
@@ -213,20 +222,25 @@
213 " SELECT uname, mtime FROM accesslog WHERE success"
214 " UNION ALL"
215 " SELECT login AS uname, rcvfrom.mtime AS mtime FROM rcvfrom JOIN user USING(uid))"
216 " GROUP BY 1;"
217 );
 
 
 
 
 
218 }
219 db_prepare(&s,
220 "SELECT uid, login, cap, info, date(mtime,'unixepoch'), lower(login) AS sortkey, "
221 " CASE WHEN info LIKE '%%expires 20%%'"
222 " THEN substr(info,instr(lower(info),'expires')+8,10)"
223 " END AS exp,"
224 "atime"
225 " FROM user LEFT JOIN lastAccess ON login=uname"
226 " WHERE login NOT IN ('anonymous','nobody','developer','reader')"
227 " ORDER BY sortkey"
228 );
229 rNow = db_double(0.0, "SELECT julianday('now');");
230 while( db_step(&s)==SQLITE_ROW ){
231 int uid = db_column_int(&s, 0);
232 const char *zLogin = db_column_text(&s, 1);
@@ -425,11 +439,12 @@
425 zOldCaps = db_text(0, "SELECT cap FROM user WHERE uid=%d",uid);
426 higherUser = zOldCaps && strchr(zOldCaps,'s');
427 }
428
429 if( P("can") ){
430 cgi_redirect("setup_ulist"); /* User pressed the Cancel button */
 
431 return;
432 }
433
434 /* If we have all the necessary information, write the new or
435 ** modified user record. After writing the user record, redirect
436
--- src/setup.c
+++ src/setup.c
@@ -139,66 +139,75 @@
139 /*
140 ** WEBPAGE: setup_ulist
141 **
142 ** Show a list of users. Clicking on any user jumps to the edit
143 ** screen for that user. Requires Admin privileges.
144 **
145 ** Query parameters:
146 **
147 ** with=CAP Only show users that have one or more capabilities in CAP.
148 */
149 void setup_ulist(void){
150 Stmt s;
151 double rNow;
152 const char *zWith = P("with");
153
154 login_check_credentials();
155 if( !g.perm.Admin ){
156 login_needed(0);
157 return;
158 }
159
160 if( zWith==0 || zWith[0]==0 ){
161 style_submenu_element("Add", "setup_uedit");
162 style_submenu_element("Log", "access_log");
163 style_submenu_element("Help", "setup_ulist_notes");
164 style_header("User List");
165 @ <table border=1 cellpadding=2 cellspacing=0 class='userTable'>
166 @ <thead><tr>
167 @ <th>UID <th>Category
168 @ <th>Capabilities (<a href='%R/setup_ucap_list'>key</a>)
169 @ <th>Info <th>Last Change</tr></thead>
170 @ <tbody>
171 db_prepare(&s,
172 "SELECT uid, login, cap, date(mtime,'unixepoch')"
173 " FROM user"
174 " WHERE login IN ('anonymous','nobody','developer','reader')"
175 " ORDER BY login"
176 );
177 while( db_step(&s)==SQLITE_ROW ){
178 int uid = db_column_int(&s, 0);
179 const char *zLogin = db_column_text(&s, 1);
180 const char *zCap = db_column_text(&s, 2);
181 const char *zDate = db_column_text(&s, 4);
182 @ <tr>
183 @ <td><a href='setup_uedit?id=%d(uid)'>%d(uid)</a>
184 @ <td><a href='setup_uedit?id=%d(uid)'>%h(zLogin)</a>
185 @ <td>%h(zCap)
186
187 if( fossil_strcmp(zLogin,"anonymous")==0 ){
188 @ <td>All logged-in users
189 }else if( fossil_strcmp(zLogin,"developer")==0 ){
190 @ <td>Users with '<b>v</b>' capability
191 }else if( fossil_strcmp(zLogin,"nobody")==0 ){
192 @ <td>All users without login
193 }else if( fossil_strcmp(zLogin,"reader")==0 ){
194 @ <td>Users with '<b>u</b>' capability
195 }else{
196 @ <td>
197 }
198 if( zDate && zDate[0] ){
199 @ <td>%h(zDate)
200 }else{
201 @ <td>
202 }
203 @ </tr>
204 }
205 db_finalize(&s);
206 }else{
207 style_header("Users With Capabilities \"%h\"", zWith);
208 }
209 @ </tbody></table>
210 @ <div class='section'>Users</div>
211 @ <table border=1 cellpadding=2 cellspacing=0 class='userTable' id='userlist'>
212 @ <thead><tr>
213 @ <th>ID<th>Login Name<th>Caps<th>Info<th>Date<th>Expire<th>Last Login</tr></thead>
@@ -213,20 +222,25 @@
222 " SELECT uname, mtime FROM accesslog WHERE success"
223 " UNION ALL"
224 " SELECT login AS uname, rcvfrom.mtime AS mtime FROM rcvfrom JOIN user USING(uid))"
225 " GROUP BY 1;"
226 );
227 }
228 if( zWith && zWith[0] ){
229 zWith = mprintf(" AND cap GLOB '*[%q]*'", zWith);
230 }else{
231 zWith = "";
232 }
233 db_prepare(&s,
234 "SELECT uid, login, cap, info, date(mtime,'unixepoch'), lower(login) AS sortkey, "
235 " CASE WHEN info LIKE '%%expires 20%%'"
236 " THEN substr(info,instr(lower(info),'expires')+8,10)"
237 " END AS exp,"
238 "atime"
239 " FROM user LEFT JOIN lastAccess ON login=uname"
240 " WHERE login NOT IN ('anonymous','nobody','developer','reader') %s"
241 " ORDER BY sortkey", zWith/*safe-for-%s*/
242 );
243 rNow = db_double(0.0, "SELECT julianday('now');");
244 while( db_step(&s)==SQLITE_ROW ){
245 int uid = db_column_int(&s, 0);
246 const char *zLogin = db_column_text(&s, 1);
@@ -425,11 +439,12 @@
439 zOldCaps = db_text(0, "SELECT cap FROM user WHERE uid=%d",uid);
440 higherUser = zOldCaps && strchr(zOldCaps,'s');
441 }
442
443 if( P("can") ){
444 /* User pressed the cancel button */
445 cgi_redirect("setup_ulist");
446 return;
447 }
448
449 /* If we have all the necessary information, write the new or
450 ** modified user record. After writing the user record, redirect
451

Keyboard Shortcuts

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