Fossil SCM

Improvements to web-based user management.

drh 2007-07-21 19:32 trunk
Commit 916b6e4b3b701915f2670ce40e776abbd05f71d0
+16 -5
--- src/db.c
+++ src/db.c
@@ -572,23 +572,34 @@
572572
** fall back to the -R or --repository option.
573573
**
574574
** Error out if the repository cannot be opened.
575575
*/
576576
void db_find_and_open_repository(void){
577
- db_open_repository(find_option("repository", "R", 1));
578
- if( g.repositoryOpen==0 ){
579
- fossil_fatal("use --repository or -R to specific the repository database");
577
+ char *zRep = find_option("repository", "R", 1);
578
+ if( zRep==0 ){
579
+ if( db_open_local()==0 ){
580
+ goto rep_not_found;
581
+ }
582
+ zRep = db_lget("repository", 0);
583
+ if( zRep==0 ){
584
+ goto rep_not_found;
585
+ }
586
+ }
587
+ db_open_repository(zRep);
588
+ if( g.repositoryOpen ){
589
+ return;
580590
}
591
+rep_not_found:
592
+ fossil_fatal("use --repository or -R to specific the repository database");
581593
}
582594
583595
/*
584596
** Open the local database. If unable, exit with an error.
585597
*/
586598
void db_must_be_within_tree(void){
587599
if( db_open_local()==0 ){
588
- fprintf(stderr,"%s: not within an open checkout\n", g.argv[0]);
589
- exit(1);
600
+ fossil_fatal("not within an open checkout");
590601
}
591602
db_open_repository(0);
592603
}
593604
594605
/*
595606
--- src/db.c
+++ src/db.c
@@ -572,23 +572,34 @@
572 ** fall back to the -R or --repository option.
573 **
574 ** Error out if the repository cannot be opened.
575 */
576 void db_find_and_open_repository(void){
577 db_open_repository(find_option("repository", "R", 1));
578 if( g.repositoryOpen==0 ){
579 fossil_fatal("use --repository or -R to specific the repository database");
 
 
 
 
 
 
 
 
 
 
580 }
 
 
581 }
582
583 /*
584 ** Open the local database. If unable, exit with an error.
585 */
586 void db_must_be_within_tree(void){
587 if( db_open_local()==0 ){
588 fprintf(stderr,"%s: not within an open checkout\n", g.argv[0]);
589 exit(1);
590 }
591 db_open_repository(0);
592 }
593
594 /*
595
--- src/db.c
+++ src/db.c
@@ -572,23 +572,34 @@
572 ** fall back to the -R or --repository option.
573 **
574 ** Error out if the repository cannot be opened.
575 */
576 void db_find_and_open_repository(void){
577 char *zRep = find_option("repository", "R", 1);
578 if( zRep==0 ){
579 if( db_open_local()==0 ){
580 goto rep_not_found;
581 }
582 zRep = db_lget("repository", 0);
583 if( zRep==0 ){
584 goto rep_not_found;
585 }
586 }
587 db_open_repository(zRep);
588 if( g.repositoryOpen ){
589 return;
590 }
591 rep_not_found:
592 fossil_fatal("use --repository or -R to specific the repository database");
593 }
594
595 /*
596 ** Open the local database. If unable, exit with an error.
597 */
598 void db_must_be_within_tree(void){
599 if( db_open_local()==0 ){
600 fossil_fatal("not within an open checkout");
 
601 }
602 db_open_repository(0);
603 }
604
605 /*
606
+6 -3
--- src/login.c
+++ src/login.c
@@ -81,11 +81,11 @@
8181
}
8282
}
8383
if( zUsername!=0 && zPasswd!=0 && strcmp(zUsername,"anonymous")!=0 ){
8484
int uid = db_int(0,
8585
"SELECT uid FROM user"
86
- " WHERE login=%Q AND pw=%B", zUsername, zPasswd);
86
+ " WHERE login=%Q AND pw=%Q", zUsername, zPasswd);
8787
if( uid<=0 ){
8888
sleep(1);
8989
zErrMsg =
9090
@ <p><font color="red">
9191
@ You entered an unknown user or an incorrect password.
@@ -92,11 +92,11 @@
9292
@ </font></p>
9393
;
9494
}else{
9595
char *zCookie;
9696
const char *zCookieName = login_cookie_name();
97
- const char *zIpAddr = PD("REMOTE_ADDR","x");
97
+ const char *zIpAddr = PD("REMOTE_ADDR","nil");
9898
const char *zExpire = db_get("cookie-expire","8766");
9999
int expires;
100100
101101
zCookie = db_text(0, "SELECT '%d/' || hex(randomblob(25))", uid);
102102
expires = atoi(zExpire)*3600;
@@ -194,14 +194,15 @@
194194
** user credentials.
195195
*/
196196
zRemoteAddr = PD("REMOTE_ADDR","nil");
197197
if( strcmp(zRemoteAddr, "127.0.0.1")==0
198198
&& db_get_int("authenticate-localhost",1)==0 ){
199
- uid = db_int(0, "SELECT uid FROM user WHERE cap LIKE '%s%'");
199
+ uid = db_int(0, "SELECT uid FROM user WHERE cap LIKE '%%s%%'");
200200
g.zLogin = db_text("?", "SELECT login FROM user WHERE uid=%d", uid);
201201
zCap = "s";
202202
g.noPswd = 1;
203
+ g.isAnon = 0;
203204
}
204205
205206
/* Check the login cookie to see if it matches a known valid user.
206207
*/
207208
if( uid==0 && (zCookie = P(login_cookie_name()))!=0 ){
@@ -214,18 +215,20 @@
214215
atoi(zCookie), zCookie, zRemoteAddr
215216
);
216217
}
217218
218219
if( uid==0 ){
220
+ g.isAnon = 1;
219221
g.zLogin = "";
220222
zCap = db_get("nologin-cap","onrj");
221223
}else if( zCap==0 ){
222224
Stmt s;
223225
db_prepare(&s, "SELECT login, cap FROM user WHERE uid=%d", uid);
224226
db_step(&s);
225227
g.zLogin = db_column_malloc(&s, 0);
226228
zCap = db_column_malloc(&s, 1);
229
+ g.isAnon = 0;
227230
db_finalize(&s);
228231
}
229232
g.userUid = uid;
230233
231234
login_set_capabilities(zCap);
232235
--- src/login.c
+++ src/login.c
@@ -81,11 +81,11 @@
81 }
82 }
83 if( zUsername!=0 && zPasswd!=0 && strcmp(zUsername,"anonymous")!=0 ){
84 int uid = db_int(0,
85 "SELECT uid FROM user"
86 " WHERE login=%Q AND pw=%B", zUsername, zPasswd);
87 if( uid<=0 ){
88 sleep(1);
89 zErrMsg =
90 @ <p><font color="red">
91 @ You entered an unknown user or an incorrect password.
@@ -92,11 +92,11 @@
92 @ </font></p>
93 ;
94 }else{
95 char *zCookie;
96 const char *zCookieName = login_cookie_name();
97 const char *zIpAddr = PD("REMOTE_ADDR","x");
98 const char *zExpire = db_get("cookie-expire","8766");
99 int expires;
100
101 zCookie = db_text(0, "SELECT '%d/' || hex(randomblob(25))", uid);
102 expires = atoi(zExpire)*3600;
@@ -194,14 +194,15 @@
194 ** user credentials.
195 */
196 zRemoteAddr = PD("REMOTE_ADDR","nil");
197 if( strcmp(zRemoteAddr, "127.0.0.1")==0
198 && db_get_int("authenticate-localhost",1)==0 ){
199 uid = db_int(0, "SELECT uid FROM user WHERE cap LIKE '%s%'");
200 g.zLogin = db_text("?", "SELECT login FROM user WHERE uid=%d", uid);
201 zCap = "s";
202 g.noPswd = 1;
 
203 }
204
205 /* Check the login cookie to see if it matches a known valid user.
206 */
207 if( uid==0 && (zCookie = P(login_cookie_name()))!=0 ){
@@ -214,18 +215,20 @@
214 atoi(zCookie), zCookie, zRemoteAddr
215 );
216 }
217
218 if( uid==0 ){
 
219 g.zLogin = "";
220 zCap = db_get("nologin-cap","onrj");
221 }else if( zCap==0 ){
222 Stmt s;
223 db_prepare(&s, "SELECT login, cap FROM user WHERE uid=%d", uid);
224 db_step(&s);
225 g.zLogin = db_column_malloc(&s, 0);
226 zCap = db_column_malloc(&s, 1);
 
227 db_finalize(&s);
228 }
229 g.userUid = uid;
230
231 login_set_capabilities(zCap);
232
--- src/login.c
+++ src/login.c
@@ -81,11 +81,11 @@
81 }
82 }
83 if( zUsername!=0 && zPasswd!=0 && strcmp(zUsername,"anonymous")!=0 ){
84 int uid = db_int(0,
85 "SELECT uid FROM user"
86 " WHERE login=%Q AND pw=%Q", zUsername, zPasswd);
87 if( uid<=0 ){
88 sleep(1);
89 zErrMsg =
90 @ <p><font color="red">
91 @ You entered an unknown user or an incorrect password.
@@ -92,11 +92,11 @@
92 @ </font></p>
93 ;
94 }else{
95 char *zCookie;
96 const char *zCookieName = login_cookie_name();
97 const char *zIpAddr = PD("REMOTE_ADDR","nil");
98 const char *zExpire = db_get("cookie-expire","8766");
99 int expires;
100
101 zCookie = db_text(0, "SELECT '%d/' || hex(randomblob(25))", uid);
102 expires = atoi(zExpire)*3600;
@@ -194,14 +194,15 @@
194 ** user credentials.
195 */
196 zRemoteAddr = PD("REMOTE_ADDR","nil");
197 if( strcmp(zRemoteAddr, "127.0.0.1")==0
198 && db_get_int("authenticate-localhost",1)==0 ){
199 uid = db_int(0, "SELECT uid FROM user WHERE cap LIKE '%%s%%'");
200 g.zLogin = db_text("?", "SELECT login FROM user WHERE uid=%d", uid);
201 zCap = "s";
202 g.noPswd = 1;
203 g.isAnon = 0;
204 }
205
206 /* Check the login cookie to see if it matches a known valid user.
207 */
208 if( uid==0 && (zCookie = P(login_cookie_name()))!=0 ){
@@ -214,18 +215,20 @@
215 atoi(zCookie), zCookie, zRemoteAddr
216 );
217 }
218
219 if( uid==0 ){
220 g.isAnon = 1;
221 g.zLogin = "";
222 zCap = db_get("nologin-cap","onrj");
223 }else if( zCap==0 ){
224 Stmt s;
225 db_prepare(&s, "SELECT login, cap FROM user WHERE uid=%d", uid);
226 db_step(&s);
227 g.zLogin = db_column_malloc(&s, 0);
228 zCap = db_column_malloc(&s, 1);
229 g.isAnon = 0;
230 db_finalize(&s);
231 }
232 g.userUid = uid;
233
234 login_set_capabilities(zCap);
235
+281 -19
--- src/setup.c
+++ src/setup.c
@@ -77,50 +77,312 @@
7777
** Show a list of users. Clicking on any user jumps to the edit
7878
** screen for that user.
7979
*/
8080
void setup_ulist(void){
8181
Stmt s;
82
+
83
+ style_footer();
8284
login_check_credentials();
83
- if( !g.okSetup ){
85
+ if( !g.okWrite || g.isAnon ){
8486
login_needed();
87
+ return;
8588
}
8689
90
+ style_submenu_element("Add", "Add User", "setup_uedit");
8791
style_header();
88
-
89
- @ <table border="0" cellpadding="0" cellspacing="0">
90
- db_prepare(&s, "SELECT uid, login, cap FROM repuser ORDER BY login");
92
+ @ <h2>List Of Users</h2>
93
+ @ <table cellspacing=0 cellpadding=0 border=0>
94
+ @ <tr>
95
+ @ <th align="right"><nobr>User ID</nobr></th>
96
+ @ <th>&nbsp;&nbsp;&nbsp;Capabilities&nbsp;&nbsp;&nbsp;</th>
97
+ @ <th><nobr>Contact Info</nobr></th>
98
+ @ </tr>
99
+ db_prepare(&s, "SELECT uid, login, cap, info FROM user ORDER BY login");
91100
while( db_step(&s)==SQLITE_ROW ){
92
- @ <tr><td><a href="%s(g.zBaseURL)/setup_uedit?uid=%d(db_column_int(&s,0))">
93
- @ %h(db_column_text(&s,1))</a></td><td width="10"></td>
94
- @ <td>%h(db_column_text(&s,2))</td></tr>
101
+ @ <tr>
102
+ @ <td align="right">
103
+ if( g.okAdmin ){
104
+ @ <a href="setup_uedit?id=%d(db_column_int(&s,0))">
105
+ }
106
+ @ <nobr>%h(db_column_text(&s,1))</nobr>
107
+ if( g.okAdmin ){
108
+ @ </a>
109
+ }
110
+ @ </td>
111
+ @ <td align="center">%s(db_column_text(&s,2))</td>
112
+ @ <td align="center">%s(db_column_text(&s,3))</td>
113
+ @ </tr>
95114
}
96
- db_finalize(&s);
115
+ @ </table>
116
+ @ <p><hr>
117
+ @ <b>Notes:</b>
118
+ @ <ol>
119
+ @ <li><p>The permission flags are as follows:</p>
120
+ @ <table>
121
+ @ <tr><td>a</td><td width="10"></td>
122
+ @ <td>Admin: Create or delete users and ticket report formats</td></tr>
123
+ @ <tr><td>d</td><td></td>
124
+ @ <td>Delete: Erase anonymous wiki, tickets, and attachments</td></tr>
125
+ @ <tr><td>i</td><td></td>
126
+ @ <td>Check-in: Add new code to the repository</td></tr>
127
+ @ <tr><td>j</td><td></td><td>Read-Wiki: View wiki pages</td></tr>
128
+ @ <tr><td>k</td><td></td><td>Wiki: Create or modify wiki pages</td></tr>
129
+ @ <tr><td>n</td><td></td><td>New: Create new tickets</td></tr>
130
+ @ <tr><td>o</td><td></td>
131
+ @ <td>Check-out: Read code out of the repository</td></tr>
132
+ @ <tr><td>p</td><td></td><td>Password: Change password</td></tr>
133
+ @ <tr><td>q</td><td></td><td>Query: Create or edit report formats</td></tr>
134
+ @ <tr><td>r</td><td></td><td>Read: View tickets and change histories</td></tr>
135
+ @ <tr><td>s</td><td></td><td>Setup: Change CVSTrac options</td></tr>
136
+ @ <tr><td>w</td><td></td><td>Write: Edit tickets</td></tr>
97137
@ </table>
98
-
138
+ @ </p></li>
139
+ @
140
+ @ <li><p>
141
+ @ If a user named "<b>anonymous</b>" exists, then anyone can access
142
+ @ the server without having to log in. The permissions on the
143
+ @ anonymous user determine the access rights for anyone who is not
144
+ @ logged in.
145
+ @ </p></li>
146
+ @
147
+ @ </ol>
99148
style_footer();
100149
}
101150
102151
/*
103
-** WEBPAGE: setup_uedit
104
-**
105
-** Edit the user with REPUSER.UID equal to the "u" query parameter.
152
+** WEBPAGE: /setup_uedit
106153
*/
107
-void setup_uedit(void){
154
+void user_edit(void){
155
+ const char *zId, *zLogin, *zInfo, *zCap;
156
+ char *oaa, *oas, *oar, *oaw, *oan, *oai, *oaj, *oao, *oap ;
157
+ char *oak, *oad, *oaq;
158
+ int doWrite;
108159
int uid;
160
+ int higherUser = 0; /* True if user being edited is SETUP and the */
161
+ /* user doing the editing is ADMIN. Disallow editing */
109162
163
+ /* Must have ADMIN privleges to access this page
164
+ */
110165
login_check_credentials();
111
- if( !g.okSetup ){
112
- login_needed();
166
+ if( !g.okAdmin ){ login_needed(); return; }
167
+
168
+ /* Check to see if an ADMIN user is trying to edit a SETUP account.
169
+ ** Don't allow that.
170
+ */
171
+ zId = PD("id", "0");
172
+ uid = atoi(zId);
173
+ if( zId && !g.okSetup && uid>0 ){
174
+ char *zOldCaps;
175
+ zOldCaps = db_text(0, "SELECT caps FROM user WHERE uid=%d",uid);
176
+ higherUser = zOldCaps && strchr(zOldCaps,'s');
177
+ }
178
+
179
+ if( P("can") ){
180
+ cgi_redirect("setup_ulist");
181
+ return;
113182
}
114
- uid = atoi(PD("u","0"));
115
- if( uid<=0 ){
183
+
184
+ /* If we have all the necessary information, write the new or
185
+ ** modified user record. After writing the user record, redirect
186
+ ** to the page that displays a list of users.
187
+ */
188
+ doWrite = cgi_all("login","info","pw") && !higherUser;
189
+ if( doWrite ){
190
+ const char *zPw;
191
+ const char *zLogin;
192
+ char zCap[20];
193
+ int i = 0;
194
+ int aa = P("aa")!=0;
195
+ int ad = P("ad")!=0;
196
+ int ai = P("ai")!=0;
197
+ int aj = P("aj")!=0;
198
+ int ak = P("ak")!=0;
199
+ int an = P("an")!=0;
200
+ int ao = P("ao")!=0;
201
+ int ap = P("ap")!=0;
202
+ int aq = P("aq")!=0;
203
+ int ar = P("ar")!=0;
204
+ int as = g.okSetup && P("as")!=0;
205
+ int aw = P("aw")!=0;
206
+ if( as ) aa = 1;
207
+ if( aa ) ai = aw = ap = 1;
208
+ if( aw ) an = ar = 1;
209
+ if( ai ) ao = 1;
210
+ if( ak ) aj = 1;
211
+ if( aa ){ zCap[i++] = 'a'; }
212
+ if( ad ){ zCap[i++] = 'd'; }
213
+ if( ai ){ zCap[i++] = 'i'; }
214
+ if( aj ){ zCap[i++] = 'j'; }
215
+ if( ak ){ zCap[i++] = 'k'; }
216
+ if( an ){ zCap[i++] = 'n'; }
217
+ if( ao ){ zCap[i++] = 'o'; }
218
+ if( ap ){ zCap[i++] = 'p'; }
219
+ if( aq ){ zCap[i++] = 'q'; }
220
+ if( ar ){ zCap[i++] = 'r'; }
221
+ if( as ){ zCap[i++] = 's'; }
222
+ if( aw ){ zCap[i++] = 'w'; }
223
+
224
+ zCap[i] = 0;
225
+ zPw = P("pw");
226
+ if( zPw==0 || zPw[0]==0 ){
227
+ zPw = db_text(0, "SELECT pw FROM user WHERE uid=%d", uid);
228
+ }
229
+ zLogin = P("login");
230
+ if( uid>0 &&
231
+ db_exists("SELECT 1 FROM user WHERE login=%Q AND uid!=%d", zLogin, uid)
232
+ ){
233
+ style_header();
234
+ @ <font color="red">Login "%h(zLogin)" is already used by a different
235
+ @ user.</font>
236
+ @
237
+ @ <p><a href="setup_uedit?id=%d(uid))>[Bummer]</a></p>
238
+ style_footer();
239
+ return;
240
+ }
241
+ db_multi_exec(
242
+ "REPLACE INTO user(uid,login,info,pw,cap) "
243
+ "VALUES(nullif(%d,0),%Q,%Q,%Q,'%s')",
244
+ uid, P("login"), P("info"), zPw, zCap
245
+ );
116246
cgi_redirect("setup_ulist");
117
- assert(0);
247
+ return;
248
+ }
249
+
250
+ /* Load the existing information about the user, if any
251
+ */
252
+ zLogin = "";
253
+ zInfo = "";
254
+ zCap = "";
255
+ oaa = oad = oai = oaj = oak = oan = oao = oap = oaq = oar = oas = oaw = "";
256
+ if( uid ){
257
+ zLogin = db_text("", "SELECT login FROM user WHERE uid=%d", uid);
258
+ zInfo = db_text("", "SELECT info FROM user WHERE uid=%d", uid);
259
+ zCap = db_text("", "SELECT cap FROM user WHERE uid=%d", uid);
260
+ if( strchr(zCap, 'a') ) oaa = " checked";
261
+ if( strchr(zCap, 'd') ) oad = " checked";
262
+ if( strchr(zCap, 'i') ) oai = " checked";
263
+ if( strchr(zCap, 'j') ) oaj = " checked";
264
+ if( strchr(zCap, 'k') ) oak = " checked";
265
+ if( strchr(zCap, 'n') ) oan = " checked";
266
+ if( strchr(zCap, 'o') ) oao = " checked";
267
+ if( strchr(zCap, 'p') ) oap = " checked";
268
+ if( strchr(zCap, 'q') ) oaq = " checked";
269
+ if( strchr(zCap, 'r') ) oar = " checked";
270
+ if( strchr(zCap, 's') ) oas = " checked";
271
+ if( strchr(zCap, 'w') ) oaw = " checked";
118272
}
273
+
274
+ /* Begin generating the page
275
+ */
276
+ style_submenu_element("Cancel", "Cancel", "setup_ulist");
119277
style_header();
120
- style_footer();
278
+ if( uid ){
279
+ @ <h2>Edit User %h(zLogin)</h2>
280
+ }else{
281
+ @ <h2>Add A New User</h2>
282
+ }
283
+ @ <table align="left" hspace="20" vspace="10"><tr><td>
284
+ @ <form action="%s(g.zPath)" method="POST">
285
+ @ <table>
286
+ @ <tr>
287
+ @ <td align="right"><nobr>User ID:</nobr></td>
288
+ if( uid ){
289
+ @ <td>%d(uid) <input type="hidden" name="id" value="%d(uid)"></td>
290
+ }else{
291
+ @ <td>(new user)<input type="hidden" name="id" value=0></td>
292
+ }
293
+ @ </tr>
294
+ @ <tr>
295
+ @ <td align="right"><nobr>Login:</nobr></td>
296
+ @ <td><input type="text" name="login" value="%h(zLogin)"></td>
297
+ @ </tr>
298
+ @ <tr>
299
+ @ <td align="right"><nobr>Contact&nbsp;Info:</nobr></td>
300
+ @ <td><input type="text" name="info" size=40 value="%h(zInfo)"></td>
301
+ @ </tr>
302
+ @ <tr>
303
+ @ <td align="right" valign="top">Capabilities:</td>
304
+ @ <td>
305
+ @ <input type="checkbox" name="aa"%s(oaa)>Admin</input><br>
306
+ @ <input type="checkbox" name="ad"%s(oad)>Delete</input><br>
307
+ @ <input type="checkbox" name="ai"%s(oai)>Check-In</input><br>
308
+ @ <input type="checkbox" name="aj"%s(oaj)>Read Wiki</input><br>
309
+ @ <input type="checkbox" name="ak"%s(oak)>Write Wiki</input><br>
310
+ @ <input type="checkbox" name="an"%s(oan)>New Tkt</input><br>
311
+ @ <input type="checkbox" name="ao"%s(oao)>Check-Out</input><br>
312
+ @ <input type="checkbox" name="ap"%s(oap)>Password</input><br>
313
+ @ <input type="checkbox" name="aq"%s(oaq)>Query</input><br>
314
+ @ <input type="checkbox" name="ar"%s(oar)>Read</input><br>
315
+ if( g.okSetup ){
316
+ @ <input type="checkbox" name="as"%s(oas)>Setup</input><br>
317
+ }
318
+ @ <input type="checkbox" name="aw"%s(oaw)>Write</input>
319
+ @ </td>
320
+ @ </tr>
321
+ @ <tr>
322
+ @ <td align="right">Password:</td>
323
+ @ <td><input type="password" name="pw" value=""></td>
324
+ @ </tr>
325
+ if( !higherUser ){
326
+ @ <tr>
327
+ @ <td>&nbsp</td>
328
+ @ <td><input type="submit" name="submit" value="Apply Changes">
329
+ @ </tr>
330
+ }
331
+ @ </table></td></tr></table>
332
+ @ <p><b>Notes:</b></p>
333
+ @ <ol>
334
+ if( higherUser ){
335
+ @ <li><p>
336
+ @ User %h(zId) has Setup privileges and you only have Admin privileges
337
+ @ so you are not permitted to make changes to %h(zId).
338
+ @ </p></li>
339
+ @
340
+ }
341
+ @ <li><p>
342
+ @ The <b>Read</b> and <b>Write</b> privileges give the user the ability
343
+ @ to read and write tickets. The <b>New Tkt</b> capability means that
344
+ @ the user is able to create new tickets.
345
+ @ </p></li>
346
+ @
347
+ @ <li><p>
348
+ @ The <b>Delete</b> privilege give the user the ability to erase
349
+ @ wiki, tickets, and atttachments that have been added by anonymous
350
+ @ users. This capability is intended for deletion of spam.
351
+ @ </p></li>
352
+ @
353
+ @ <li><p>
354
+ @ The <b>Query</b> privilege allows the user to create or edit
355
+ @ report formats by specifying appropriate SQL. Users can run
356
+ @ existing reports without the Query privilege.
357
+ @ </p></li>
358
+ @
359
+ @ <li><p>
360
+ @ An <b>Admin</b> user can add other users, create new ticket report
361
+ @ formats, and change system defaults. But only the <b>Setup</b> user
362
+ @ is able to change the repository to
363
+ @ which this program is linked.
364
+ @ </p></li>
365
+ @
366
+ if( zId==0 || strcmp(zId,"anonymous")==0 ){
367
+ @ <li><p>
368
+ @ No login is required for user "<b>anonymous</b>". The capabilities
369
+ @ of this user are available to anyone without supplying a username or
370
+ @ password. To disable anonymous access, make sure there is no user
371
+ @ with an ID of <b>anonymous</b>.
372
+ @ </p></li>
373
+ @
374
+ @ <li><p>
375
+ @ The password for the "<b>anonymous</b>" user is used for anonymous
376
+ @ access. The recommended value for the anonymous password
377
+ @ is "anonymous".
378
+ @ </p></li>
379
+ }
380
+ @ </form>
381
+ style_footer();
121382
}
383
+
122384
123385
/*
124386
** Generate a checkbox for an attribute.
125387
*/
126388
static void onoff_attribute(
127389
--- src/setup.c
+++ src/setup.c
@@ -77,50 +77,312 @@
77 ** Show a list of users. Clicking on any user jumps to the edit
78 ** screen for that user.
79 */
80 void setup_ulist(void){
81 Stmt s;
 
 
82 login_check_credentials();
83 if( !g.okSetup ){
84 login_needed();
 
85 }
86
 
87 style_header();
88
89 @ <table border="0" cellpadding="0" cellspacing="0">
90 db_prepare(&s, "SELECT uid, login, cap FROM repuser ORDER BY login");
 
 
 
 
 
91 while( db_step(&s)==SQLITE_ROW ){
92 @ <tr><td><a href="%s(g.zBaseURL)/setup_uedit?uid=%d(db_column_int(&s,0))">
93 @ %h(db_column_text(&s,1))</a></td><td width="10"></td>
94 @ <td>%h(db_column_text(&s,2))</td></tr>
 
 
 
 
 
 
 
 
 
 
95 }
96 db_finalize(&s);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
97 @ </table>
98
 
 
 
 
 
 
 
 
 
99 style_footer();
100 }
101
102 /*
103 ** WEBPAGE: setup_uedit
104 **
105 ** Edit the user with REPUSER.UID equal to the "u" query parameter.
106 */
107 void setup_uedit(void){
 
 
 
 
108 int uid;
 
 
109
 
 
110 login_check_credentials();
111 if( !g.okSetup ){
112 login_needed();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
113 }
114 uid = atoi(PD("u","0"));
115 if( uid<=0 ){
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
116 cgi_redirect("setup_ulist");
117 assert(0);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
118 }
 
 
 
 
119 style_header();
120 style_footer();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
121 }
 
122
123 /*
124 ** Generate a checkbox for an attribute.
125 */
126 static void onoff_attribute(
127
--- src/setup.c
+++ src/setup.c
@@ -77,50 +77,312 @@
77 ** Show a list of users. Clicking on any user jumps to the edit
78 ** screen for that user.
79 */
80 void setup_ulist(void){
81 Stmt s;
82
83 style_footer();
84 login_check_credentials();
85 if( !g.okWrite || g.isAnon ){
86 login_needed();
87 return;
88 }
89
90 style_submenu_element("Add", "Add User", "setup_uedit");
91 style_header();
92 @ <h2>List Of Users</h2>
93 @ <table cellspacing=0 cellpadding=0 border=0>
94 @ <tr>
95 @ <th align="right"><nobr>User ID</nobr></th>
96 @ <th>&nbsp;&nbsp;&nbsp;Capabilities&nbsp;&nbsp;&nbsp;</th>
97 @ <th><nobr>Contact Info</nobr></th>
98 @ </tr>
99 db_prepare(&s, "SELECT uid, login, cap, info FROM user ORDER BY login");
100 while( db_step(&s)==SQLITE_ROW ){
101 @ <tr>
102 @ <td align="right">
103 if( g.okAdmin ){
104 @ <a href="setup_uedit?id=%d(db_column_int(&s,0))">
105 }
106 @ <nobr>%h(db_column_text(&s,1))</nobr>
107 if( g.okAdmin ){
108 @ </a>
109 }
110 @ </td>
111 @ <td align="center">%s(db_column_text(&s,2))</td>
112 @ <td align="center">%s(db_column_text(&s,3))</td>
113 @ </tr>
114 }
115 @ </table>
116 @ <p><hr>
117 @ <b>Notes:</b>
118 @ <ol>
119 @ <li><p>The permission flags are as follows:</p>
120 @ <table>
121 @ <tr><td>a</td><td width="10"></td>
122 @ <td>Admin: Create or delete users and ticket report formats</td></tr>
123 @ <tr><td>d</td><td></td>
124 @ <td>Delete: Erase anonymous wiki, tickets, and attachments</td></tr>
125 @ <tr><td>i</td><td></td>
126 @ <td>Check-in: Add new code to the repository</td></tr>
127 @ <tr><td>j</td><td></td><td>Read-Wiki: View wiki pages</td></tr>
128 @ <tr><td>k</td><td></td><td>Wiki: Create or modify wiki pages</td></tr>
129 @ <tr><td>n</td><td></td><td>New: Create new tickets</td></tr>
130 @ <tr><td>o</td><td></td>
131 @ <td>Check-out: Read code out of the repository</td></tr>
132 @ <tr><td>p</td><td></td><td>Password: Change password</td></tr>
133 @ <tr><td>q</td><td></td><td>Query: Create or edit report formats</td></tr>
134 @ <tr><td>r</td><td></td><td>Read: View tickets and change histories</td></tr>
135 @ <tr><td>s</td><td></td><td>Setup: Change CVSTrac options</td></tr>
136 @ <tr><td>w</td><td></td><td>Write: Edit tickets</td></tr>
137 @ </table>
138 @ </p></li>
139 @
140 @ <li><p>
141 @ If a user named "<b>anonymous</b>" exists, then anyone can access
142 @ the server without having to log in. The permissions on the
143 @ anonymous user determine the access rights for anyone who is not
144 @ logged in.
145 @ </p></li>
146 @
147 @ </ol>
148 style_footer();
149 }
150
151 /*
152 ** WEBPAGE: /setup_uedit
 
 
153 */
154 void user_edit(void){
155 const char *zId, *zLogin, *zInfo, *zCap;
156 char *oaa, *oas, *oar, *oaw, *oan, *oai, *oaj, *oao, *oap ;
157 char *oak, *oad, *oaq;
158 int doWrite;
159 int uid;
160 int higherUser = 0; /* True if user being edited is SETUP and the */
161 /* user doing the editing is ADMIN. Disallow editing */
162
163 /* Must have ADMIN privleges to access this page
164 */
165 login_check_credentials();
166 if( !g.okAdmin ){ login_needed(); return; }
167
168 /* Check to see if an ADMIN user is trying to edit a SETUP account.
169 ** Don't allow that.
170 */
171 zId = PD("id", "0");
172 uid = atoi(zId);
173 if( zId && !g.okSetup && uid>0 ){
174 char *zOldCaps;
175 zOldCaps = db_text(0, "SELECT caps FROM user WHERE uid=%d",uid);
176 higherUser = zOldCaps && strchr(zOldCaps,'s');
177 }
178
179 if( P("can") ){
180 cgi_redirect("setup_ulist");
181 return;
182 }
183
184 /* If we have all the necessary information, write the new or
185 ** modified user record. After writing the user record, redirect
186 ** to the page that displays a list of users.
187 */
188 doWrite = cgi_all("login","info","pw") && !higherUser;
189 if( doWrite ){
190 const char *zPw;
191 const char *zLogin;
192 char zCap[20];
193 int i = 0;
194 int aa = P("aa")!=0;
195 int ad = P("ad")!=0;
196 int ai = P("ai")!=0;
197 int aj = P("aj")!=0;
198 int ak = P("ak")!=0;
199 int an = P("an")!=0;
200 int ao = P("ao")!=0;
201 int ap = P("ap")!=0;
202 int aq = P("aq")!=0;
203 int ar = P("ar")!=0;
204 int as = g.okSetup && P("as")!=0;
205 int aw = P("aw")!=0;
206 if( as ) aa = 1;
207 if( aa ) ai = aw = ap = 1;
208 if( aw ) an = ar = 1;
209 if( ai ) ao = 1;
210 if( ak ) aj = 1;
211 if( aa ){ zCap[i++] = 'a'; }
212 if( ad ){ zCap[i++] = 'd'; }
213 if( ai ){ zCap[i++] = 'i'; }
214 if( aj ){ zCap[i++] = 'j'; }
215 if( ak ){ zCap[i++] = 'k'; }
216 if( an ){ zCap[i++] = 'n'; }
217 if( ao ){ zCap[i++] = 'o'; }
218 if( ap ){ zCap[i++] = 'p'; }
219 if( aq ){ zCap[i++] = 'q'; }
220 if( ar ){ zCap[i++] = 'r'; }
221 if( as ){ zCap[i++] = 's'; }
222 if( aw ){ zCap[i++] = 'w'; }
223
224 zCap[i] = 0;
225 zPw = P("pw");
226 if( zPw==0 || zPw[0]==0 ){
227 zPw = db_text(0, "SELECT pw FROM user WHERE uid=%d", uid);
228 }
229 zLogin = P("login");
230 if( uid>0 &&
231 db_exists("SELECT 1 FROM user WHERE login=%Q AND uid!=%d", zLogin, uid)
232 ){
233 style_header();
234 @ <font color="red">Login "%h(zLogin)" is already used by a different
235 @ user.</font>
236 @
237 @ <p><a href="setup_uedit?id=%d(uid))>[Bummer]</a></p>
238 style_footer();
239 return;
240 }
241 db_multi_exec(
242 "REPLACE INTO user(uid,login,info,pw,cap) "
243 "VALUES(nullif(%d,0),%Q,%Q,%Q,'%s')",
244 uid, P("login"), P("info"), zPw, zCap
245 );
246 cgi_redirect("setup_ulist");
247 return;
248 }
249
250 /* Load the existing information about the user, if any
251 */
252 zLogin = "";
253 zInfo = "";
254 zCap = "";
255 oaa = oad = oai = oaj = oak = oan = oao = oap = oaq = oar = oas = oaw = "";
256 if( uid ){
257 zLogin = db_text("", "SELECT login FROM user WHERE uid=%d", uid);
258 zInfo = db_text("", "SELECT info FROM user WHERE uid=%d", uid);
259 zCap = db_text("", "SELECT cap FROM user WHERE uid=%d", uid);
260 if( strchr(zCap, 'a') ) oaa = " checked";
261 if( strchr(zCap, 'd') ) oad = " checked";
262 if( strchr(zCap, 'i') ) oai = " checked";
263 if( strchr(zCap, 'j') ) oaj = " checked";
264 if( strchr(zCap, 'k') ) oak = " checked";
265 if( strchr(zCap, 'n') ) oan = " checked";
266 if( strchr(zCap, 'o') ) oao = " checked";
267 if( strchr(zCap, 'p') ) oap = " checked";
268 if( strchr(zCap, 'q') ) oaq = " checked";
269 if( strchr(zCap, 'r') ) oar = " checked";
270 if( strchr(zCap, 's') ) oas = " checked";
271 if( strchr(zCap, 'w') ) oaw = " checked";
272 }
273
274 /* Begin generating the page
275 */
276 style_submenu_element("Cancel", "Cancel", "setup_ulist");
277 style_header();
278 if( uid ){
279 @ <h2>Edit User %h(zLogin)</h2>
280 }else{
281 @ <h2>Add A New User</h2>
282 }
283 @ <table align="left" hspace="20" vspace="10"><tr><td>
284 @ <form action="%s(g.zPath)" method="POST">
285 @ <table>
286 @ <tr>
287 @ <td align="right"><nobr>User ID:</nobr></td>
288 if( uid ){
289 @ <td>%d(uid) <input type="hidden" name="id" value="%d(uid)"></td>
290 }else{
291 @ <td>(new user)<input type="hidden" name="id" value=0></td>
292 }
293 @ </tr>
294 @ <tr>
295 @ <td align="right"><nobr>Login:</nobr></td>
296 @ <td><input type="text" name="login" value="%h(zLogin)"></td>
297 @ </tr>
298 @ <tr>
299 @ <td align="right"><nobr>Contact&nbsp;Info:</nobr></td>
300 @ <td><input type="text" name="info" size=40 value="%h(zInfo)"></td>
301 @ </tr>
302 @ <tr>
303 @ <td align="right" valign="top">Capabilities:</td>
304 @ <td>
305 @ <input type="checkbox" name="aa"%s(oaa)>Admin</input><br>
306 @ <input type="checkbox" name="ad"%s(oad)>Delete</input><br>
307 @ <input type="checkbox" name="ai"%s(oai)>Check-In</input><br>
308 @ <input type="checkbox" name="aj"%s(oaj)>Read Wiki</input><br>
309 @ <input type="checkbox" name="ak"%s(oak)>Write Wiki</input><br>
310 @ <input type="checkbox" name="an"%s(oan)>New Tkt</input><br>
311 @ <input type="checkbox" name="ao"%s(oao)>Check-Out</input><br>
312 @ <input type="checkbox" name="ap"%s(oap)>Password</input><br>
313 @ <input type="checkbox" name="aq"%s(oaq)>Query</input><br>
314 @ <input type="checkbox" name="ar"%s(oar)>Read</input><br>
315 if( g.okSetup ){
316 @ <input type="checkbox" name="as"%s(oas)>Setup</input><br>
317 }
318 @ <input type="checkbox" name="aw"%s(oaw)>Write</input>
319 @ </td>
320 @ </tr>
321 @ <tr>
322 @ <td align="right">Password:</td>
323 @ <td><input type="password" name="pw" value=""></td>
324 @ </tr>
325 if( !higherUser ){
326 @ <tr>
327 @ <td>&nbsp</td>
328 @ <td><input type="submit" name="submit" value="Apply Changes">
329 @ </tr>
330 }
331 @ </table></td></tr></table>
332 @ <p><b>Notes:</b></p>
333 @ <ol>
334 if( higherUser ){
335 @ <li><p>
336 @ User %h(zId) has Setup privileges and you only have Admin privileges
337 @ so you are not permitted to make changes to %h(zId).
338 @ </p></li>
339 @
340 }
341 @ <li><p>
342 @ The <b>Read</b> and <b>Write</b> privileges give the user the ability
343 @ to read and write tickets. The <b>New Tkt</b> capability means that
344 @ the user is able to create new tickets.
345 @ </p></li>
346 @
347 @ <li><p>
348 @ The <b>Delete</b> privilege give the user the ability to erase
349 @ wiki, tickets, and atttachments that have been added by anonymous
350 @ users. This capability is intended for deletion of spam.
351 @ </p></li>
352 @
353 @ <li><p>
354 @ The <b>Query</b> privilege allows the user to create or edit
355 @ report formats by specifying appropriate SQL. Users can run
356 @ existing reports without the Query privilege.
357 @ </p></li>
358 @
359 @ <li><p>
360 @ An <b>Admin</b> user can add other users, create new ticket report
361 @ formats, and change system defaults. But only the <b>Setup</b> user
362 @ is able to change the repository to
363 @ which this program is linked.
364 @ </p></li>
365 @
366 if( zId==0 || strcmp(zId,"anonymous")==0 ){
367 @ <li><p>
368 @ No login is required for user "<b>anonymous</b>". The capabilities
369 @ of this user are available to anyone without supplying a username or
370 @ password. To disable anonymous access, make sure there is no user
371 @ with an ID of <b>anonymous</b>.
372 @ </p></li>
373 @
374 @ <li><p>
375 @ The password for the "<b>anonymous</b>" user is used for anonymous
376 @ access. The recommended value for the anonymous password
377 @ is "anonymous".
378 @ </p></li>
379 }
380 @ </form>
381 style_footer();
382 }
383
384
385 /*
386 ** Generate a checkbox for an attribute.
387 */
388 static void onoff_attribute(
389
+2 -2
--- src/style.c
+++ src/style.c
@@ -69,11 +69,11 @@
6969
/*
7070
** Draw the header.
7171
*/
7272
void style_header(void){
7373
const char *zLogInOut = "Logout";
74
- /* login_check_credentials(); */
74
+ login_check_credentials();
7575
@ <html>
7676
@ <body bgcolor="white">
7777
@ <hr size="1">
7878
@ <table border="0" cellpadding="0" cellspacing="0" width="100%%">
7979
@ <tr><td valign="top" align="left">
@@ -104,11 +104,11 @@
104104
struct Submenu *p = &aSubmenu[i];
105105
char *zTail = i<nSubmenu-1 ? " | " : "";
106106
if( p->zLink==0 ){
107107
@ <font color="#888888">%h(p->zLabel)</font> %s(zTail)
108108
}else{
109
- @ <a href="p->zLink">%h(p->zLabel)</a> %s(zTail)
109
+ @ <a href="%T(p->zLink)">%h(p->zLabel)</a> %s(zTail)
110110
}
111111
}
112112
}
113113
@ </td></tr></table>
114114
@ <hr size="1">
115115
--- src/style.c
+++ src/style.c
@@ -69,11 +69,11 @@
69 /*
70 ** Draw the header.
71 */
72 void style_header(void){
73 const char *zLogInOut = "Logout";
74 /* login_check_credentials(); */
75 @ <html>
76 @ <body bgcolor="white">
77 @ <hr size="1">
78 @ <table border="0" cellpadding="0" cellspacing="0" width="100%%">
79 @ <tr><td valign="top" align="left">
@@ -104,11 +104,11 @@
104 struct Submenu *p = &aSubmenu[i];
105 char *zTail = i<nSubmenu-1 ? " | " : "";
106 if( p->zLink==0 ){
107 @ <font color="#888888">%h(p->zLabel)</font> %s(zTail)
108 }else{
109 @ <a href="p->zLink">%h(p->zLabel)</a> %s(zTail)
110 }
111 }
112 }
113 @ </td></tr></table>
114 @ <hr size="1">
115
--- src/style.c
+++ src/style.c
@@ -69,11 +69,11 @@
69 /*
70 ** Draw the header.
71 */
72 void style_header(void){
73 const char *zLogInOut = "Logout";
74 login_check_credentials();
75 @ <html>
76 @ <body bgcolor="white">
77 @ <hr size="1">
78 @ <table border="0" cellpadding="0" cellspacing="0" width="100%%">
79 @ <tr><td valign="top" align="left">
@@ -104,11 +104,11 @@
104 struct Submenu *p = &aSubmenu[i];
105 char *zTail = i<nSubmenu-1 ? " | " : "";
106 if( p->zLink==0 ){
107 @ <font color="#888888">%h(p->zLabel)</font> %s(zTail)
108 }else{
109 @ <a href="%T(p->zLink)">%h(p->zLabel)</a> %s(zTail)
110 }
111 }
112 }
113 @ </td></tr></table>
114 @ <hr size="1">
115
+24 -6
--- src/user.c
+++ src/user.c
@@ -106,15 +106,17 @@
106106
** COMMAND: user
107107
**
108108
** Dispatcher for various user subcommands.
109109
*/
110110
void user_cmd(void){
111
+ int n;
111112
db_find_and_open_repository();
112113
if( g.argc<3 ){
113
- usage("create|default|list|password ...");
114
+ usage("capabilities|default|list|new|password ...");
114115
}
115
- if( strcmp(g.argv[2],"create")==0 ){
116
+ n = strlen(g.argv[2]);
117
+ if( n>=2 && strncmp(g.argv[2],"new",n)==0 ){
116118
Blob passwd, login, contact;
117119
118120
prompt_user("login: ", &login);
119121
prompt_user("contact-info: ", &contact);
120122
get_passphrase("password: ", &passwd, 1);
@@ -121,27 +123,27 @@
121123
db_multi_exec(
122124
"INSERT INTO user(login,pw,cap,info)"
123125
"VALUES(%B,%B,'jnor',%B)",
124126
&login, &passwd, &contact
125127
);
126
- }else if( strcmp(g.argv[2],"default")==0 ){
128
+ }else if( n>=2 && strncmp(g.argv[2],"default",n)==0 ){
127129
user_select();
128130
if( g.argc==3 ){
129131
printf("%s\n", g.zLogin);
130132
}else if( g.localOpen ){
131133
db_lset("default-user", g.zLogin);
132134
}else{
133135
db_set("default-user", g.zLogin);
134136
}
135
- }else if( strcmp(g.argv[2],"list")==0 ){
137
+ }else if( n>=2 && strncmp(g.argv[2],"list",n)==0 ){
136138
Stmt q;
137139
db_prepare(&q, "SELECT login, info FROM user ORDER BY login");
138140
while( db_step(&q)==SQLITE_ROW ){
139141
printf("%-12s %s\n", db_column_text(&q, 0), db_column_text(&q, 1));
140142
}
141143
db_finalize(&q);
142
- }else if( strcmp(g.argv[2],"password")==0 ){
144
+ }else if( n>=2 && strncmp(g.argv[2],"password",2)==0 ){
143145
char *zPrompt;
144146
int uid;
145147
Blob pw;
146148
if( g.argc!=4 ) usage("user password USERNAME");
147149
uid = db_int(0, "SELECT uid FROM user WHERE login=%Q", g.argv[3]);
@@ -153,13 +155,29 @@
153155
if( blob_size(&pw)==0 ){
154156
printf("password unchanged\n");
155157
}else{
156158
db_multi_exec("UPDATE user SET pw=%B WHERE uid=%d", &pw, uid);
157159
}
160
+ }else if( n>=2 && strncmp(g.argv[2],"capabilities",2)==0 ){
161
+ int uid;
162
+ if( g.argc!=4 && g.argc!=5 ){
163
+ usage("user capabilities USERNAME ?PERMISSIONS?");
164
+ }
165
+ uid = db_int(0, "SELECT uid FROM user WHERE login=%Q", g.argv[3]);
166
+ if( uid==0 ){
167
+ fossil_fatal("no such user: %s", g.argv[3]);
168
+ }
169
+ if( g.argc==5 ){
170
+ db_multi_exec(
171
+ "UPDATE user SET cap=%Q WHERE uid=%d", g.argv[4],
172
+ uid
173
+ );
174
+ }
175
+ printf("%s\n", db_text(0, "SELECT cap FROM user WHERE uid=%d", uid));
158176
}else{
159177
fossil_panic("user subcommand should be one of: "
160
- "create default list password");
178
+ "capabilities default list new password");
161179
}
162180
}
163181
164182
/*
165183
** Attempt to set the user to zLogin
166184
--- src/user.c
+++ src/user.c
@@ -106,15 +106,17 @@
106 ** COMMAND: user
107 **
108 ** Dispatcher for various user subcommands.
109 */
110 void user_cmd(void){
 
111 db_find_and_open_repository();
112 if( g.argc<3 ){
113 usage("create|default|list|password ...");
114 }
115 if( strcmp(g.argv[2],"create")==0 ){
 
116 Blob passwd, login, contact;
117
118 prompt_user("login: ", &login);
119 prompt_user("contact-info: ", &contact);
120 get_passphrase("password: ", &passwd, 1);
@@ -121,27 +123,27 @@
121 db_multi_exec(
122 "INSERT INTO user(login,pw,cap,info)"
123 "VALUES(%B,%B,'jnor',%B)",
124 &login, &passwd, &contact
125 );
126 }else if( strcmp(g.argv[2],"default")==0 ){
127 user_select();
128 if( g.argc==3 ){
129 printf("%s\n", g.zLogin);
130 }else if( g.localOpen ){
131 db_lset("default-user", g.zLogin);
132 }else{
133 db_set("default-user", g.zLogin);
134 }
135 }else if( strcmp(g.argv[2],"list")==0 ){
136 Stmt q;
137 db_prepare(&q, "SELECT login, info FROM user ORDER BY login");
138 while( db_step(&q)==SQLITE_ROW ){
139 printf("%-12s %s\n", db_column_text(&q, 0), db_column_text(&q, 1));
140 }
141 db_finalize(&q);
142 }else if( strcmp(g.argv[2],"password")==0 ){
143 char *zPrompt;
144 int uid;
145 Blob pw;
146 if( g.argc!=4 ) usage("user password USERNAME");
147 uid = db_int(0, "SELECT uid FROM user WHERE login=%Q", g.argv[3]);
@@ -153,13 +155,29 @@
153 if( blob_size(&pw)==0 ){
154 printf("password unchanged\n");
155 }else{
156 db_multi_exec("UPDATE user SET pw=%B WHERE uid=%d", &pw, uid);
157 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
158 }else{
159 fossil_panic("user subcommand should be one of: "
160 "create default list password");
161 }
162 }
163
164 /*
165 ** Attempt to set the user to zLogin
166
--- src/user.c
+++ src/user.c
@@ -106,15 +106,17 @@
106 ** COMMAND: user
107 **
108 ** Dispatcher for various user subcommands.
109 */
110 void user_cmd(void){
111 int n;
112 db_find_and_open_repository();
113 if( g.argc<3 ){
114 usage("capabilities|default|list|new|password ...");
115 }
116 n = strlen(g.argv[2]);
117 if( n>=2 && strncmp(g.argv[2],"new",n)==0 ){
118 Blob passwd, login, contact;
119
120 prompt_user("login: ", &login);
121 prompt_user("contact-info: ", &contact);
122 get_passphrase("password: ", &passwd, 1);
@@ -121,27 +123,27 @@
123 db_multi_exec(
124 "INSERT INTO user(login,pw,cap,info)"
125 "VALUES(%B,%B,'jnor',%B)",
126 &login, &passwd, &contact
127 );
128 }else if( n>=2 && strncmp(g.argv[2],"default",n)==0 ){
129 user_select();
130 if( g.argc==3 ){
131 printf("%s\n", g.zLogin);
132 }else if( g.localOpen ){
133 db_lset("default-user", g.zLogin);
134 }else{
135 db_set("default-user", g.zLogin);
136 }
137 }else if( n>=2 && strncmp(g.argv[2],"list",n)==0 ){
138 Stmt q;
139 db_prepare(&q, "SELECT login, info FROM user ORDER BY login");
140 while( db_step(&q)==SQLITE_ROW ){
141 printf("%-12s %s\n", db_column_text(&q, 0), db_column_text(&q, 1));
142 }
143 db_finalize(&q);
144 }else if( n>=2 && strncmp(g.argv[2],"password",2)==0 ){
145 char *zPrompt;
146 int uid;
147 Blob pw;
148 if( g.argc!=4 ) usage("user password USERNAME");
149 uid = db_int(0, "SELECT uid FROM user WHERE login=%Q", g.argv[3]);
@@ -153,13 +155,29 @@
155 if( blob_size(&pw)==0 ){
156 printf("password unchanged\n");
157 }else{
158 db_multi_exec("UPDATE user SET pw=%B WHERE uid=%d", &pw, uid);
159 }
160 }else if( n>=2 && strncmp(g.argv[2],"capabilities",2)==0 ){
161 int uid;
162 if( g.argc!=4 && g.argc!=5 ){
163 usage("user capabilities USERNAME ?PERMISSIONS?");
164 }
165 uid = db_int(0, "SELECT uid FROM user WHERE login=%Q", g.argv[3]);
166 if( uid==0 ){
167 fossil_fatal("no such user: %s", g.argv[3]);
168 }
169 if( g.argc==5 ){
170 db_multi_exec(
171 "UPDATE user SET cap=%Q WHERE uid=%d", g.argv[4],
172 uid
173 );
174 }
175 printf("%s\n", db_text(0, "SELECT cap FROM user WHERE uid=%d", uid));
176 }else{
177 fossil_panic("user subcommand should be one of: "
178 "capabilities default list new password");
179 }
180 }
181
182 /*
183 ** Attempt to set the user to zLogin
184
+2 -2
--- src/xfer.c
+++ src/xfer.c
@@ -222,11 +222,11 @@
222222
blob_append(&combined, blob_buffer(&pw), blob_size(&pw));
223223
sha1sum_blob(&combined, &hash);
224224
rc = blob_compare(&hash, pSig);
225225
blob_reset(&hash);
226226
blob_reset(&combined);
227
- if( rc ){
227
+ if( rc==0 ){
228228
const char *zCap;
229229
zCap = db_column_text(&q, 1);
230230
login_set_capabilities(zCap);
231231
g.userUid = db_column_int(&q, 2);
232232
g.zLogin = mprintf("%b", pLogin);
@@ -394,11 +394,11 @@
394394
@ push %s(db_get("server-code", "x")) %s(db_get("project-code", "x"))
395395
db_multi_exec(
396396
"INSERT OR IGNORE INTO pending(rid) "
397397
"SELECT rid FROM blob WHERE size>=0"
398398
);
399
- }
399
+ }else
400400
401401
/* login USER NONCE SIGNATURE
402402
**
403403
** Check for a valid login. This has to happen before anything else.
404404
*/
405405
--- src/xfer.c
+++ src/xfer.c
@@ -222,11 +222,11 @@
222 blob_append(&combined, blob_buffer(&pw), blob_size(&pw));
223 sha1sum_blob(&combined, &hash);
224 rc = blob_compare(&hash, pSig);
225 blob_reset(&hash);
226 blob_reset(&combined);
227 if( rc ){
228 const char *zCap;
229 zCap = db_column_text(&q, 1);
230 login_set_capabilities(zCap);
231 g.userUid = db_column_int(&q, 2);
232 g.zLogin = mprintf("%b", pLogin);
@@ -394,11 +394,11 @@
394 @ push %s(db_get("server-code", "x")) %s(db_get("project-code", "x"))
395 db_multi_exec(
396 "INSERT OR IGNORE INTO pending(rid) "
397 "SELECT rid FROM blob WHERE size>=0"
398 );
399 }
400
401 /* login USER NONCE SIGNATURE
402 **
403 ** Check for a valid login. This has to happen before anything else.
404 */
405
--- src/xfer.c
+++ src/xfer.c
@@ -222,11 +222,11 @@
222 blob_append(&combined, blob_buffer(&pw), blob_size(&pw));
223 sha1sum_blob(&combined, &hash);
224 rc = blob_compare(&hash, pSig);
225 blob_reset(&hash);
226 blob_reset(&combined);
227 if( rc==0 ){
228 const char *zCap;
229 zCap = db_column_text(&q, 1);
230 login_set_capabilities(zCap);
231 g.userUid = db_column_int(&q, 2);
232 g.zLogin = mprintf("%b", pLogin);
@@ -394,11 +394,11 @@
394 @ push %s(db_get("server-code", "x")) %s(db_get("project-code", "x"))
395 db_multi_exec(
396 "INSERT OR IGNORE INTO pending(rid) "
397 "SELECT rid FROM blob WHERE size>=0"
398 );
399 }else
400
401 /* login USER NONCE SIGNATURE
402 **
403 ** Check for a valid login. This has to happen before anything else.
404 */
405

Keyboard Shortcuts

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