Fossil SCM

Change the user-elevation notification subscription to a user-perms-changed notification, per /chat disucssion.

stephan 2025-04-08 15:58 trunk
Commit 36f72c08727ddb74790e600632b2c481559e282d22181b744c0dc83aea8dd741
+3 -3
--- src/alerts.c
+++ src/alerts.c
@@ -51,11 +51,11 @@
5151
@ -- f - Forum posts
5252
@ -- k - ** Special: Unsubscribed using /oneclickunsub
5353
@ -- n - New forum threads
5454
@ -- r - Replies to my own forum posts
5555
@ -- t - Ticket changes
56
-@ -- u - Potential elevation of users' permissions (admins only)
56
+@ -- u - Changes of users' permissions (admins only)
5757
@ -- w - Wiki changes
5858
@ -- x - Edits to forum posts
5959
@ -- Probably different codes will be added in the future. In the future
6060
@ -- we might also add a separate table that allows subscribing to email
6161
@ -- notifications for specific branches or tags or tickets.
@@ -1721,11 +1721,11 @@
17211721
@ <label><input type="checkbox" name="sw" %s(PCK("sw"))> \
17221722
@ Wiki</label><br>
17231723
}
17241724
if( g.perm.Admin ){
17251725
@ <label><input type="checkbox" name="su" %s(PCK("su"))> \
1726
- @ User permission additions</label>
1726
+ @ User permission changes</label>
17271727
}
17281728
di = PB("di");
17291729
@ </td></tr>
17301730
@ <tr>
17311731
@ <td class="form_label">Delivery:</td>
@@ -2131,11 +2131,11 @@
21312131
/* Corner-case bug: if an admin assigns 'u' to a non-admin, that
21322132
** subscription will get removed if the user later edits their
21332133
** subscriptions, as non-admins are not permitted to add that
21342134
** subscription. */
21352135
@ <label><input type="checkbox" name="su" %s(su?"checked":"")>\
2136
- @ User permission additions</label>
2136
+ @ User permission changes</label>
21372137
}
21382138
@ </td></tr>
21392139
if( strchr(ssub,'k')!=0 ){
21402140
@ <tr><td></td><td>&nbsp;&uarr;&nbsp;
21412141
@ Note: User did a one-click unsubscribe</td></tr>
21422142
--- src/alerts.c
+++ src/alerts.c
@@ -51,11 +51,11 @@
51 @ -- f - Forum posts
52 @ -- k - ** Special: Unsubscribed using /oneclickunsub
53 @ -- n - New forum threads
54 @ -- r - Replies to my own forum posts
55 @ -- t - Ticket changes
56 @ -- u - Potential elevation of users' permissions (admins only)
57 @ -- w - Wiki changes
58 @ -- x - Edits to forum posts
59 @ -- Probably different codes will be added in the future. In the future
60 @ -- we might also add a separate table that allows subscribing to email
61 @ -- notifications for specific branches or tags or tickets.
@@ -1721,11 +1721,11 @@
1721 @ <label><input type="checkbox" name="sw" %s(PCK("sw"))> \
1722 @ Wiki</label><br>
1723 }
1724 if( g.perm.Admin ){
1725 @ <label><input type="checkbox" name="su" %s(PCK("su"))> \
1726 @ User permission additions</label>
1727 }
1728 di = PB("di");
1729 @ </td></tr>
1730 @ <tr>
1731 @ <td class="form_label">Delivery:</td>
@@ -2131,11 +2131,11 @@
2131 /* Corner-case bug: if an admin assigns 'u' to a non-admin, that
2132 ** subscription will get removed if the user later edits their
2133 ** subscriptions, as non-admins are not permitted to add that
2134 ** subscription. */
2135 @ <label><input type="checkbox" name="su" %s(su?"checked":"")>\
2136 @ User permission additions</label>
2137 }
2138 @ </td></tr>
2139 if( strchr(ssub,'k')!=0 ){
2140 @ <tr><td></td><td>&nbsp;&uarr;&nbsp;
2141 @ Note: User did a one-click unsubscribe</td></tr>
2142
--- src/alerts.c
+++ src/alerts.c
@@ -51,11 +51,11 @@
51 @ -- f - Forum posts
52 @ -- k - ** Special: Unsubscribed using /oneclickunsub
53 @ -- n - New forum threads
54 @ -- r - Replies to my own forum posts
55 @ -- t - Ticket changes
56 @ -- u - Changes of users' permissions (admins only)
57 @ -- w - Wiki changes
58 @ -- x - Edits to forum posts
59 @ -- Probably different codes will be added in the future. In the future
60 @ -- we might also add a separate table that allows subscribing to email
61 @ -- notifications for specific branches or tags or tickets.
@@ -1721,11 +1721,11 @@
1721 @ <label><input type="checkbox" name="sw" %s(PCK("sw"))> \
1722 @ Wiki</label><br>
1723 }
1724 if( g.perm.Admin ){
1725 @ <label><input type="checkbox" name="su" %s(PCK("su"))> \
1726 @ User permission changes</label>
1727 }
1728 di = PB("di");
1729 @ </td></tr>
1730 @ <tr>
1731 @ <td class="form_label">Delivery:</td>
@@ -2131,11 +2131,11 @@
2131 /* Corner-case bug: if an admin assigns 'u' to a non-admin, that
2132 ** subscription will get removed if the user later edits their
2133 ** subscriptions, as non-admins are not permitted to add that
2134 ** subscription. */
2135 @ <label><input type="checkbox" name="su" %s(su?"checked":"")>\
2136 @ User permission changes</label>
2137 }
2138 @ </td></tr>
2139 if( strchr(ssub,'k')!=0 ){
2140 @ <tr><td></td><td>&nbsp;&uarr;&nbsp;
2141 @ Note: User did a one-click unsubscribe</td></tr>
2142
+57 -18
--- src/setupuser.c
+++ src/setupuser.c
@@ -307,22 +307,59 @@
307307
while( zPw[0]=='*' ){ zPw++; }
308308
return zPw[0]!=0;
309309
}
310310
311311
/*
312
-** Return true if user capability string zNew contains any capability
313
-** letter which is not in user capability string zOrig, else 0. This
314
-** does not take inherited permissions into account. Either argument
315
-** may be NULL.
312
+** Return true if user capability strings zOrig and zNew materially
313
+** differ, taking into account that they may be sorted in an arbitary
314
+** order. This does not take inherited permissions into
315
+** account. Either argument may be NULL. A NULL and an empty string
316
+** are considered equivalent here. e.g. "abc" and "cab" are equivalent
317
+** for this purpose, but "aCb" and "acb" are not.
318
+*/
319
+static int userCapsChanged(const char *zOrig, const char *zNew){
320
+ if( !zOrig ){
321
+ return zNew ? (0!=*zNew) : 0;
322
+ }else if( !zNew ){
323
+ return 0!=*zOrig;
324
+ }else if( 0==fossil_strcmp(zOrig, zNew) ){
325
+ return 0;
326
+ }else{
327
+ /* We don't know that zOrig and zNew are sorted equivalently. The
328
+ ** following steps will compare strings which contain all the same
329
+ ** capabilities letters as equivalent, regardless of the letters'
330
+ ** order in their strings. */
331
+ char aOrig[128]; /* table of zOrig bytes */
332
+ int nOrig = 0, nNew = 0;
333
+
334
+ memset( &aOrig[0], 0, sizeof(aOrig) );
335
+ for( ; *zOrig; ++zOrig, ++nOrig ){
336
+ if( 0==(*zOrig & 0x80) ){
337
+ aOrig[(int)*zOrig] = 1;
338
+ }
339
+ }
340
+ for( ; *zNew; ++zNew, ++nNew ){
341
+ if( 0==(*zNew & 0x80) && !aOrig[(int)*zNew] ){
342
+ return 1;
343
+ }
344
+ }
345
+ return nOrig!=nNew;
346
+ }
347
+}
348
+
349
+/*
350
+** COMMAND: test-user-caps-changed
351
+**
352
+** Usage: %fossil test-user-caps-changed caps1 caps2
353
+**
316354
*/
317
-static int userHasNewCaps(const char *zOrig, const char *zNew){
318
- for( ; zNew && *zNew; ++zNew ){
319
- if( !zOrig || strchr(zOrig,*zNew)==0 ){
320
- return *zNew;
321
- }
322
- }
323
- return 0;
355
+void test_user_caps_changed(void){
356
+
357
+ char const * zOld = g.argc>2 ? g.argv[2] : NULL;
358
+ char const * zNew = g.argc>3 ? g.argv[3] : NULL;
359
+ fossil_print("Has changes? = %d\n",
360
+ userCapsChanged( zOld, zNew ));
324361
}
325362
326363
/*
327364
** Sends notification of user permission elevation changes to all
328365
** subscribers with a "u" subscription. This is a no-op if alerts are
@@ -336,11 +373,11 @@
336373
** edits their subscriptions after an admin assigns them this one,
337374
** this particular one will be lost. "Feature or bug?" is unclear,
338375
** but it would be odd for a non-admin to be assigned this
339376
** capability.
340377
*/
341
-static void alert_user_elevation(const char *zLogin, /*Affected user*/
378
+static void alert_user_cap_change(const char *zLogin, /*Affected user*/
342379
int uid, /*[user].uid*/
343380
int bIsNew, /*true if new user*/
344381
const char *zOrigCaps,/*Old caps*/
345382
const char *zNewCaps /*New caps*/){
346383
Blob hdr, body;
@@ -489,11 +526,11 @@
489526
}else if( !cgi_csrf_safe(2) ){
490527
/* This might be a cross-site request forgery, so ignore it */
491528
}else{
492529
/* We have all the information we need to make the change to the user */
493530
char c;
494
- int bHasNewCaps = 0 /* 1 if user's permissions are increased */;
531
+ int bCapsChanged = 0 /* 1 if user's permissions changed */;
495532
const int bIsNew = uid<=0;
496533
char aCap[70], zNm[4];
497534
zNm[0] = 'a';
498535
zNm[2] = 0;
499536
for(i=0, c='a'; c<='z'; c++){
@@ -511,11 +548,11 @@
511548
a[c&0x7f] = P(zNm)!=0;
512549
if( a[c&0x7f] ) aCap[i++] = c;
513550
}
514551
515552
aCap[i] = 0;
516
- bHasNewCaps = bIsNew || userHasNewCaps(zOldCaps, &aCap[0]);
553
+ bCapsChanged = bIsNew || userCapsChanged(zOldCaps, &aCap[0]);
517554
zPw = P("pw");
518555
zLogin = P("login");
519556
if( strlen(zLogin)==0 ){
520557
const char *zRef = cgi_referer("setup_ulist");
521558
style_header("User Creation Error");
@@ -616,18 +653,20 @@
616653
@ <span class="loginError">%h(zErr)</span>
617654
@
618655
@ <p><a href="setup_uedit?id=%d(uid)&referer=%T(zRef)">
619656
@ [Bummer]</a></p>
620657
style_finish_page();
621
- if( bHasNewCaps ){
622
- alert_user_elevation(zLogin, uid, bIsNew, zOldCaps, &aCap[0]);
658
+ if( bCapsChanged ){
659
+ /* It's possible that caps were updated locally even if
660
+ ** login group updates failed. */
661
+ alert_user_cap_change(zLogin, uid, bIsNew, zOldCaps, &aCap[0]);
623662
}
624663
return;
625664
}
626665
}
627
- if( bHasNewCaps ){
628
- alert_user_elevation(zLogin, uid, bIsNew, zOldCaps, &aCap[0]);
666
+ if( bCapsChanged ){
667
+ alert_user_cap_change(zLogin, uid, bIsNew, zOldCaps, &aCap[0]);
629668
}
630669
cgi_redirect(cgi_referer("setup_ulist"));
631670
return;
632671
}
633672
634673
--- src/setupuser.c
+++ src/setupuser.c
@@ -307,22 +307,59 @@
307 while( zPw[0]=='*' ){ zPw++; }
308 return zPw[0]!=0;
309 }
310
311 /*
312 ** Return true if user capability string zNew contains any capability
313 ** letter which is not in user capability string zOrig, else 0. This
314 ** does not take inherited permissions into account. Either argument
315 ** may be NULL.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
316 */
317 static int userHasNewCaps(const char *zOrig, const char *zNew){
318 for( ; zNew && *zNew; ++zNew ){
319 if( !zOrig || strchr(zOrig,*zNew)==0 ){
320 return *zNew;
321 }
322 }
323 return 0;
324 }
325
326 /*
327 ** Sends notification of user permission elevation changes to all
328 ** subscribers with a "u" subscription. This is a no-op if alerts are
@@ -336,11 +373,11 @@
336 ** edits their subscriptions after an admin assigns them this one,
337 ** this particular one will be lost. "Feature or bug?" is unclear,
338 ** but it would be odd for a non-admin to be assigned this
339 ** capability.
340 */
341 static void alert_user_elevation(const char *zLogin, /*Affected user*/
342 int uid, /*[user].uid*/
343 int bIsNew, /*true if new user*/
344 const char *zOrigCaps,/*Old caps*/
345 const char *zNewCaps /*New caps*/){
346 Blob hdr, body;
@@ -489,11 +526,11 @@
489 }else if( !cgi_csrf_safe(2) ){
490 /* This might be a cross-site request forgery, so ignore it */
491 }else{
492 /* We have all the information we need to make the change to the user */
493 char c;
494 int bHasNewCaps = 0 /* 1 if user's permissions are increased */;
495 const int bIsNew = uid<=0;
496 char aCap[70], zNm[4];
497 zNm[0] = 'a';
498 zNm[2] = 0;
499 for(i=0, c='a'; c<='z'; c++){
@@ -511,11 +548,11 @@
511 a[c&0x7f] = P(zNm)!=0;
512 if( a[c&0x7f] ) aCap[i++] = c;
513 }
514
515 aCap[i] = 0;
516 bHasNewCaps = bIsNew || userHasNewCaps(zOldCaps, &aCap[0]);
517 zPw = P("pw");
518 zLogin = P("login");
519 if( strlen(zLogin)==0 ){
520 const char *zRef = cgi_referer("setup_ulist");
521 style_header("User Creation Error");
@@ -616,18 +653,20 @@
616 @ <span class="loginError">%h(zErr)</span>
617 @
618 @ <p><a href="setup_uedit?id=%d(uid)&referer=%T(zRef)">
619 @ [Bummer]</a></p>
620 style_finish_page();
621 if( bHasNewCaps ){
622 alert_user_elevation(zLogin, uid, bIsNew, zOldCaps, &aCap[0]);
 
 
623 }
624 return;
625 }
626 }
627 if( bHasNewCaps ){
628 alert_user_elevation(zLogin, uid, bIsNew, zOldCaps, &aCap[0]);
629 }
630 cgi_redirect(cgi_referer("setup_ulist"));
631 return;
632 }
633
634
--- src/setupuser.c
+++ src/setupuser.c
@@ -307,22 +307,59 @@
307 while( zPw[0]=='*' ){ zPw++; }
308 return zPw[0]!=0;
309 }
310
311 /*
312 ** Return true if user capability strings zOrig and zNew materially
313 ** differ, taking into account that they may be sorted in an arbitary
314 ** order. This does not take inherited permissions into
315 ** account. Either argument may be NULL. A NULL and an empty string
316 ** are considered equivalent here. e.g. "abc" and "cab" are equivalent
317 ** for this purpose, but "aCb" and "acb" are not.
318 */
319 static int userCapsChanged(const char *zOrig, const char *zNew){
320 if( !zOrig ){
321 return zNew ? (0!=*zNew) : 0;
322 }else if( !zNew ){
323 return 0!=*zOrig;
324 }else if( 0==fossil_strcmp(zOrig, zNew) ){
325 return 0;
326 }else{
327 /* We don't know that zOrig and zNew are sorted equivalently. The
328 ** following steps will compare strings which contain all the same
329 ** capabilities letters as equivalent, regardless of the letters'
330 ** order in their strings. */
331 char aOrig[128]; /* table of zOrig bytes */
332 int nOrig = 0, nNew = 0;
333
334 memset( &aOrig[0], 0, sizeof(aOrig) );
335 for( ; *zOrig; ++zOrig, ++nOrig ){
336 if( 0==(*zOrig & 0x80) ){
337 aOrig[(int)*zOrig] = 1;
338 }
339 }
340 for( ; *zNew; ++zNew, ++nNew ){
341 if( 0==(*zNew & 0x80) && !aOrig[(int)*zNew] ){
342 return 1;
343 }
344 }
345 return nOrig!=nNew;
346 }
347 }
348
349 /*
350 ** COMMAND: test-user-caps-changed
351 **
352 ** Usage: %fossil test-user-caps-changed caps1 caps2
353 **
354 */
355 void test_user_caps_changed(void){
356
357 char const * zOld = g.argc>2 ? g.argv[2] : NULL;
358 char const * zNew = g.argc>3 ? g.argv[3] : NULL;
359 fossil_print("Has changes? = %d\n",
360 userCapsChanged( zOld, zNew ));
 
361 }
362
363 /*
364 ** Sends notification of user permission elevation changes to all
365 ** subscribers with a "u" subscription. This is a no-op if alerts are
@@ -336,11 +373,11 @@
373 ** edits their subscriptions after an admin assigns them this one,
374 ** this particular one will be lost. "Feature or bug?" is unclear,
375 ** but it would be odd for a non-admin to be assigned this
376 ** capability.
377 */
378 static void alert_user_cap_change(const char *zLogin, /*Affected user*/
379 int uid, /*[user].uid*/
380 int bIsNew, /*true if new user*/
381 const char *zOrigCaps,/*Old caps*/
382 const char *zNewCaps /*New caps*/){
383 Blob hdr, body;
@@ -489,11 +526,11 @@
526 }else if( !cgi_csrf_safe(2) ){
527 /* This might be a cross-site request forgery, so ignore it */
528 }else{
529 /* We have all the information we need to make the change to the user */
530 char c;
531 int bCapsChanged = 0 /* 1 if user's permissions changed */;
532 const int bIsNew = uid<=0;
533 char aCap[70], zNm[4];
534 zNm[0] = 'a';
535 zNm[2] = 0;
536 for(i=0, c='a'; c<='z'; c++){
@@ -511,11 +548,11 @@
548 a[c&0x7f] = P(zNm)!=0;
549 if( a[c&0x7f] ) aCap[i++] = c;
550 }
551
552 aCap[i] = 0;
553 bCapsChanged = bIsNew || userCapsChanged(zOldCaps, &aCap[0]);
554 zPw = P("pw");
555 zLogin = P("login");
556 if( strlen(zLogin)==0 ){
557 const char *zRef = cgi_referer("setup_ulist");
558 style_header("User Creation Error");
@@ -616,18 +653,20 @@
653 @ <span class="loginError">%h(zErr)</span>
654 @
655 @ <p><a href="setup_uedit?id=%d(uid)&referer=%T(zRef)">
656 @ [Bummer]</a></p>
657 style_finish_page();
658 if( bCapsChanged ){
659 /* It's possible that caps were updated locally even if
660 ** login group updates failed. */
661 alert_user_cap_change(zLogin, uid, bIsNew, zOldCaps, &aCap[0]);
662 }
663 return;
664 }
665 }
666 if( bCapsChanged ){
667 alert_user_cap_change(zLogin, uid, bIsNew, zOldCaps, &aCap[0]);
668 }
669 cgi_redirect(cgi_referer("setup_ulist"));
670 return;
671 }
672
673
--- www/changes.wiki
+++ www/changes.wiki
@@ -127,13 +127,13 @@
127127
<li> Added button 'Submit and New' to create multiple tickets
128128
in a row.
129129
</ol>
130130
* Added the "hash" query parameter to the
131131
[/help?cmd=/whatis|/whatis webpage].
132
- * Add a "user elevation" [/doc/trunk/www/alerts.md|subscription]
132
+ * Add a "user permissions changes" [/doc/trunk/www/alerts.md|subscription]
133133
which alerts subscribers when an admin creates a new user or
134
- adds new permissions to one.
134
+ when a user's permissions change.
135135
* Show project description on repository list.
136136
* Diverse minor fixes and additions.
137137
138138
139139
<h2 id='v2_25'>Changes for version 2.25 (2024-11-06)</h2>
140140
--- www/changes.wiki
+++ www/changes.wiki
@@ -127,13 +127,13 @@
127 <li> Added button 'Submit and New' to create multiple tickets
128 in a row.
129 </ol>
130 * Added the "hash" query parameter to the
131 [/help?cmd=/whatis|/whatis webpage].
132 * Add a "user elevation" [/doc/trunk/www/alerts.md|subscription]
133 which alerts subscribers when an admin creates a new user or
134 adds new permissions to one.
135 * Show project description on repository list.
136 * Diverse minor fixes and additions.
137
138
139 <h2 id='v2_25'>Changes for version 2.25 (2024-11-06)</h2>
140
--- www/changes.wiki
+++ www/changes.wiki
@@ -127,13 +127,13 @@
127 <li> Added button 'Submit and New' to create multiple tickets
128 in a row.
129 </ol>
130 * Added the "hash" query parameter to the
131 [/help?cmd=/whatis|/whatis webpage].
132 * Add a "user permissions changes" [/doc/trunk/www/alerts.md|subscription]
133 which alerts subscribers when an admin creates a new user or
134 when a user's permissions change.
135 * Show project description on repository list.
136 * Diverse minor fixes and additions.
137
138
139 <h2 id='v2_25'>Changes for version 2.25 (2024-11-06)</h2>
140

Keyboard Shortcuts

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