Fossil SCM
Cleanups, mostly docs, in the user elevation alerts. Document the currently-known ways which this particular alert differs from others. This needs more sanding-down but am checking this in to go work on the broken user deletion (which pre-dates this branch but was first discovered here).
Commit
d6c5c7f639bceeef2e8c60de96731d2138094fcf2f3f8aa7bec971937a9ba4a8
Parent
5772d2f132c48c0…
2 files changed
+10
-2
+28
-16
+10
-2
| --- src/alerts.c | ||
| +++ src/alerts.c | ||
| @@ -1987,11 +1987,11 @@ | ||
| 1987 | 1987 | sc = strchr(ssub,'c')!=0; |
| 1988 | 1988 | sf = strchr(ssub,'f')!=0; |
| 1989 | 1989 | sn = strchr(ssub,'n')!=0; |
| 1990 | 1990 | sr = strchr(ssub,'r')!=0; |
| 1991 | 1991 | st = strchr(ssub,'t')!=0; |
| 1992 | - su = g.perm.Admin && strchr(ssub,'u')!=0; | |
| 1992 | + su = strchr(ssub,'u')!=0; | |
| 1993 | 1993 | sw = strchr(ssub,'w')!=0; |
| 1994 | 1994 | sx = strchr(ssub,'x')!=0; |
| 1995 | 1995 | smip = db_column_text(&q, 5); |
| 1996 | 1996 | mtime = db_column_text(&q, 7); |
| 1997 | 1997 | sctime = db_column_text(&q, 8); |
| @@ -2109,10 +2109,14 @@ | ||
| 2109 | 2109 | if( g.perm.RdWiki ){ |
| 2110 | 2110 | @ <label><input type="checkbox" name="sw" %s(sw?"checked":"")>\ |
| 2111 | 2111 | @ Wiki</label><br> |
| 2112 | 2112 | } |
| 2113 | 2113 | if( g.perm.Admin ){ |
| 2114 | + /* Corner-case bug: if an admin assigns 'u' to a non-admin, that | |
| 2115 | + ** subscription will get removed if the user later edits their | |
| 2116 | + ** subscriptions, as non-admins are not permitted to add that | |
| 2117 | + ** subscription. */ | |
| 2114 | 2118 | @ <label><input type="checkbox" name="su" %s(su?"checked":"")>\ |
| 2115 | 2119 | @ User permission elevation</label> |
| 2116 | 2120 | } |
| 2117 | 2121 | @ </td></tr> |
| 2118 | 2122 | if( strchr(ssub,'k')!=0 ){ |
| @@ -2542,15 +2546,16 @@ | ||
| 2542 | 2546 | ** f An original forum post |
| 2543 | 2547 | ** n New forum threads |
| 2544 | 2548 | ** r Replies to my forum posts |
| 2545 | 2549 | ** x An edit to a prior forum post |
| 2546 | 2550 | ** t A new ticket or a change to an existing ticket |
| 2551 | +** u A user was added or received new permissions | |
| 2547 | 2552 | ** w A change to a wiki page |
| 2548 | 2553 | ** x Edits to forum posts |
| 2549 | 2554 | */ |
| 2550 | 2555 | struct EmailEvent { |
| 2551 | - int type; /* 'c', 'f', 'n', 'r', 't', 'w', 'x' */ | |
| 2556 | + int type; /* 'c', 'f', 'n', 'r', 't', 'u', 'w', 'x' */ | |
| 2552 | 2557 | int needMod; /* Pending moderator approval */ |
| 2553 | 2558 | Blob hdr; /* Header content, for forum entries */ |
| 2554 | 2559 | Blob txt; /* Text description to appear in an alert */ |
| 2555 | 2560 | char *zFromName; /* Human name of the sender */ |
| 2556 | 2561 | char *zPriors; /* Upthread sender IDs for forum posts */ |
| @@ -2945,10 +2950,11 @@ | ||
| 2945 | 2950 | ); |
| 2946 | 2951 | if( strchr(zSub, 'a') ) blob_appendf(pBody, " * Announcements\n"); |
| 2947 | 2952 | if( strchr(zSub, 'c') ) blob_appendf(pBody, " * Check-ins\n"); |
| 2948 | 2953 | if( strchr(zSub, 'f') ) blob_appendf(pBody, " * Forum posts\n"); |
| 2949 | 2954 | if( strchr(zSub, 't') ) blob_appendf(pBody, " * Ticket changes\n"); |
| 2955 | + if( strchr(zSub, 'u') ) blob_appendf(pBody, " * User permission elevation\n"); | |
| 2950 | 2956 | if( strchr(zSub, 'w') ) blob_appendf(pBody, " * Wiki changes\n"); |
| 2951 | 2957 | blob_appendf(pBody, "\n" |
| 2952 | 2958 | "If you take no action, your subscription will expire and you will be\n" |
| 2953 | 2959 | "unsubscribed in about %d days. To make other changes or to unsubscribe\n" |
| 2954 | 2960 | "immediately, visit the following webpage:\n\n" |
| @@ -3157,10 +3163,11 @@ | ||
| 3157 | 3163 | switch( p->type ){ |
| 3158 | 3164 | case 'x': case 'f': |
| 3159 | 3165 | case 'n': case 'r': xType = '5'; break; |
| 3160 | 3166 | case 't': xType = 'q'; break; |
| 3161 | 3167 | case 'w': xType = 'l'; break; |
| 3168 | + /* Note: case 'u' is not handled here */ | |
| 3162 | 3169 | } |
| 3163 | 3170 | if( strchr(zCap,xType)==0 ) continue; |
| 3164 | 3171 | } |
| 3165 | 3172 | }else if( strchr(zCap,'s')!=0 || strchr(zCap,'a')!=0 ){ |
| 3166 | 3173 | /* Setup and admin users can get any notification that does not |
| @@ -3173,10 +3180,11 @@ | ||
| 3173 | 3180 | case 'c': xType = 'o'; break; |
| 3174 | 3181 | case 'x': case 'f': |
| 3175 | 3182 | case 'n': case 'r': xType = '2'; break; |
| 3176 | 3183 | case 't': xType = 'r'; break; |
| 3177 | 3184 | case 'w': xType = 'j'; break; |
| 3185 | + /* Note: case 'u' is not handled here */ | |
| 3178 | 3186 | } |
| 3179 | 3187 | if( strchr(zCap,xType)==0 ) continue; |
| 3180 | 3188 | } |
| 3181 | 3189 | if( blob_size(&p->hdr)>0 ){ |
| 3182 | 3190 | /* This alert should be sent as a separate email */ |
| 3183 | 3191 |
| --- src/alerts.c | |
| +++ src/alerts.c | |
| @@ -1987,11 +1987,11 @@ | |
| 1987 | sc = strchr(ssub,'c')!=0; |
| 1988 | sf = strchr(ssub,'f')!=0; |
| 1989 | sn = strchr(ssub,'n')!=0; |
| 1990 | sr = strchr(ssub,'r')!=0; |
| 1991 | st = strchr(ssub,'t')!=0; |
| 1992 | su = g.perm.Admin && strchr(ssub,'u')!=0; |
| 1993 | sw = strchr(ssub,'w')!=0; |
| 1994 | sx = strchr(ssub,'x')!=0; |
| 1995 | smip = db_column_text(&q, 5); |
| 1996 | mtime = db_column_text(&q, 7); |
| 1997 | sctime = db_column_text(&q, 8); |
| @@ -2109,10 +2109,14 @@ | |
| 2109 | if( g.perm.RdWiki ){ |
| 2110 | @ <label><input type="checkbox" name="sw" %s(sw?"checked":"")>\ |
| 2111 | @ Wiki</label><br> |
| 2112 | } |
| 2113 | if( g.perm.Admin ){ |
| 2114 | @ <label><input type="checkbox" name="su" %s(su?"checked":"")>\ |
| 2115 | @ User permission elevation</label> |
| 2116 | } |
| 2117 | @ </td></tr> |
| 2118 | if( strchr(ssub,'k')!=0 ){ |
| @@ -2542,15 +2546,16 @@ | |
| 2542 | ** f An original forum post |
| 2543 | ** n New forum threads |
| 2544 | ** r Replies to my forum posts |
| 2545 | ** x An edit to a prior forum post |
| 2546 | ** t A new ticket or a change to an existing ticket |
| 2547 | ** w A change to a wiki page |
| 2548 | ** x Edits to forum posts |
| 2549 | */ |
| 2550 | struct EmailEvent { |
| 2551 | int type; /* 'c', 'f', 'n', 'r', 't', 'w', 'x' */ |
| 2552 | int needMod; /* Pending moderator approval */ |
| 2553 | Blob hdr; /* Header content, for forum entries */ |
| 2554 | Blob txt; /* Text description to appear in an alert */ |
| 2555 | char *zFromName; /* Human name of the sender */ |
| 2556 | char *zPriors; /* Upthread sender IDs for forum posts */ |
| @@ -2945,10 +2950,11 @@ | |
| 2945 | ); |
| 2946 | if( strchr(zSub, 'a') ) blob_appendf(pBody, " * Announcements\n"); |
| 2947 | if( strchr(zSub, 'c') ) blob_appendf(pBody, " * Check-ins\n"); |
| 2948 | if( strchr(zSub, 'f') ) blob_appendf(pBody, " * Forum posts\n"); |
| 2949 | if( strchr(zSub, 't') ) blob_appendf(pBody, " * Ticket changes\n"); |
| 2950 | if( strchr(zSub, 'w') ) blob_appendf(pBody, " * Wiki changes\n"); |
| 2951 | blob_appendf(pBody, "\n" |
| 2952 | "If you take no action, your subscription will expire and you will be\n" |
| 2953 | "unsubscribed in about %d days. To make other changes or to unsubscribe\n" |
| 2954 | "immediately, visit the following webpage:\n\n" |
| @@ -3157,10 +3163,11 @@ | |
| 3157 | switch( p->type ){ |
| 3158 | case 'x': case 'f': |
| 3159 | case 'n': case 'r': xType = '5'; break; |
| 3160 | case 't': xType = 'q'; break; |
| 3161 | case 'w': xType = 'l'; break; |
| 3162 | } |
| 3163 | if( strchr(zCap,xType)==0 ) continue; |
| 3164 | } |
| 3165 | }else if( strchr(zCap,'s')!=0 || strchr(zCap,'a')!=0 ){ |
| 3166 | /* Setup and admin users can get any notification that does not |
| @@ -3173,10 +3180,11 @@ | |
| 3173 | case 'c': xType = 'o'; break; |
| 3174 | case 'x': case 'f': |
| 3175 | case 'n': case 'r': xType = '2'; break; |
| 3176 | case 't': xType = 'r'; break; |
| 3177 | case 'w': xType = 'j'; break; |
| 3178 | } |
| 3179 | if( strchr(zCap,xType)==0 ) continue; |
| 3180 | } |
| 3181 | if( blob_size(&p->hdr)>0 ){ |
| 3182 | /* This alert should be sent as a separate email */ |
| 3183 |
| --- src/alerts.c | |
| +++ src/alerts.c | |
| @@ -1987,11 +1987,11 @@ | |
| 1987 | sc = strchr(ssub,'c')!=0; |
| 1988 | sf = strchr(ssub,'f')!=0; |
| 1989 | sn = strchr(ssub,'n')!=0; |
| 1990 | sr = strchr(ssub,'r')!=0; |
| 1991 | st = strchr(ssub,'t')!=0; |
| 1992 | su = strchr(ssub,'u')!=0; |
| 1993 | sw = strchr(ssub,'w')!=0; |
| 1994 | sx = strchr(ssub,'x')!=0; |
| 1995 | smip = db_column_text(&q, 5); |
| 1996 | mtime = db_column_text(&q, 7); |
| 1997 | sctime = db_column_text(&q, 8); |
| @@ -2109,10 +2109,14 @@ | |
| 2109 | if( g.perm.RdWiki ){ |
| 2110 | @ <label><input type="checkbox" name="sw" %s(sw?"checked":"")>\ |
| 2111 | @ Wiki</label><br> |
| 2112 | } |
| 2113 | if( g.perm.Admin ){ |
| 2114 | /* Corner-case bug: if an admin assigns 'u' to a non-admin, that |
| 2115 | ** subscription will get removed if the user later edits their |
| 2116 | ** subscriptions, as non-admins are not permitted to add that |
| 2117 | ** subscription. */ |
| 2118 | @ <label><input type="checkbox" name="su" %s(su?"checked":"")>\ |
| 2119 | @ User permission elevation</label> |
| 2120 | } |
| 2121 | @ </td></tr> |
| 2122 | if( strchr(ssub,'k')!=0 ){ |
| @@ -2542,15 +2546,16 @@ | |
| 2546 | ** f An original forum post |
| 2547 | ** n New forum threads |
| 2548 | ** r Replies to my forum posts |
| 2549 | ** x An edit to a prior forum post |
| 2550 | ** t A new ticket or a change to an existing ticket |
| 2551 | ** u A user was added or received new permissions |
| 2552 | ** w A change to a wiki page |
| 2553 | ** x Edits to forum posts |
| 2554 | */ |
| 2555 | struct EmailEvent { |
| 2556 | int type; /* 'c', 'f', 'n', 'r', 't', 'u', 'w', 'x' */ |
| 2557 | int needMod; /* Pending moderator approval */ |
| 2558 | Blob hdr; /* Header content, for forum entries */ |
| 2559 | Blob txt; /* Text description to appear in an alert */ |
| 2560 | char *zFromName; /* Human name of the sender */ |
| 2561 | char *zPriors; /* Upthread sender IDs for forum posts */ |
| @@ -2945,10 +2950,11 @@ | |
| 2950 | ); |
| 2951 | if( strchr(zSub, 'a') ) blob_appendf(pBody, " * Announcements\n"); |
| 2952 | if( strchr(zSub, 'c') ) blob_appendf(pBody, " * Check-ins\n"); |
| 2953 | if( strchr(zSub, 'f') ) blob_appendf(pBody, " * Forum posts\n"); |
| 2954 | if( strchr(zSub, 't') ) blob_appendf(pBody, " * Ticket changes\n"); |
| 2955 | if( strchr(zSub, 'u') ) blob_appendf(pBody, " * User permission elevation\n"); |
| 2956 | if( strchr(zSub, 'w') ) blob_appendf(pBody, " * Wiki changes\n"); |
| 2957 | blob_appendf(pBody, "\n" |
| 2958 | "If you take no action, your subscription will expire and you will be\n" |
| 2959 | "unsubscribed in about %d days. To make other changes or to unsubscribe\n" |
| 2960 | "immediately, visit the following webpage:\n\n" |
| @@ -3157,10 +3163,11 @@ | |
| 3163 | switch( p->type ){ |
| 3164 | case 'x': case 'f': |
| 3165 | case 'n': case 'r': xType = '5'; break; |
| 3166 | case 't': xType = 'q'; break; |
| 3167 | case 'w': xType = 'l'; break; |
| 3168 | /* Note: case 'u' is not handled here */ |
| 3169 | } |
| 3170 | if( strchr(zCap,xType)==0 ) continue; |
| 3171 | } |
| 3172 | }else if( strchr(zCap,'s')!=0 || strchr(zCap,'a')!=0 ){ |
| 3173 | /* Setup and admin users can get any notification that does not |
| @@ -3173,10 +3180,11 @@ | |
| 3180 | case 'c': xType = 'o'; break; |
| 3181 | case 'x': case 'f': |
| 3182 | case 'n': case 'r': xType = '2'; break; |
| 3183 | case 't': xType = 'r'; break; |
| 3184 | case 'w': xType = 'j'; break; |
| 3185 | /* Note: case 'u' is not handled here */ |
| 3186 | } |
| 3187 | if( strchr(zCap,xType)==0 ) continue; |
| 3188 | } |
| 3189 | if( blob_size(&p->hdr)>0 ){ |
| 3190 | /* This alert should be sent as a separate email */ |
| 3191 |
+28
-16
| --- src/setupuser.c | ||
| +++ src/setupuser.c | ||
| @@ -320,11 +320,27 @@ | ||
| 320 | 320 | return 0; |
| 321 | 321 | } |
| 322 | 322 | |
| 323 | 323 | /* |
| 324 | 324 | ** Sends notification of user permission elevation changes to all |
| 325 | -** subscribers with a "u" subscription. | |
| 325 | +** subscribers with a "u" subscription. This is a no-op if alerts are | |
| 326 | +** not enabled. | |
| 327 | +** | |
| 328 | +** These subscriptions differ from most, in that: | |
| 329 | +** | |
| 330 | +** - The attempt is made to send them immediately, as opposed to | |
| 331 | +** handling them en masse via alert_send_alerts(). | |
| 332 | +** | |
| 333 | +** - They do not honor digest mode. | |
| 334 | +** | |
| 335 | +** - They currently lack an "unsubscribe" link. | |
| 336 | +** | |
| 337 | +** - Only an admin can assign this subscription, but if a non-admin | |
| 338 | +** edits their subscriptions after an admin assigns them this one, | |
| 339 | +** this particular one will be lost. "Feature or bug?" is unclear, | |
| 340 | +** but it would be odd for a non-admin to be assigned this | |
| 341 | +** capability. | |
| 326 | 342 | */ |
| 327 | 343 | static void alert_user_elevation(const char *zLogin, /*Affected user*/ |
| 328 | 344 | int uid, /*[user].uid*/ |
| 329 | 345 | int bIsNew, /*true if new user*/ |
| 330 | 346 | const char *zOrigCaps,/*Old caps*/ |
| @@ -331,15 +347,20 @@ | ||
| 331 | 347 | const char *zNewCaps /*New caps*/){ |
| 332 | 348 | Blob hdr, body; |
| 333 | 349 | Stmt q; |
| 334 | 350 | int nBody; |
| 335 | 351 | AlertSender *pSender; |
| 336 | - char *zSubname = db_get("email-subname", "[Fossil Repo]"); | |
| 337 | - char *zURL = db_get("email-url",0); | |
| 338 | - char * zSubject = bIsNew | |
| 352 | + char *zSubname; | |
| 353 | + char *zURL; | |
| 354 | + char * zSubject; | |
| 355 | + | |
| 356 | + if( !alert_enabled() ) return; | |
| 357 | + zSubject = bIsNew | |
| 339 | 358 | ? mprintf("New user created: [%q]", zLogin) |
| 340 | 359 | : mprintf("User [%q] permissions elevated", zLogin); |
| 360 | + zURL = db_get("email-url",0); | |
| 361 | + zSubname = db_get("email-subname", "[Fossil Repo]"); | |
| 341 | 362 | blob_init(&body, 0, 0); |
| 342 | 363 | blob_init(&hdr, 0, 0); |
| 343 | 364 | if( bIsNew ){ |
| 344 | 365 | blob_appendf(&body, "User [%q] was created by with " |
| 345 | 366 | "permissions [%q] by user [%q].\n", |
| @@ -357,13 +378,12 @@ | ||
| 357 | 378 | db_prepare(&q, |
| 358 | 379 | "SELECT semail, hex(subscriberCode)" |
| 359 | 380 | " FROM subscriber, user " |
| 360 | 381 | " WHERE sverified AND NOT sdonotcall" |
| 361 | 382 | " AND suname=login" |
| 362 | - " AND fullcap(cap) GLOB '*a*'" | |
| 363 | 383 | " AND ssub GLOB '*u*'"); |
| 364 | - while( db_step(&q)==SQLITE_ROW ){ | |
| 384 | + while( !pSender->zErr && db_step(&q)==SQLITE_ROW ){ | |
| 365 | 385 | const char *zTo = db_column_text(&q, 0); |
| 366 | 386 | blob_truncate(&hdr, 0); |
| 367 | 387 | blob_appendf(&hdr, "To: <%s>\r\nSubject: %s %s\r\n", |
| 368 | 388 | zTo, zSubname, zSubject); |
| 369 | 389 | if( zURL ){ |
| @@ -525,24 +545,16 @@ | ||
| 525 | 545 | style_finish_page(); |
| 526 | 546 | return; |
| 527 | 547 | } |
| 528 | 548 | cgi_csrf_verify(); |
| 529 | 549 | db_unprotect(PROTECT_USER); |
| 530 | - { | |
| 531 | - Stmt q; | |
| 532 | - db_prepare(&q, | |
| 550 | + uid = db_int(0, | |
| 533 | 551 | "REPLACE INTO user(uid,login,info,pw,cap,mtime) " |
| 534 | 552 | "VALUES(nullif(%d,0),%Q,%Q,%Q,%Q,now()) " |
| 535 | 553 | "RETURNING uid", |
| 536 | 554 | uid, zLogin, P("info"), zPw, &aCap[0]); |
| 537 | - if( SQLITE_ROW==db_step(&q) ){ | |
| 538 | - uid = db_column_int(&q, 0); | |
| 539 | - }else{ | |
| 540 | - fossil_fatal("Inserting new user failed"); | |
| 541 | - } | |
| 542 | - db_finalize(&q); | |
| 543 | - } | |
| 555 | + assert( uid>0 ); | |
| 544 | 556 | if( zOldLogin && fossil_strcmp(zLogin, zOldLogin)!=0 ){ |
| 545 | 557 | if( alert_tables_exist() ){ |
| 546 | 558 | /* Rename matching subscriber entry, else the user cannot |
| 547 | 559 | re-subscribe with their same email address. */ |
| 548 | 560 | db_multi_exec("UPDATE subscriber SET suname=%Q WHERE suname=%Q", |
| 549 | 561 |
| --- src/setupuser.c | |
| +++ src/setupuser.c | |
| @@ -320,11 +320,27 @@ | |
| 320 | return 0; |
| 321 | } |
| 322 | |
| 323 | /* |
| 324 | ** Sends notification of user permission elevation changes to all |
| 325 | ** subscribers with a "u" subscription. |
| 326 | */ |
| 327 | static void alert_user_elevation(const char *zLogin, /*Affected user*/ |
| 328 | int uid, /*[user].uid*/ |
| 329 | int bIsNew, /*true if new user*/ |
| 330 | const char *zOrigCaps,/*Old caps*/ |
| @@ -331,15 +347,20 @@ | |
| 331 | const char *zNewCaps /*New caps*/){ |
| 332 | Blob hdr, body; |
| 333 | Stmt q; |
| 334 | int nBody; |
| 335 | AlertSender *pSender; |
| 336 | char *zSubname = db_get("email-subname", "[Fossil Repo]"); |
| 337 | char *zURL = db_get("email-url",0); |
| 338 | char * zSubject = bIsNew |
| 339 | ? mprintf("New user created: [%q]", zLogin) |
| 340 | : mprintf("User [%q] permissions elevated", zLogin); |
| 341 | blob_init(&body, 0, 0); |
| 342 | blob_init(&hdr, 0, 0); |
| 343 | if( bIsNew ){ |
| 344 | blob_appendf(&body, "User [%q] was created by with " |
| 345 | "permissions [%q] by user [%q].\n", |
| @@ -357,13 +378,12 @@ | |
| 357 | db_prepare(&q, |
| 358 | "SELECT semail, hex(subscriberCode)" |
| 359 | " FROM subscriber, user " |
| 360 | " WHERE sverified AND NOT sdonotcall" |
| 361 | " AND suname=login" |
| 362 | " AND fullcap(cap) GLOB '*a*'" |
| 363 | " AND ssub GLOB '*u*'"); |
| 364 | while( db_step(&q)==SQLITE_ROW ){ |
| 365 | const char *zTo = db_column_text(&q, 0); |
| 366 | blob_truncate(&hdr, 0); |
| 367 | blob_appendf(&hdr, "To: <%s>\r\nSubject: %s %s\r\n", |
| 368 | zTo, zSubname, zSubject); |
| 369 | if( zURL ){ |
| @@ -525,24 +545,16 @@ | |
| 525 | style_finish_page(); |
| 526 | return; |
| 527 | } |
| 528 | cgi_csrf_verify(); |
| 529 | db_unprotect(PROTECT_USER); |
| 530 | { |
| 531 | Stmt q; |
| 532 | db_prepare(&q, |
| 533 | "REPLACE INTO user(uid,login,info,pw,cap,mtime) " |
| 534 | "VALUES(nullif(%d,0),%Q,%Q,%Q,%Q,now()) " |
| 535 | "RETURNING uid", |
| 536 | uid, zLogin, P("info"), zPw, &aCap[0]); |
| 537 | if( SQLITE_ROW==db_step(&q) ){ |
| 538 | uid = db_column_int(&q, 0); |
| 539 | }else{ |
| 540 | fossil_fatal("Inserting new user failed"); |
| 541 | } |
| 542 | db_finalize(&q); |
| 543 | } |
| 544 | if( zOldLogin && fossil_strcmp(zLogin, zOldLogin)!=0 ){ |
| 545 | if( alert_tables_exist() ){ |
| 546 | /* Rename matching subscriber entry, else the user cannot |
| 547 | re-subscribe with their same email address. */ |
| 548 | db_multi_exec("UPDATE subscriber SET suname=%Q WHERE suname=%Q", |
| 549 |
| --- src/setupuser.c | |
| +++ src/setupuser.c | |
| @@ -320,11 +320,27 @@ | |
| 320 | return 0; |
| 321 | } |
| 322 | |
| 323 | /* |
| 324 | ** Sends notification of user permission elevation changes to all |
| 325 | ** subscribers with a "u" subscription. This is a no-op if alerts are |
| 326 | ** not enabled. |
| 327 | ** |
| 328 | ** These subscriptions differ from most, in that: |
| 329 | ** |
| 330 | ** - The attempt is made to send them immediately, as opposed to |
| 331 | ** handling them en masse via alert_send_alerts(). |
| 332 | ** |
| 333 | ** - They do not honor digest mode. |
| 334 | ** |
| 335 | ** - They currently lack an "unsubscribe" link. |
| 336 | ** |
| 337 | ** - Only an admin can assign this subscription, but if a non-admin |
| 338 | ** edits their subscriptions after an admin assigns them this one, |
| 339 | ** this particular one will be lost. "Feature or bug?" is unclear, |
| 340 | ** but it would be odd for a non-admin to be assigned this |
| 341 | ** capability. |
| 342 | */ |
| 343 | static void alert_user_elevation(const char *zLogin, /*Affected user*/ |
| 344 | int uid, /*[user].uid*/ |
| 345 | int bIsNew, /*true if new user*/ |
| 346 | const char *zOrigCaps,/*Old caps*/ |
| @@ -331,15 +347,20 @@ | |
| 347 | const char *zNewCaps /*New caps*/){ |
| 348 | Blob hdr, body; |
| 349 | Stmt q; |
| 350 | int nBody; |
| 351 | AlertSender *pSender; |
| 352 | char *zSubname; |
| 353 | char *zURL; |
| 354 | char * zSubject; |
| 355 | |
| 356 | if( !alert_enabled() ) return; |
| 357 | zSubject = bIsNew |
| 358 | ? mprintf("New user created: [%q]", zLogin) |
| 359 | : mprintf("User [%q] permissions elevated", zLogin); |
| 360 | zURL = db_get("email-url",0); |
| 361 | zSubname = db_get("email-subname", "[Fossil Repo]"); |
| 362 | blob_init(&body, 0, 0); |
| 363 | blob_init(&hdr, 0, 0); |
| 364 | if( bIsNew ){ |
| 365 | blob_appendf(&body, "User [%q] was created by with " |
| 366 | "permissions [%q] by user [%q].\n", |
| @@ -357,13 +378,12 @@ | |
| 378 | db_prepare(&q, |
| 379 | "SELECT semail, hex(subscriberCode)" |
| 380 | " FROM subscriber, user " |
| 381 | " WHERE sverified AND NOT sdonotcall" |
| 382 | " AND suname=login" |
| 383 | " AND ssub GLOB '*u*'"); |
| 384 | while( !pSender->zErr && db_step(&q)==SQLITE_ROW ){ |
| 385 | const char *zTo = db_column_text(&q, 0); |
| 386 | blob_truncate(&hdr, 0); |
| 387 | blob_appendf(&hdr, "To: <%s>\r\nSubject: %s %s\r\n", |
| 388 | zTo, zSubname, zSubject); |
| 389 | if( zURL ){ |
| @@ -525,24 +545,16 @@ | |
| 545 | style_finish_page(); |
| 546 | return; |
| 547 | } |
| 548 | cgi_csrf_verify(); |
| 549 | db_unprotect(PROTECT_USER); |
| 550 | uid = db_int(0, |
| 551 | "REPLACE INTO user(uid,login,info,pw,cap,mtime) " |
| 552 | "VALUES(nullif(%d,0),%Q,%Q,%Q,%Q,now()) " |
| 553 | "RETURNING uid", |
| 554 | uid, zLogin, P("info"), zPw, &aCap[0]); |
| 555 | assert( uid>0 ); |
| 556 | if( zOldLogin && fossil_strcmp(zLogin, zOldLogin)!=0 ){ |
| 557 | if( alert_tables_exist() ){ |
| 558 | /* Rename matching subscriber entry, else the user cannot |
| 559 | re-subscribe with their same email address. */ |
| 560 | db_multi_exec("UPDATE subscriber SET suname=%Q WHERE suname=%Q", |
| 561 |