Fossil SCM
Add the ability to deny capabilities to self-registered accounts until the email verification comes through.
Commit
3b7970e032b39c6bab92a635d2c49430f0f833b01690df13e123403bd13ceb1f
Parent
fb38b925015c69d…
6 files changed
+15
-2
+1
-1
+12
-4
+1
-1
+8
+1
-1
+15
-2
| --- src/alerts.c | ||
| +++ src/alerts.c | ||
| @@ -1733,13 +1733,26 @@ | ||
| 1733 | 1733 | smip = db_column_text(&q, 5); |
| 1734 | 1734 | mtime = db_column_text(&q, 7); |
| 1735 | 1735 | sctime = db_column_text(&q, 8); |
| 1736 | 1736 | if( !g.perm.Admin && !sverified ){ |
| 1737 | 1737 | if( nName==64 ){ |
| 1738 | - db_multi_exec( | |
| 1739 | - "UPDATE subscriber SET sverified=1 WHERE subscriberCode=hextoblob(%Q)", | |
| 1738 | + db_multi_exec( | |
| 1739 | + "UPDATE subscriber SET sverified=1" | |
| 1740 | + " WHERE subscriberCode=hextoblob(%Q)", | |
| 1740 | 1741 | zName); |
| 1742 | + if( db_get_boolean("selfreg-verify",0) ){ | |
| 1743 | + char *zNewCap = db_get("default-perms","u"); | |
| 1744 | + db_multi_exec( | |
| 1745 | + "UPDATE user" | |
| 1746 | + " SET cap=%Q" | |
| 1747 | + " WHERE cap='7' AND login=(" | |
| 1748 | + " SELECT suname FROM subscriber" | |
| 1749 | + " WHERE subscriberCode=hextoblob(%Q))", | |
| 1750 | + zNewCap, zName | |
| 1751 | + ); | |
| 1752 | + login_set_capabilities(zNewCap, 0); | |
| 1753 | + } | |
| 1741 | 1754 | @ <h1>Your email alert subscription has been verified!</h1> |
| 1742 | 1755 | @ <p>Use the form below to update your subscription information.</p> |
| 1743 | 1756 | @ <p>Hint: Bookmark this page so that you can more easily update |
| 1744 | 1757 | @ your subscription information in the future</p> |
| 1745 | 1758 | }else{ |
| 1746 | 1759 |
| --- src/alerts.c | |
| +++ src/alerts.c | |
| @@ -1733,13 +1733,26 @@ | |
| 1733 | smip = db_column_text(&q, 5); |
| 1734 | mtime = db_column_text(&q, 7); |
| 1735 | sctime = db_column_text(&q, 8); |
| 1736 | if( !g.perm.Admin && !sverified ){ |
| 1737 | if( nName==64 ){ |
| 1738 | db_multi_exec( |
| 1739 | "UPDATE subscriber SET sverified=1 WHERE subscriberCode=hextoblob(%Q)", |
| 1740 | zName); |
| 1741 | @ <h1>Your email alert subscription has been verified!</h1> |
| 1742 | @ <p>Use the form below to update your subscription information.</p> |
| 1743 | @ <p>Hint: Bookmark this page so that you can more easily update |
| 1744 | @ your subscription information in the future</p> |
| 1745 | }else{ |
| 1746 |
| --- src/alerts.c | |
| +++ src/alerts.c | |
| @@ -1733,13 +1733,26 @@ | |
| 1733 | smip = db_column_text(&q, 5); |
| 1734 | mtime = db_column_text(&q, 7); |
| 1735 | sctime = db_column_text(&q, 8); |
| 1736 | if( !g.perm.Admin && !sverified ){ |
| 1737 | if( nName==64 ){ |
| 1738 | db_multi_exec( |
| 1739 | "UPDATE subscriber SET sverified=1" |
| 1740 | " WHERE subscriberCode=hextoblob(%Q)", |
| 1741 | zName); |
| 1742 | if( db_get_boolean("selfreg-verify",0) ){ |
| 1743 | char *zNewCap = db_get("default-perms","u"); |
| 1744 | db_multi_exec( |
| 1745 | "UPDATE user" |
| 1746 | " SET cap=%Q" |
| 1747 | " WHERE cap='7' AND login=(" |
| 1748 | " SELECT suname FROM subscriber" |
| 1749 | " WHERE subscriberCode=hextoblob(%Q))", |
| 1750 | zNewCap, zName |
| 1751 | ); |
| 1752 | login_set_capabilities(zNewCap, 0); |
| 1753 | } |
| 1754 | @ <h1>Your email alert subscription has been verified!</h1> |
| 1755 | @ <p>Use the form below to update your subscription information.</p> |
| 1756 | @ <p>Hint: Bookmark this page so that you can more easily update |
| 1757 | @ your subscription information in the future</p> |
| 1758 | }else{ |
| 1759 |
+1
-1
| --- src/capabilities.c | ||
| +++ src/capabilities.c | ||
| @@ -366,11 +366,11 @@ | ||
| 366 | 366 | CapabilityString *pCap; |
| 367 | 367 | char *zSelfCap; |
| 368 | 368 | char *zPubPages = db_get("public-pages",0); |
| 369 | 369 | int hasPubPages = zPubPages && zPubPages[0]; |
| 370 | 370 | |
| 371 | - pCap = capability_add(0, db_get("default-perms",0)); | |
| 371 | + pCap = capability_add(0, db_get("default-perms","u")); | |
| 372 | 372 | capability_expand(pCap); |
| 373 | 373 | zSelfCap = capability_string(pCap); |
| 374 | 374 | capability_free(pCap); |
| 375 | 375 | |
| 376 | 376 | db_prepare(&q, |
| 377 | 377 |
| --- src/capabilities.c | |
| +++ src/capabilities.c | |
| @@ -366,11 +366,11 @@ | |
| 366 | CapabilityString *pCap; |
| 367 | char *zSelfCap; |
| 368 | char *zPubPages = db_get("public-pages",0); |
| 369 | int hasPubPages = zPubPages && zPubPages[0]; |
| 370 | |
| 371 | pCap = capability_add(0, db_get("default-perms",0)); |
| 372 | capability_expand(pCap); |
| 373 | zSelfCap = capability_string(pCap); |
| 374 | capability_free(pCap); |
| 375 | |
| 376 | db_prepare(&q, |
| 377 |
| --- src/capabilities.c | |
| +++ src/capabilities.c | |
| @@ -366,11 +366,11 @@ | |
| 366 | CapabilityString *pCap; |
| 367 | char *zSelfCap; |
| 368 | char *zPubPages = db_get("public-pages",0); |
| 369 | int hasPubPages = zPubPages && zPubPages[0]; |
| 370 | |
| 371 | pCap = capability_add(0, db_get("default-perms","u")); |
| 372 | capability_expand(pCap); |
| 373 | zSelfCap = capability_string(pCap); |
| 374 | capability_free(pCap); |
| 375 | |
| 376 | db_prepare(&q, |
| 377 |
+12
-4
| --- src/login.c | ||
| +++ src/login.c | ||
| @@ -481,11 +481,11 @@ | ||
| 481 | 481 | int login_self_register_available(const char *zNeeded){ |
| 482 | 482 | CapabilityString *pCap; |
| 483 | 483 | int rc; |
| 484 | 484 | if( !db_get_boolean("self-register",0) ) return 0; |
| 485 | 485 | if( zNeeded==0 ) return 1; |
| 486 | - pCap = capability_add(0, db_get("default-perms", 0)); | |
| 486 | + pCap = capability_add(0, db_get("default-perms", "u")); | |
| 487 | 487 | capability_expand(pCap); |
| 488 | 488 | rc = capability_has_any(pCap, zNeeded); |
| 489 | 489 | capability_free(pCap); |
| 490 | 490 | return rc; |
| 491 | 491 | } |
| @@ -1128,11 +1128,11 @@ | ||
| 1128 | 1128 | if( zPublicPages!=0 ){ |
| 1129 | 1129 | Glob *pGlob = glob_create(zPublicPages); |
| 1130 | 1130 | const char *zUri = PD("REQUEST_URI",""); |
| 1131 | 1131 | zUri += (int)strlen(g.zTop); |
| 1132 | 1132 | if( glob_match(pGlob, zUri) ){ |
| 1133 | - login_set_capabilities(db_get("default-perms", 0), 0); | |
| 1133 | + login_set_capabilities(db_get("default-perms", "u"), 0); | |
| 1134 | 1134 | } |
| 1135 | 1135 | glob_free(pGlob); |
| 1136 | 1136 | } |
| 1137 | 1137 | } |
| 1138 | 1138 | |
| @@ -1511,11 +1511,11 @@ | ||
| 1511 | 1511 | @ <p>This project does not allow user self-registration. Please contact the |
| 1512 | 1512 | @ project administrator to obtain an account.</p> |
| 1513 | 1513 | style_footer(); |
| 1514 | 1514 | return; |
| 1515 | 1515 | } |
| 1516 | - zPerms = db_get("default-perms", 0); | |
| 1516 | + zPerms = db_get("default-perms", "u"); | |
| 1517 | 1517 | |
| 1518 | 1518 | /* Prompt the user for email alerts if this repository is configured for |
| 1519 | 1519 | ** email alerts and if the default permissions include "7" */ |
| 1520 | 1520 | canDoAlerts = alert_tables_exist() && db_int(0, |
| 1521 | 1521 | "SELECT fullcap(%Q) GLOB '*7*'", zPerms |
| @@ -1578,16 +1578,24 @@ | ||
| 1578 | 1578 | /* If all of the tests above have passed, that means that the submitted |
| 1579 | 1579 | ** form contains valid data and we can proceed to create the new login */ |
| 1580 | 1580 | Blob sql; |
| 1581 | 1581 | int uid; |
| 1582 | 1582 | char *zPass = sha1_shared_secret(zPasswd, zUserID, 0); |
| 1583 | + const char *zStartPerms = zPerms; | |
| 1584 | + if( db_get_boolean("selfreg-verify",0) ){ | |
| 1585 | + /* If email verification is required for self-registration, initalize | |
| 1586 | + ** the new user capabilities to just "7" (Sign up for email). The | |
| 1587 | + ** full "default-perms" permissions will be added when they click | |
| 1588 | + ** the verification link on the email they are sent. */ | |
| 1589 | + zStartPerms = "7"; | |
| 1590 | + } | |
| 1583 | 1591 | blob_init(&sql, 0, 0); |
| 1584 | 1592 | blob_append_sql(&sql, |
| 1585 | 1593 | "INSERT INTO user(login,pw,cap,info,mtime)\n" |
| 1586 | 1594 | "VALUES(%Q,%Q,%Q," |
| 1587 | 1595 | "'%q <%q>\nself-register from ip %q on '||datetime('now'),now())", |
| 1588 | - zUserID, zPass, zPerms, zDName, zEAddr, g.zIpAddr); | |
| 1596 | + zUserID, zPass, zStartPerms, zDName, zEAddr, g.zIpAddr); | |
| 1589 | 1597 | fossil_free(zPass); |
| 1590 | 1598 | db_multi_exec("%s", blob_sql_text(&sql)); |
| 1591 | 1599 | uid = db_int(0, "SELECT uid FROM user WHERE login=%Q", zUserID); |
| 1592 | 1600 | login_set_user_cookie(zUserID, uid, NULL); |
| 1593 | 1601 | if( doAlerts ){ |
| 1594 | 1602 |
| --- src/login.c | |
| +++ src/login.c | |
| @@ -481,11 +481,11 @@ | |
| 481 | int login_self_register_available(const char *zNeeded){ |
| 482 | CapabilityString *pCap; |
| 483 | int rc; |
| 484 | if( !db_get_boolean("self-register",0) ) return 0; |
| 485 | if( zNeeded==0 ) return 1; |
| 486 | pCap = capability_add(0, db_get("default-perms", 0)); |
| 487 | capability_expand(pCap); |
| 488 | rc = capability_has_any(pCap, zNeeded); |
| 489 | capability_free(pCap); |
| 490 | return rc; |
| 491 | } |
| @@ -1128,11 +1128,11 @@ | |
| 1128 | if( zPublicPages!=0 ){ |
| 1129 | Glob *pGlob = glob_create(zPublicPages); |
| 1130 | const char *zUri = PD("REQUEST_URI",""); |
| 1131 | zUri += (int)strlen(g.zTop); |
| 1132 | if( glob_match(pGlob, zUri) ){ |
| 1133 | login_set_capabilities(db_get("default-perms", 0), 0); |
| 1134 | } |
| 1135 | glob_free(pGlob); |
| 1136 | } |
| 1137 | } |
| 1138 | |
| @@ -1511,11 +1511,11 @@ | |
| 1511 | @ <p>This project does not allow user self-registration. Please contact the |
| 1512 | @ project administrator to obtain an account.</p> |
| 1513 | style_footer(); |
| 1514 | return; |
| 1515 | } |
| 1516 | zPerms = db_get("default-perms", 0); |
| 1517 | |
| 1518 | /* Prompt the user for email alerts if this repository is configured for |
| 1519 | ** email alerts and if the default permissions include "7" */ |
| 1520 | canDoAlerts = alert_tables_exist() && db_int(0, |
| 1521 | "SELECT fullcap(%Q) GLOB '*7*'", zPerms |
| @@ -1578,16 +1578,24 @@ | |
| 1578 | /* If all of the tests above have passed, that means that the submitted |
| 1579 | ** form contains valid data and we can proceed to create the new login */ |
| 1580 | Blob sql; |
| 1581 | int uid; |
| 1582 | char *zPass = sha1_shared_secret(zPasswd, zUserID, 0); |
| 1583 | blob_init(&sql, 0, 0); |
| 1584 | blob_append_sql(&sql, |
| 1585 | "INSERT INTO user(login,pw,cap,info,mtime)\n" |
| 1586 | "VALUES(%Q,%Q,%Q," |
| 1587 | "'%q <%q>\nself-register from ip %q on '||datetime('now'),now())", |
| 1588 | zUserID, zPass, zPerms, zDName, zEAddr, g.zIpAddr); |
| 1589 | fossil_free(zPass); |
| 1590 | db_multi_exec("%s", blob_sql_text(&sql)); |
| 1591 | uid = db_int(0, "SELECT uid FROM user WHERE login=%Q", zUserID); |
| 1592 | login_set_user_cookie(zUserID, uid, NULL); |
| 1593 | if( doAlerts ){ |
| 1594 |
| --- src/login.c | |
| +++ src/login.c | |
| @@ -481,11 +481,11 @@ | |
| 481 | int login_self_register_available(const char *zNeeded){ |
| 482 | CapabilityString *pCap; |
| 483 | int rc; |
| 484 | if( !db_get_boolean("self-register",0) ) return 0; |
| 485 | if( zNeeded==0 ) return 1; |
| 486 | pCap = capability_add(0, db_get("default-perms", "u")); |
| 487 | capability_expand(pCap); |
| 488 | rc = capability_has_any(pCap, zNeeded); |
| 489 | capability_free(pCap); |
| 490 | return rc; |
| 491 | } |
| @@ -1128,11 +1128,11 @@ | |
| 1128 | if( zPublicPages!=0 ){ |
| 1129 | Glob *pGlob = glob_create(zPublicPages); |
| 1130 | const char *zUri = PD("REQUEST_URI",""); |
| 1131 | zUri += (int)strlen(g.zTop); |
| 1132 | if( glob_match(pGlob, zUri) ){ |
| 1133 | login_set_capabilities(db_get("default-perms", "u"), 0); |
| 1134 | } |
| 1135 | glob_free(pGlob); |
| 1136 | } |
| 1137 | } |
| 1138 | |
| @@ -1511,11 +1511,11 @@ | |
| 1511 | @ <p>This project does not allow user self-registration. Please contact the |
| 1512 | @ project administrator to obtain an account.</p> |
| 1513 | style_footer(); |
| 1514 | return; |
| 1515 | } |
| 1516 | zPerms = db_get("default-perms", "u"); |
| 1517 | |
| 1518 | /* Prompt the user for email alerts if this repository is configured for |
| 1519 | ** email alerts and if the default permissions include "7" */ |
| 1520 | canDoAlerts = alert_tables_exist() && db_int(0, |
| 1521 | "SELECT fullcap(%Q) GLOB '*7*'", zPerms |
| @@ -1578,16 +1578,24 @@ | |
| 1578 | /* If all of the tests above have passed, that means that the submitted |
| 1579 | ** form contains valid data and we can proceed to create the new login */ |
| 1580 | Blob sql; |
| 1581 | int uid; |
| 1582 | char *zPass = sha1_shared_secret(zPasswd, zUserID, 0); |
| 1583 | const char *zStartPerms = zPerms; |
| 1584 | if( db_get_boolean("selfreg-verify",0) ){ |
| 1585 | /* If email verification is required for self-registration, initalize |
| 1586 | ** the new user capabilities to just "7" (Sign up for email). The |
| 1587 | ** full "default-perms" permissions will be added when they click |
| 1588 | ** the verification link on the email they are sent. */ |
| 1589 | zStartPerms = "7"; |
| 1590 | } |
| 1591 | blob_init(&sql, 0, 0); |
| 1592 | blob_append_sql(&sql, |
| 1593 | "INSERT INTO user(login,pw,cap,info,mtime)\n" |
| 1594 | "VALUES(%Q,%Q,%Q," |
| 1595 | "'%q <%q>\nself-register from ip %q on '||datetime('now'),now())", |
| 1596 | zUserID, zPass, zStartPerms, zDName, zEAddr, g.zIpAddr); |
| 1597 | fossil_free(zPass); |
| 1598 | db_multi_exec("%s", blob_sql_text(&sql)); |
| 1599 | uid = db_int(0, "SELECT uid FROM user WHERE login=%Q", zUserID); |
| 1600 | login_set_user_cookie(zUserID, uid, NULL); |
| 1601 | if( doAlerts ){ |
| 1602 |
+1
-1
| --- src/security_audit.c | ||
| +++ src/security_audit.c | ||
| @@ -122,11 +122,11 @@ | ||
| 122 | 122 | zAnonCap = db_text("", "SELECT fullcap(NULL)"); |
| 123 | 123 | zDevCap = db_text("", "SELECT fullcap('v')"); |
| 124 | 124 | zReadCap = db_text("", "SELECT fullcap('u')"); |
| 125 | 125 | zPubPages = db_get("public-pages",0); |
| 126 | 126 | hasSelfReg = db_get_boolean("self-register",0); |
| 127 | - pCap = capability_add(0, db_get("default-perms",0)); | |
| 127 | + pCap = capability_add(0, db_get("default-perms","u")); | |
| 128 | 128 | capability_expand(pCap); |
| 129 | 129 | zSelfCap = capability_string(pCap); |
| 130 | 130 | capability_free(pCap); |
| 131 | 131 | if( hasAnyCap(zAnonCap,"as") ){ |
| 132 | 132 | @ <li><p>This repository is <big><b>Wildly INSECURE</b></big> because |
| 133 | 133 |
| --- src/security_audit.c | |
| +++ src/security_audit.c | |
| @@ -122,11 +122,11 @@ | |
| 122 | zAnonCap = db_text("", "SELECT fullcap(NULL)"); |
| 123 | zDevCap = db_text("", "SELECT fullcap('v')"); |
| 124 | zReadCap = db_text("", "SELECT fullcap('u')"); |
| 125 | zPubPages = db_get("public-pages",0); |
| 126 | hasSelfReg = db_get_boolean("self-register",0); |
| 127 | pCap = capability_add(0, db_get("default-perms",0)); |
| 128 | capability_expand(pCap); |
| 129 | zSelfCap = capability_string(pCap); |
| 130 | capability_free(pCap); |
| 131 | if( hasAnyCap(zAnonCap,"as") ){ |
| 132 | @ <li><p>This repository is <big><b>Wildly INSECURE</b></big> because |
| 133 |
| --- src/security_audit.c | |
| +++ src/security_audit.c | |
| @@ -122,11 +122,11 @@ | |
| 122 | zAnonCap = db_text("", "SELECT fullcap(NULL)"); |
| 123 | zDevCap = db_text("", "SELECT fullcap('v')"); |
| 124 | zReadCap = db_text("", "SELECT fullcap('u')"); |
| 125 | zPubPages = db_get("public-pages",0); |
| 126 | hasSelfReg = db_get_boolean("self-register",0); |
| 127 | pCap = capability_add(0, db_get("default-perms","u")); |
| 128 | capability_expand(pCap); |
| 129 | zSelfCap = capability_string(pCap); |
| 130 | capability_free(pCap); |
| 131 | if( hasAnyCap(zAnonCap,"as") ){ |
| 132 | @ <li><p>This repository is <big><b>Wildly INSECURE</b></big> because |
| 133 |
+8
| --- src/setup.c | ||
| +++ src/setup.c | ||
| @@ -508,10 +508,18 @@ | ||
| 508 | 508 | @ (<em>auto-captcha</em> setting is ignored). Keep in mind that anyone |
| 509 | 509 | @ can register under any user name. This option is useful for public projects |
| 510 | 510 | @ where you do not want everyone in any ticket discussion to be named |
| 511 | 511 | @ "Anonymous". (Property: "self-register")</p> |
| 512 | 512 | |
| 513 | + @ <hr /> | |
| 514 | + onoff_attribute("Email verification required for self-registration", | |
| 515 | + "selfreg-verify", "selfregver", 0, 0); | |
| 516 | + @ <p>If enabled, self-registration creates a new entry in the USER table | |
| 517 | + @ but with provide any new capabilities until the email address provided | |
| 518 | + @ with registration has been verified. | |
| 519 | + @ (Property: "selfreg-verify")</p> | |
| 520 | + | |
| 513 | 521 | @ <hr /> |
| 514 | 522 | entry_attribute("Authorized self-registration email addresses", 35, |
| 515 | 523 | "self-reg-email", "selfregemail", "", 0); |
| 516 | 524 | @ <p>This is a comma-separated list of GLOB patterns that specify |
| 517 | 525 | @ email addresses that are authorized to self-register. If blank |
| 518 | 526 |
| --- src/setup.c | |
| +++ src/setup.c | |
| @@ -508,10 +508,18 @@ | |
| 508 | @ (<em>auto-captcha</em> setting is ignored). Keep in mind that anyone |
| 509 | @ can register under any user name. This option is useful for public projects |
| 510 | @ where you do not want everyone in any ticket discussion to be named |
| 511 | @ "Anonymous". (Property: "self-register")</p> |
| 512 | |
| 513 | @ <hr /> |
| 514 | entry_attribute("Authorized self-registration email addresses", 35, |
| 515 | "self-reg-email", "selfregemail", "", 0); |
| 516 | @ <p>This is a comma-separated list of GLOB patterns that specify |
| 517 | @ email addresses that are authorized to self-register. If blank |
| 518 |
| --- src/setup.c | |
| +++ src/setup.c | |
| @@ -508,10 +508,18 @@ | |
| 508 | @ (<em>auto-captcha</em> setting is ignored). Keep in mind that anyone |
| 509 | @ can register under any user name. This option is useful for public projects |
| 510 | @ where you do not want everyone in any ticket discussion to be named |
| 511 | @ "Anonymous". (Property: "self-register")</p> |
| 512 | |
| 513 | @ <hr /> |
| 514 | onoff_attribute("Email verification required for self-registration", |
| 515 | "selfreg-verify", "selfregver", 0, 0); |
| 516 | @ <p>If enabled, self-registration creates a new entry in the USER table |
| 517 | @ but with provide any new capabilities until the email address provided |
| 518 | @ with registration has been verified. |
| 519 | @ (Property: "selfreg-verify")</p> |
| 520 | |
| 521 | @ <hr /> |
| 522 | entry_attribute("Authorized self-registration email addresses", 35, |
| 523 | "self-reg-email", "selfregemail", "", 0); |
| 524 | @ <p>This is a comma-separated list of GLOB patterns that specify |
| 525 | @ email addresses that are authorized to self-register. If blank |
| 526 |
+1
-1
| --- src/setupuser.c | ||
| +++ src/setupuser.c | ||
| @@ -553,11 +553,11 @@ | ||
| 553 | 553 | if( alert_tables_exist() ){ |
| 554 | 554 | int sid; |
| 555 | 555 | sid = db_int(0, "SELECT subscriberId FROM subscriber" |
| 556 | 556 | " WHERE suname=%Q", zLogin); |
| 557 | 557 | if( sid>0 ){ |
| 558 | - @ <a href="%R/alerts?sid=%d(sid)>\ | |
| 558 | + @ <a href="%R/alerts?sid=%d(sid)">\ | |
| 559 | 559 | @ (subscription info for %h(zLogin))</a>\ |
| 560 | 560 | } |
| 561 | 561 | } |
| 562 | 562 | @ </td></tr> |
| 563 | 563 | @ <tr> |
| 564 | 564 |
| --- src/setupuser.c | |
| +++ src/setupuser.c | |
| @@ -553,11 +553,11 @@ | |
| 553 | if( alert_tables_exist() ){ |
| 554 | int sid; |
| 555 | sid = db_int(0, "SELECT subscriberId FROM subscriber" |
| 556 | " WHERE suname=%Q", zLogin); |
| 557 | if( sid>0 ){ |
| 558 | @ <a href="%R/alerts?sid=%d(sid)>\ |
| 559 | @ (subscription info for %h(zLogin))</a>\ |
| 560 | } |
| 561 | } |
| 562 | @ </td></tr> |
| 563 | @ <tr> |
| 564 |
| --- src/setupuser.c | |
| +++ src/setupuser.c | |
| @@ -553,11 +553,11 @@ | |
| 553 | if( alert_tables_exist() ){ |
| 554 | int sid; |
| 555 | sid = db_int(0, "SELECT subscriberId FROM subscriber" |
| 556 | " WHERE suname=%Q", zLogin); |
| 557 | if( sid>0 ){ |
| 558 | @ <a href="%R/alerts?sid=%d(sid)">\ |
| 559 | @ (subscription info for %h(zLogin))</a>\ |
| 560 | } |
| 561 | } |
| 562 | @ </td></tr> |
| 563 | @ <tr> |
| 564 |