Fossil SCM

First attempt at a /subscribe page. Non-functional display only.

drh 2018-06-20 22:39 trunk
Commit fb3934ec53e86be5d2694cdcd0577fc542eb18fcb4ff07111b412087be96fa9f
2 files changed +4 +89 -50
--- src/default_css.txt
+++ src/default_css.txt
@@ -668,5 +668,9 @@
668668
padding: 1px;
669669
}
670670
div.forum_body p {
671671
margin-top: 0;
672672
}
673
+td.form_label {
674
+ vertical-align: top;
675
+ text-align: right;
676
+}
673677
--- src/default_css.txt
+++ src/default_css.txt
@@ -668,5 +668,9 @@
668 padding: 1px;
669 }
670 div.forum_body p {
671 margin-top: 0;
672 }
 
 
 
 
673
--- src/default_css.txt
+++ src/default_css.txt
@@ -668,5 +668,9 @@
668 padding: 1px;
669 }
670 div.forum_body p {
671 margin-top: 0;
672 }
673 td.form_label {
674 vertical-align: top;
675 text-align: right;
676 }
677
+89 -50
--- src/email.c
+++ src/email.c
@@ -30,10 +30,20 @@
3030
@ -- the USER table without being a subscriber. Or a person can be a
3131
@ -- subscriber without having a USER table entry. Or they can have both.
3232
@ -- In the last case the suname column points from the subscriber entry
3333
@ -- to the USER entry.
3434
@ --
35
+@ -- The ssub field is a string where each character indicates a particular
36
+@ -- type of event to subscribe to. Choices:
37
+@ -- a - Announcements
38
+@ -- c - Check-ins
39
+@ -- t - Ticket changes
40
+@ -- w - Wiki changes
41
+@ -- Probably different codes will be added in the future. In the future
42
+@ -- we might also add a separate table that allows subscribing to email
43
+@ -- notifications for specific branches or tags or tickets.
44
+@ --
3545
@ CREATE TABLE repository.subscriber(
3646
@ subscriberId INTEGER PRIMARY KEY, -- numeric subscriber ID. Internal use
3747
@ subscriberCode TEXT UNIQUE, -- UUID for subscriber. External use
3848
@ sname TEXT, -- Human readable name
3949
@ suname TEXT, -- Corresponding USER or NULL
@@ -46,48 +56,10 @@
4656
@ smtime DATE, -- Last change. JulianDay
4757
@ sipaddr TEXT, -- IP address for last change
4858
@ spswdHash TEXT -- SHA3 hash of password
4959
@ );
5060
@
51
-@ -- Each subscriber is associated with zero or more subscriptions. Each
52
-@ -- subscription identifies events for which the subscriber desires
53
-@ -- email notification.
54
-@ --
55
-@ -- The stype field can be:
56
-@ --
57
-@ -- 'c' Check-ins
58
-@ -- 'w' Wiki pages
59
-@ -- 't' Tickets
60
-@ -- 'e' Tech-notes
61
-@ -- 'g' Tags
62
-@ -- 'f' Forum posts
63
-@ -- 'm' Any item in need of moderation
64
-@ --
65
-@ -- stype values are restricted to items that suname is allowed to see.
66
-@ -- If suname is NULL, then stype values are restricted to things that
67
-@ -- user "nobody" is allowed to see.
68
-@ --
69
-@ -- The sarg field provides additional restrictions. Since it is
70
-@ -- part of the primary key, sarg cannot be NULL. Use an empty string
71
-@ -- instead.
72
-@ --
73
-@ -- For check-ins, sargs can be a tag that is on the check-in. Examples:
74
-@ -- 'trunk', or 'release'. Notifications are only sent if that tag is
75
-@ -- present. For wiki, the sarg is a glob pattern matching the page name.
76
-@ -- For tickets, sarg is the UUID of the ticket. And so forth.
77
-@ --
78
-@ -- For the 'x' subscription, email is sent for any timeline event whose
79
-@ -- text matches the GLOB pattern defined by sarg.
80
-@ --
81
-@ CREATE TABLE repository.subscription(
82
-@ subscriberId INTEGER, -- Which user has subscribed
83
-@ stype TEXT, -- event type
84
-@ sarg TEXT, -- additional event restriction
85
-@ PRIMARY KEY(stype,sarg,subscriberId)
86
-@ ) WITHOUT ROWID;
87
-@ CREATE INDEX repository.subscription_x1 ON subscription(subscriberId);
88
-@
8961
@ -- Email notifications that need to be sent.
9062
@ --
9163
@ -- If the eventid key is an integer, then it corresponds to the
9264
@ -- EVENT.OBJID table. Other kinds of eventids are reserved for
9365
@ -- future expansion.
@@ -355,10 +327,14 @@
355327
** COMMAND: email
356328
**
357329
** Usage: %fossil email SUBCOMMAND ARGS...
358330
**
359331
** Subcommands:
332
+**
333
+** reset Hard reset of all email notification tables
334
+** in the repository. This erases all subscription
335
+** information. Use with extreme care.
360336
**
361337
** send TO [OPTIONS] Send a single email message using whatever
362338
** email sending mechanism is currently configured.
363339
** Use this for testing the email configuration.
364340
** Options:
@@ -376,10 +352,30 @@
376352
int nCmd;
377353
db_find_and_open_repository(0, 0);
378354
email_schema();
379355
zCmd = g.argc>=3 ? g.argv[2] : "x";
380356
nCmd = (int)strlen(zCmd);
357
+ if( strncmp(zCmd, "reset", nCmd)==0 ){
358
+ Blob yn;
359
+ int c;
360
+ fossil_print(
361
+ "This will erase all content in the repository tables, thus\n"
362
+ "deleting all subscriber information. The information will be\n"
363
+ "unrecoverable.\n");
364
+ prompt_user("Continue? (y/N) ", &yn);
365
+ c = blob_str(&yn)[0];
366
+ if( c=='y' ){
367
+ db_multi_exec(
368
+ "DROP TABLE IF EXISTS subscriber;\n"
369
+ "DROP TABLE IF EXISTS subscription;\n"
370
+ "DROP TABLE IF EXISTS email_pending;\n"
371
+ "DROP TABLE IF EXISTS email_bounce;\n"
372
+ );
373
+ email_schema();
374
+ }
375
+ blob_zero(&yn);
376
+ }else
381377
if( strncmp(zCmd, "send", nCmd)==0 ){
382378
Blob prompt, body, hdr;
383379
int sendAsBoth = find_option("both",0,0)!=0;
384380
int sendAsHtml = find_option("html",0,0)!=0;
385381
const char *zDest = find_option("stdout",0,0)!=0 ? "stdout" : 0;
@@ -438,11 +434,11 @@
438434
if( strncmp(pSetting->name,"email-",6)!=0 ) continue;
439435
print_setting(pSetting);
440436
}
441437
}
442438
else{
443
- usage("send|setting");
439
+ usage("reset|send|setting");
444440
}
445441
}
446442
447443
/*
448444
** WEBPAGE: subscribe
@@ -449,32 +445,75 @@
449445
**
450446
** Allow users to subscribe to email notifications, or to change or
451447
** verify their subscription.
452448
*/
453449
void subscribe_page(void){
450
+ int needCaptcha;
451
+ unsigned int uSeed;
452
+ const char *zDecoded;
453
+ char *zCaptcha;
454
+
454455
login_check_credentials();
455456
if( !g.perm.EmailAlert ){
456457
login_needed(g.anon.EmailAlert);
457458
return;
458459
}
459460
style_header("Email Subscription");
461
+ needCaptcha = P("usecaptcha")!=0 || login_is_nobody()
462
+ || login_is_special(g.zLogin);
460463
form_begin(0, "%R/subscribe");
461464
@ <table class="subscribe">
462465
@ <tr>
463
- @ <td class="subscribe_label">Nickname:</td>
464
- @ <td><input type="text" id="nn" value="" size="30"></td>
466
+ @ <td class="form_label">Email&nbsp;Address:</td>
467
+ @ <td><input type="text" name="e" value="" size="30"></td>
468
+ @ <td></td>
469
+ @ </tr>
470
+ if( needCaptcha ){
471
+ uSeed = captcha_seed();
472
+ zDecoded = captcha_decode(uSeed);
473
+ zCaptcha = captcha_render(zDecoded);
474
+ @ <tr>
475
+ @ <td class="form_label">Security Code:</td>
476
+ @ <td><input type="text" name="captcha" value="" size="30">
477
+ @ <input type="hidden" name="usecaptcha" value="1"></td>
478
+ @ <input type="hidden" name="captchaseed" value="%u(uSeed)"></td>
479
+ @ <td><span class="optionalTag">(copy from below)</span></td>
480
+ @ </tr>
481
+ }
482
+ @ <tr>
483
+ @ <td class="form_label">Nickname:</td>
484
+ @ <td><input type="text" name="nn" value="" size="30"></td>
485
+ @ <td><span class="optionalTag">(optional)</span></td>
486
+ @ </tr>
487
+ @ <tr>
488
+ @ <td class="form_label">Password:</td>
489
+ @ <td><input type="password" name="pw" value="" size="30"></td>
465490
@ <td><span class="optionalTag">(optional)</span></td>
466491
@ </tr>
467492
@ <tr>
468
- @ <td class="subscribe_label">Email&nbsp;Address:</td>
469
- @ <td><input type="text" id="e" value="" size="30"></td>
470
- @ <td></td>
493
+ @ <td class="form_label">Options:</td>
494
+ @ <td><label><input type="checkbox" name="sa" value="0">\
495
+ @ Announcements</label><br>
496
+ @ <label><input type="checkbox" name="sc" value="0">\
497
+ @ Check-ins</label><br>
498
+ @ <label><input type="checkbox" name="st" value="0">\
499
+ @ Ticket changes</label><br>
500
+ @ <label><input type="checkbox" name="sw" value="0">\
501
+ @ Wiki</label><br>
502
+ @ <label><input type="checkbox" name="di" value="0">\
503
+ @ Daily digest only</label><br></td>
471504
@ </tr>
472505
@ <tr>
473
- @ <td class="subscribe_label">Password:</td>
474
- @ <td><input type="password" id="p1" value="" size="30"></td>
475
- @ <td><span class="optionalTag">(optional)</span></td>
506
+ @ <td></td>
507
+ @ <td><input type="submit" value="Submit"></td>
476508
@ </tr>
477
-
478
-
479
-
509
+ @ </table>
510
+ if( needCaptcha ){
511
+ @ <div class="captcha"><table class="captcha"><tr><td><pre>
512
+ @ %h(zCaptcha)
513
+ @ </pre>
514
+ @ Enter the 8 characters above in the "Security Code" box
515
+ @ </td></tr></table></div>
516
+ }
517
+ @ </form>
518
+ style_footer();
480519
}
481520
--- src/email.c
+++ src/email.c
@@ -30,10 +30,20 @@
30 @ -- the USER table without being a subscriber. Or a person can be a
31 @ -- subscriber without having a USER table entry. Or they can have both.
32 @ -- In the last case the suname column points from the subscriber entry
33 @ -- to the USER entry.
34 @ --
 
 
 
 
 
 
 
 
 
 
35 @ CREATE TABLE repository.subscriber(
36 @ subscriberId INTEGER PRIMARY KEY, -- numeric subscriber ID. Internal use
37 @ subscriberCode TEXT UNIQUE, -- UUID for subscriber. External use
38 @ sname TEXT, -- Human readable name
39 @ suname TEXT, -- Corresponding USER or NULL
@@ -46,48 +56,10 @@
46 @ smtime DATE, -- Last change. JulianDay
47 @ sipaddr TEXT, -- IP address for last change
48 @ spswdHash TEXT -- SHA3 hash of password
49 @ );
50 @
51 @ -- Each subscriber is associated with zero or more subscriptions. Each
52 @ -- subscription identifies events for which the subscriber desires
53 @ -- email notification.
54 @ --
55 @ -- The stype field can be:
56 @ --
57 @ -- 'c' Check-ins
58 @ -- 'w' Wiki pages
59 @ -- 't' Tickets
60 @ -- 'e' Tech-notes
61 @ -- 'g' Tags
62 @ -- 'f' Forum posts
63 @ -- 'm' Any item in need of moderation
64 @ --
65 @ -- stype values are restricted to items that suname is allowed to see.
66 @ -- If suname is NULL, then stype values are restricted to things that
67 @ -- user "nobody" is allowed to see.
68 @ --
69 @ -- The sarg field provides additional restrictions. Since it is
70 @ -- part of the primary key, sarg cannot be NULL. Use an empty string
71 @ -- instead.
72 @ --
73 @ -- For check-ins, sargs can be a tag that is on the check-in. Examples:
74 @ -- 'trunk', or 'release'. Notifications are only sent if that tag is
75 @ -- present. For wiki, the sarg is a glob pattern matching the page name.
76 @ -- For tickets, sarg is the UUID of the ticket. And so forth.
77 @ --
78 @ -- For the 'x' subscription, email is sent for any timeline event whose
79 @ -- text matches the GLOB pattern defined by sarg.
80 @ --
81 @ CREATE TABLE repository.subscription(
82 @ subscriberId INTEGER, -- Which user has subscribed
83 @ stype TEXT, -- event type
84 @ sarg TEXT, -- additional event restriction
85 @ PRIMARY KEY(stype,sarg,subscriberId)
86 @ ) WITHOUT ROWID;
87 @ CREATE INDEX repository.subscription_x1 ON subscription(subscriberId);
88 @
89 @ -- Email notifications that need to be sent.
90 @ --
91 @ -- If the eventid key is an integer, then it corresponds to the
92 @ -- EVENT.OBJID table. Other kinds of eventids are reserved for
93 @ -- future expansion.
@@ -355,10 +327,14 @@
355 ** COMMAND: email
356 **
357 ** Usage: %fossil email SUBCOMMAND ARGS...
358 **
359 ** Subcommands:
 
 
 
 
360 **
361 ** send TO [OPTIONS] Send a single email message using whatever
362 ** email sending mechanism is currently configured.
363 ** Use this for testing the email configuration.
364 ** Options:
@@ -376,10 +352,30 @@
376 int nCmd;
377 db_find_and_open_repository(0, 0);
378 email_schema();
379 zCmd = g.argc>=3 ? g.argv[2] : "x";
380 nCmd = (int)strlen(zCmd);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
381 if( strncmp(zCmd, "send", nCmd)==0 ){
382 Blob prompt, body, hdr;
383 int sendAsBoth = find_option("both",0,0)!=0;
384 int sendAsHtml = find_option("html",0,0)!=0;
385 const char *zDest = find_option("stdout",0,0)!=0 ? "stdout" : 0;
@@ -438,11 +434,11 @@
438 if( strncmp(pSetting->name,"email-",6)!=0 ) continue;
439 print_setting(pSetting);
440 }
441 }
442 else{
443 usage("send|setting");
444 }
445 }
446
447 /*
448 ** WEBPAGE: subscribe
@@ -449,32 +445,75 @@
449 **
450 ** Allow users to subscribe to email notifications, or to change or
451 ** verify their subscription.
452 */
453 void subscribe_page(void){
 
 
 
 
 
454 login_check_credentials();
455 if( !g.perm.EmailAlert ){
456 login_needed(g.anon.EmailAlert);
457 return;
458 }
459 style_header("Email Subscription");
 
 
460 form_begin(0, "%R/subscribe");
461 @ <table class="subscribe">
462 @ <tr>
463 @ <td class="subscribe_label">Nickname:</td>
464 @ <td><input type="text" id="nn" value="" size="30"></td>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
465 @ <td><span class="optionalTag">(optional)</span></td>
466 @ </tr>
467 @ <tr>
468 @ <td class="subscribe_label">Email&nbsp;Address:</td>
469 @ <td><input type="text" id="e" value="" size="30"></td>
470 @ <td></td>
 
 
 
 
 
 
 
 
471 @ </tr>
472 @ <tr>
473 @ <td class="subscribe_label">Password:</td>
474 @ <td><input type="password" id="p1" value="" size="30"></td>
475 @ <td><span class="optionalTag">(optional)</span></td>
476 @ </tr>
477
478
479
 
 
 
 
 
 
 
480 }
481
--- src/email.c
+++ src/email.c
@@ -30,10 +30,20 @@
30 @ -- the USER table without being a subscriber. Or a person can be a
31 @ -- subscriber without having a USER table entry. Or they can have both.
32 @ -- In the last case the suname column points from the subscriber entry
33 @ -- to the USER entry.
34 @ --
35 @ -- The ssub field is a string where each character indicates a particular
36 @ -- type of event to subscribe to. Choices:
37 @ -- a - Announcements
38 @ -- c - Check-ins
39 @ -- t - Ticket changes
40 @ -- w - Wiki changes
41 @ -- Probably different codes will be added in the future. In the future
42 @ -- we might also add a separate table that allows subscribing to email
43 @ -- notifications for specific branches or tags or tickets.
44 @ --
45 @ CREATE TABLE repository.subscriber(
46 @ subscriberId INTEGER PRIMARY KEY, -- numeric subscriber ID. Internal use
47 @ subscriberCode TEXT UNIQUE, -- UUID for subscriber. External use
48 @ sname TEXT, -- Human readable name
49 @ suname TEXT, -- Corresponding USER or NULL
@@ -46,48 +56,10 @@
56 @ smtime DATE, -- Last change. JulianDay
57 @ sipaddr TEXT, -- IP address for last change
58 @ spswdHash TEXT -- SHA3 hash of password
59 @ );
60 @
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
61 @ -- Email notifications that need to be sent.
62 @ --
63 @ -- If the eventid key is an integer, then it corresponds to the
64 @ -- EVENT.OBJID table. Other kinds of eventids are reserved for
65 @ -- future expansion.
@@ -355,10 +327,14 @@
327 ** COMMAND: email
328 **
329 ** Usage: %fossil email SUBCOMMAND ARGS...
330 **
331 ** Subcommands:
332 **
333 ** reset Hard reset of all email notification tables
334 ** in the repository. This erases all subscription
335 ** information. Use with extreme care.
336 **
337 ** send TO [OPTIONS] Send a single email message using whatever
338 ** email sending mechanism is currently configured.
339 ** Use this for testing the email configuration.
340 ** Options:
@@ -376,10 +352,30 @@
352 int nCmd;
353 db_find_and_open_repository(0, 0);
354 email_schema();
355 zCmd = g.argc>=3 ? g.argv[2] : "x";
356 nCmd = (int)strlen(zCmd);
357 if( strncmp(zCmd, "reset", nCmd)==0 ){
358 Blob yn;
359 int c;
360 fossil_print(
361 "This will erase all content in the repository tables, thus\n"
362 "deleting all subscriber information. The information will be\n"
363 "unrecoverable.\n");
364 prompt_user("Continue? (y/N) ", &yn);
365 c = blob_str(&yn)[0];
366 if( c=='y' ){
367 db_multi_exec(
368 "DROP TABLE IF EXISTS subscriber;\n"
369 "DROP TABLE IF EXISTS subscription;\n"
370 "DROP TABLE IF EXISTS email_pending;\n"
371 "DROP TABLE IF EXISTS email_bounce;\n"
372 );
373 email_schema();
374 }
375 blob_zero(&yn);
376 }else
377 if( strncmp(zCmd, "send", nCmd)==0 ){
378 Blob prompt, body, hdr;
379 int sendAsBoth = find_option("both",0,0)!=0;
380 int sendAsHtml = find_option("html",0,0)!=0;
381 const char *zDest = find_option("stdout",0,0)!=0 ? "stdout" : 0;
@@ -438,11 +434,11 @@
434 if( strncmp(pSetting->name,"email-",6)!=0 ) continue;
435 print_setting(pSetting);
436 }
437 }
438 else{
439 usage("reset|send|setting");
440 }
441 }
442
443 /*
444 ** WEBPAGE: subscribe
@@ -449,32 +445,75 @@
445 **
446 ** Allow users to subscribe to email notifications, or to change or
447 ** verify their subscription.
448 */
449 void subscribe_page(void){
450 int needCaptcha;
451 unsigned int uSeed;
452 const char *zDecoded;
453 char *zCaptcha;
454
455 login_check_credentials();
456 if( !g.perm.EmailAlert ){
457 login_needed(g.anon.EmailAlert);
458 return;
459 }
460 style_header("Email Subscription");
461 needCaptcha = P("usecaptcha")!=0 || login_is_nobody()
462 || login_is_special(g.zLogin);
463 form_begin(0, "%R/subscribe");
464 @ <table class="subscribe">
465 @ <tr>
466 @ <td class="form_label">Email&nbsp;Address:</td>
467 @ <td><input type="text" name="e" value="" size="30"></td>
468 @ <td></td>
469 @ </tr>
470 if( needCaptcha ){
471 uSeed = captcha_seed();
472 zDecoded = captcha_decode(uSeed);
473 zCaptcha = captcha_render(zDecoded);
474 @ <tr>
475 @ <td class="form_label">Security Code:</td>
476 @ <td><input type="text" name="captcha" value="" size="30">
477 @ <input type="hidden" name="usecaptcha" value="1"></td>
478 @ <input type="hidden" name="captchaseed" value="%u(uSeed)"></td>
479 @ <td><span class="optionalTag">(copy from below)</span></td>
480 @ </tr>
481 }
482 @ <tr>
483 @ <td class="form_label">Nickname:</td>
484 @ <td><input type="text" name="nn" value="" size="30"></td>
485 @ <td><span class="optionalTag">(optional)</span></td>
486 @ </tr>
487 @ <tr>
488 @ <td class="form_label">Password:</td>
489 @ <td><input type="password" name="pw" value="" size="30"></td>
490 @ <td><span class="optionalTag">(optional)</span></td>
491 @ </tr>
492 @ <tr>
493 @ <td class="form_label">Options:</td>
494 @ <td><label><input type="checkbox" name="sa" value="0">\
495 @ Announcements</label><br>
496 @ <label><input type="checkbox" name="sc" value="0">\
497 @ Check-ins</label><br>
498 @ <label><input type="checkbox" name="st" value="0">\
499 @ Ticket changes</label><br>
500 @ <label><input type="checkbox" name="sw" value="0">\
501 @ Wiki</label><br>
502 @ <label><input type="checkbox" name="di" value="0">\
503 @ Daily digest only</label><br></td>
504 @ </tr>
505 @ <tr>
506 @ <td></td>
507 @ <td><input type="submit" value="Submit"></td>
 
508 @ </tr>
509 @ </table>
510 if( needCaptcha ){
511 @ <div class="captcha"><table class="captcha"><tr><td><pre>
512 @ %h(zCaptcha)
513 @ </pre>
514 @ Enter the 8 characters above in the "Security Code" box
515 @ </td></tr></table></div>
516 }
517 @ </form>
518 style_footer();
519 }
520

Keyboard Shortcuts

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