Fossil SCM

Add an admin/debug flag to the forum which enables the user to skip sending of notifications for a given new post or edit.

stephan 2023-04-19 00:46 trunk merge
Commit 3f6aa94641ad9283218b617b3c6e572f75b266ee32917fe55de38541387ec6eb
2 files changed +17 -1 +50 -29
+17 -1
--- src/alerts.c
+++ src/alerts.c
@@ -186,11 +186,11 @@
186186
" ON CONFLICT(eventId) DO NOTHING;\n"
187187
"END;"
188188
);
189189
}
190190
if( db_table_exists("repository","chat")
191
- && db_get("chat-timeline-user", "")[0]!=0
191
+ && db_get("chat-timeline-user", "")[0]!=0
192192
){
193193
/* Record events that will be relayed to chat, but do not relay
194194
** them immediately, as the chat_msg_from_event() function requires
195195
** that TAGXREF be up-to-date, and that has not happened yet when
196196
** the insert into the EVENT table occurs. Make arrangements to
@@ -233,10 +233,26 @@
233233
int alert_enabled(void){
234234
if( !alert_tables_exist() ) return 0;
235235
if( fossil_strcmp(db_get("email-send-method",0),"off")==0 ) return 0;
236236
return 1;
237237
}
238
+
239
+/*
240
+** If alerts are enabled, removes the pending_alert entry which
241
+** matches (eventType || rid). Note that pending_alert entries are
242
+** added via the manifest crosslinking process, so this has no effect
243
+** if called before crosslinking is performed. Because alerts are sent
244
+** asynchronously, unqueuing needs to be performed as part of the
245
+** transaction in which crosslinking is performed in order to avoid a
246
+** race condition.
247
+*/
248
+void alert_unqueue(char eventType, int rid){
249
+ if( alert_enabled() ){
250
+ db_multi_exec("DELETE FROM pending_alert WHERE eventid='%c%d'",
251
+ eventType, rid);
252
+ }
253
+}
238254
239255
/*
240256
** If the subscriber table does not exist, then paint an error message
241257
** web page and return true.
242258
**
243259
--- src/alerts.c
+++ src/alerts.c
@@ -186,11 +186,11 @@
186 " ON CONFLICT(eventId) DO NOTHING;\n"
187 "END;"
188 );
189 }
190 if( db_table_exists("repository","chat")
191 && db_get("chat-timeline-user", "")[0]!=0
192 ){
193 /* Record events that will be relayed to chat, but do not relay
194 ** them immediately, as the chat_msg_from_event() function requires
195 ** that TAGXREF be up-to-date, and that has not happened yet when
196 ** the insert into the EVENT table occurs. Make arrangements to
@@ -233,10 +233,26 @@
233 int alert_enabled(void){
234 if( !alert_tables_exist() ) return 0;
235 if( fossil_strcmp(db_get("email-send-method",0),"off")==0 ) return 0;
236 return 1;
237 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
238
239 /*
240 ** If the subscriber table does not exist, then paint an error message
241 ** web page and return true.
242 **
243
--- src/alerts.c
+++ src/alerts.c
@@ -186,11 +186,11 @@
186 " ON CONFLICT(eventId) DO NOTHING;\n"
187 "END;"
188 );
189 }
190 if( db_table_exists("repository","chat")
191 && db_get("chat-timeline-user", "")[0]!=0
192 ){
193 /* Record events that will be relayed to chat, but do not relay
194 ** them immediately, as the chat_msg_from_event() function requires
195 ** that TAGXREF be up-to-date, and that has not happened yet when
196 ** the insert into the EVENT table occurs. Make arrangements to
@@ -233,10 +233,26 @@
233 int alert_enabled(void){
234 if( !alert_tables_exist() ) return 0;
235 if( fossil_strcmp(db_get("email-send-method",0),"off")==0 ) return 0;
236 return 1;
237 }
238
239 /*
240 ** If alerts are enabled, removes the pending_alert entry which
241 ** matches (eventType || rid). Note that pending_alert entries are
242 ** added via the manifest crosslinking process, so this has no effect
243 ** if called before crosslinking is performed. Because alerts are sent
244 ** asynchronously, unqueuing needs to be performed as part of the
245 ** transaction in which crosslinking is performed in order to avoid a
246 ** race condition.
247 */
248 void alert_unqueue(char eventType, int rid){
249 if( alert_enabled() ){
250 db_multi_exec("DELETE FROM pending_alert WHERE eventid='%c%d'",
251 eventType, rid);
252 }
253 }
254
255 /*
256 ** If the subscriber table does not exist, then paint an error message
257 ** web page and return true.
258 **
259
+50 -29
--- src/forum.c
+++ src/forum.c
@@ -945,10 +945,25 @@
945945
static int whitespace_only(const char *z){
946946
if( z==0 ) return 1;
947947
while( z[0] && fossil_isspace(z[0]) ){ z++; }
948948
return z[0]==0;
949949
}
950
+
951
+/* Flags for use with forum_post() */
952
+#define FPOST_NO_ALERT 1 /* do not send any alerts */
953
+
954
+/*
955
+** Return a flags value for use with the final argument to
956
+** forum_post(), extracted from the CGI environment.
957
+*/
958
+static int forum_post_flags(void){
959
+ int iPostFlags = 0;
960
+ if( g.perm.Debug && P("fpsilent")!=0 ){
961
+ iPostFlags |= FPOST_NO_ALERT;
962
+ }
963
+ return iPostFlags;
964
+}
950965
951966
/*
952967
** Add a new Forum Post artifact to the repository.
953968
**
954969
** Return true if a redirect occurs.
@@ -957,11 +972,12 @@
957972
const char *zTitle, /* Title. NULL for replies */
958973
int iInReplyTo, /* Post replying to. 0 for new threads */
959974
int iEdit, /* Post being edited, or zero for a new post */
960975
const char *zUser, /* Username. NULL means use login name */
961976
const char *zMimetype, /* Mimetype of content. */
962
- const char *zContent /* Content */
977
+ const char *zContent, /* Content */
978
+ int iFlags /* FPOST_xyz flag values */
963979
){
964980
char *zDate;
965981
char *zI;
966982
char *zG;
967983
int iBasis;
@@ -1039,13 +1055,18 @@
10391055
@ <pre>%h(blob_str(&x))</pre>
10401056
@ </div>
10411057
blob_reset(&x);
10421058
return 0;
10431059
}else{
1044
- int nrid = wiki_put(&x, iEdit>0 ? iEdit : 0,
1045
- forum_need_moderation());
1060
+ int nrid;
1061
+ db_begin_transaction();
1062
+ nrid = wiki_put(&x, iEdit>0 ? iEdit : 0, forum_need_moderation());
10461063
blob_reset(&x);
1064
+ if( (iFlags & FPOST_NO_ALERT)!=0 ){
1065
+ alert_unqueue('f', nrid);
1066
+ }
1067
+ db_commit_transaction();
10471068
cgi_redirectf("%R/forumpost/%S", rid_to_uuid(nrid));
10481069
return 1;
10491070
}
10501071
}
10511072
@@ -1135,10 +1156,27 @@
11351156
@ From: anonymous<br>
11361157
}else{
11371158
@ From: %h(login_name())<br>
11381159
}
11391160
}
1161
+
1162
+static void forum_render_debug_options(void){
1163
+ if( g.perm.Debug ){
1164
+ /* Give extra control over the post to users with the special
1165
+ * Debug capability, which includes Admin and Setup users */
1166
+ @ <div class="debug">
1167
+ @ <label><input type="checkbox" name="dryrun" %s(PCK("dryrun"))> \
1168
+ @ Dry run</label>
1169
+ @ <br><label><input type="checkbox" name="domod" %s(PCK("domod"))> \
1170
+ @ Require moderator approval</label>
1171
+ @ <br><label><input type="checkbox" name="showqp" %s(PCK("showqp"))> \
1172
+ @ Show query parameters</label>
1173
+ @ <br><label><input type="checkbox" name="fpsilent" %s(PCK("fpsilent"))> \
1174
+ @ Do not sent notification emails</label>
1175
+ @ </div>
1176
+ }
1177
+}
11401178
11411179
/*
11421180
** WEBPAGE: forume1
11431181
**
11441182
** Start a new forum thread.
@@ -1145,17 +1183,19 @@
11451183
*/
11461184
void forumnew_page(void){
11471185
const char *zTitle = PDT("title","");
11481186
const char *zMimetype = PD("mimetype",DEFAULT_FORUM_MIMETYPE);
11491187
const char *zContent = PDT("content","");
1188
+
11501189
login_check_credentials();
11511190
if( !g.perm.WrForum ){
11521191
login_needed(g.anon.WrForum);
11531192
return;
11541193
}
11551194
if( P("submit") && cgi_csrf_safe(1) ){
1156
- if( forum_post(zTitle, 0, 0, 0, zMimetype, zContent) ) return;
1195
+ if( forum_post(zTitle, 0, 0, 0, zMimetype, zContent,
1196
+ forum_post_flags()) ) return;
11571197
}
11581198
if( P("preview") && !whitespace_only(zContent) ){
11591199
@ <h1>Preview:</h1>
11601200
forum_render(zTitle, zMimetype, zContent, "forumEdit", 1);
11611201
}
@@ -1169,22 +1209,11 @@
11691209
if( P("preview") && !whitespace_only(zContent) ){
11701210
@ <input type="submit" name="submit" value="Submit">
11711211
}else{
11721212
@ <input type="submit" name="submit" value="Submit" disabled>
11731213
}
1174
- if( g.perm.Debug ){
1175
- /* Give extra control over the post to users with the special
1176
- * Debug capability, which includes Admin and Setup users */
1177
- @ <div class="debug">
1178
- @ <label><input type="checkbox" name="dryrun" %s(PCK("dryrun"))> \
1179
- @ Dry run</label>
1180
- @ <br><label><input type="checkbox" name="domod" %s(PCK("domod"))> \
1181
- @ Require moderator approval</label>
1182
- @ <br><label><input type="checkbox" name="showqp" %s(PCK("showqp"))> \
1183
- @ Show query parameters</label>
1184
- @ </div>
1185
- }
1214
+ forum_render_debug_options();
11861215
@ </form>
11871216
forum_emit_js();
11881217
style_finish_page();
11891218
}
11901219
@@ -1273,13 +1302,15 @@
12731302
&& (!whitespace_only(zContent) || isDelete)
12741303
){
12751304
int done = 1;
12761305
const char *zMimetype = PD("mimetype",DEFAULT_FORUM_MIMETYPE);
12771306
if( P("reply") ){
1278
- done = forum_post(0, fpid, 0, 0, zMimetype, zContent);
1307
+ done = forum_post(0, fpid, 0, 0, zMimetype, zContent,
1308
+ forum_post_flags());
12791309
}else if( P("edit") || isDelete ){
1280
- done = forum_post(P("title"), 0, fpid, 0, zMimetype, zContent);
1310
+ done = forum_post(P("title"), 0, fpid, 0, zMimetype, zContent,
1311
+ forum_post_flags());
12811312
}else{
12821313
webpage_error("Missing 'reply' query parameter");
12831314
}
12841315
if( done ) return;
12851316
}
@@ -1360,21 +1391,11 @@
13601391
}
13611392
@ <input type="submit" name="cancel" value="Cancel">
13621393
if( (P("preview") && !whitespace_only(zContent)) || isDelete ){
13631394
@ <input type="submit" name="submit" value="Submit">
13641395
}
1365
- if( g.perm.Debug ){
1366
- /* For the test-forumnew page add these extra debugging controls */
1367
- @ <div class="debug">
1368
- @ <label><input type="checkbox" name="dryrun" %s(PCK("dryrun"))> \
1369
- @ Dry run</label>
1370
- @ <br><label><input type="checkbox" name="domod" %s(PCK("domod"))> \
1371
- @ Require moderator approval</label>
1372
- @ <br><label><input type="checkbox" name="showqp" %s(PCK("showqp"))> \
1373
- @ Show query parameters</label>
1374
- @ </div>
1375
- }
1396
+ forum_render_debug_options();
13761397
@ </form>
13771398
forum_emit_js();
13781399
style_finish_page();
13791400
}
13801401
13811402
--- src/forum.c
+++ src/forum.c
@@ -945,10 +945,25 @@
945 static int whitespace_only(const char *z){
946 if( z==0 ) return 1;
947 while( z[0] && fossil_isspace(z[0]) ){ z++; }
948 return z[0]==0;
949 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
950
951 /*
952 ** Add a new Forum Post artifact to the repository.
953 **
954 ** Return true if a redirect occurs.
@@ -957,11 +972,12 @@
957 const char *zTitle, /* Title. NULL for replies */
958 int iInReplyTo, /* Post replying to. 0 for new threads */
959 int iEdit, /* Post being edited, or zero for a new post */
960 const char *zUser, /* Username. NULL means use login name */
961 const char *zMimetype, /* Mimetype of content. */
962 const char *zContent /* Content */
 
963 ){
964 char *zDate;
965 char *zI;
966 char *zG;
967 int iBasis;
@@ -1039,13 +1055,18 @@
1039 @ <pre>%h(blob_str(&x))</pre>
1040 @ </div>
1041 blob_reset(&x);
1042 return 0;
1043 }else{
1044 int nrid = wiki_put(&x, iEdit>0 ? iEdit : 0,
1045 forum_need_moderation());
 
1046 blob_reset(&x);
 
 
 
 
1047 cgi_redirectf("%R/forumpost/%S", rid_to_uuid(nrid));
1048 return 1;
1049 }
1050 }
1051
@@ -1135,10 +1156,27 @@
1135 @ From: anonymous<br>
1136 }else{
1137 @ From: %h(login_name())<br>
1138 }
1139 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1140
1141 /*
1142 ** WEBPAGE: forume1
1143 **
1144 ** Start a new forum thread.
@@ -1145,17 +1183,19 @@
1145 */
1146 void forumnew_page(void){
1147 const char *zTitle = PDT("title","");
1148 const char *zMimetype = PD("mimetype",DEFAULT_FORUM_MIMETYPE);
1149 const char *zContent = PDT("content","");
 
1150 login_check_credentials();
1151 if( !g.perm.WrForum ){
1152 login_needed(g.anon.WrForum);
1153 return;
1154 }
1155 if( P("submit") && cgi_csrf_safe(1) ){
1156 if( forum_post(zTitle, 0, 0, 0, zMimetype, zContent) ) return;
 
1157 }
1158 if( P("preview") && !whitespace_only(zContent) ){
1159 @ <h1>Preview:</h1>
1160 forum_render(zTitle, zMimetype, zContent, "forumEdit", 1);
1161 }
@@ -1169,22 +1209,11 @@
1169 if( P("preview") && !whitespace_only(zContent) ){
1170 @ <input type="submit" name="submit" value="Submit">
1171 }else{
1172 @ <input type="submit" name="submit" value="Submit" disabled>
1173 }
1174 if( g.perm.Debug ){
1175 /* Give extra control over the post to users with the special
1176 * Debug capability, which includes Admin and Setup users */
1177 @ <div class="debug">
1178 @ <label><input type="checkbox" name="dryrun" %s(PCK("dryrun"))> \
1179 @ Dry run</label>
1180 @ <br><label><input type="checkbox" name="domod" %s(PCK("domod"))> \
1181 @ Require moderator approval</label>
1182 @ <br><label><input type="checkbox" name="showqp" %s(PCK("showqp"))> \
1183 @ Show query parameters</label>
1184 @ </div>
1185 }
1186 @ </form>
1187 forum_emit_js();
1188 style_finish_page();
1189 }
1190
@@ -1273,13 +1302,15 @@
1273 && (!whitespace_only(zContent) || isDelete)
1274 ){
1275 int done = 1;
1276 const char *zMimetype = PD("mimetype",DEFAULT_FORUM_MIMETYPE);
1277 if( P("reply") ){
1278 done = forum_post(0, fpid, 0, 0, zMimetype, zContent);
 
1279 }else if( P("edit") || isDelete ){
1280 done = forum_post(P("title"), 0, fpid, 0, zMimetype, zContent);
 
1281 }else{
1282 webpage_error("Missing 'reply' query parameter");
1283 }
1284 if( done ) return;
1285 }
@@ -1360,21 +1391,11 @@
1360 }
1361 @ <input type="submit" name="cancel" value="Cancel">
1362 if( (P("preview") && !whitespace_only(zContent)) || isDelete ){
1363 @ <input type="submit" name="submit" value="Submit">
1364 }
1365 if( g.perm.Debug ){
1366 /* For the test-forumnew page add these extra debugging controls */
1367 @ <div class="debug">
1368 @ <label><input type="checkbox" name="dryrun" %s(PCK("dryrun"))> \
1369 @ Dry run</label>
1370 @ <br><label><input type="checkbox" name="domod" %s(PCK("domod"))> \
1371 @ Require moderator approval</label>
1372 @ <br><label><input type="checkbox" name="showqp" %s(PCK("showqp"))> \
1373 @ Show query parameters</label>
1374 @ </div>
1375 }
1376 @ </form>
1377 forum_emit_js();
1378 style_finish_page();
1379 }
1380
1381
--- src/forum.c
+++ src/forum.c
@@ -945,10 +945,25 @@
945 static int whitespace_only(const char *z){
946 if( z==0 ) return 1;
947 while( z[0] && fossil_isspace(z[0]) ){ z++; }
948 return z[0]==0;
949 }
950
951 /* Flags for use with forum_post() */
952 #define FPOST_NO_ALERT 1 /* do not send any alerts */
953
954 /*
955 ** Return a flags value for use with the final argument to
956 ** forum_post(), extracted from the CGI environment.
957 */
958 static int forum_post_flags(void){
959 int iPostFlags = 0;
960 if( g.perm.Debug && P("fpsilent")!=0 ){
961 iPostFlags |= FPOST_NO_ALERT;
962 }
963 return iPostFlags;
964 }
965
966 /*
967 ** Add a new Forum Post artifact to the repository.
968 **
969 ** Return true if a redirect occurs.
@@ -957,11 +972,12 @@
972 const char *zTitle, /* Title. NULL for replies */
973 int iInReplyTo, /* Post replying to. 0 for new threads */
974 int iEdit, /* Post being edited, or zero for a new post */
975 const char *zUser, /* Username. NULL means use login name */
976 const char *zMimetype, /* Mimetype of content. */
977 const char *zContent, /* Content */
978 int iFlags /* FPOST_xyz flag values */
979 ){
980 char *zDate;
981 char *zI;
982 char *zG;
983 int iBasis;
@@ -1039,13 +1055,18 @@
1055 @ <pre>%h(blob_str(&x))</pre>
1056 @ </div>
1057 blob_reset(&x);
1058 return 0;
1059 }else{
1060 int nrid;
1061 db_begin_transaction();
1062 nrid = wiki_put(&x, iEdit>0 ? iEdit : 0, forum_need_moderation());
1063 blob_reset(&x);
1064 if( (iFlags & FPOST_NO_ALERT)!=0 ){
1065 alert_unqueue('f', nrid);
1066 }
1067 db_commit_transaction();
1068 cgi_redirectf("%R/forumpost/%S", rid_to_uuid(nrid));
1069 return 1;
1070 }
1071 }
1072
@@ -1135,10 +1156,27 @@
1156 @ From: anonymous<br>
1157 }else{
1158 @ From: %h(login_name())<br>
1159 }
1160 }
1161
1162 static void forum_render_debug_options(void){
1163 if( g.perm.Debug ){
1164 /* Give extra control over the post to users with the special
1165 * Debug capability, which includes Admin and Setup users */
1166 @ <div class="debug">
1167 @ <label><input type="checkbox" name="dryrun" %s(PCK("dryrun"))> \
1168 @ Dry run</label>
1169 @ <br><label><input type="checkbox" name="domod" %s(PCK("domod"))> \
1170 @ Require moderator approval</label>
1171 @ <br><label><input type="checkbox" name="showqp" %s(PCK("showqp"))> \
1172 @ Show query parameters</label>
1173 @ <br><label><input type="checkbox" name="fpsilent" %s(PCK("fpsilent"))> \
1174 @ Do not sent notification emails</label>
1175 @ </div>
1176 }
1177 }
1178
1179 /*
1180 ** WEBPAGE: forume1
1181 **
1182 ** Start a new forum thread.
@@ -1145,17 +1183,19 @@
1183 */
1184 void forumnew_page(void){
1185 const char *zTitle = PDT("title","");
1186 const char *zMimetype = PD("mimetype",DEFAULT_FORUM_MIMETYPE);
1187 const char *zContent = PDT("content","");
1188
1189 login_check_credentials();
1190 if( !g.perm.WrForum ){
1191 login_needed(g.anon.WrForum);
1192 return;
1193 }
1194 if( P("submit") && cgi_csrf_safe(1) ){
1195 if( forum_post(zTitle, 0, 0, 0, zMimetype, zContent,
1196 forum_post_flags()) ) return;
1197 }
1198 if( P("preview") && !whitespace_only(zContent) ){
1199 @ <h1>Preview:</h1>
1200 forum_render(zTitle, zMimetype, zContent, "forumEdit", 1);
1201 }
@@ -1169,22 +1209,11 @@
1209 if( P("preview") && !whitespace_only(zContent) ){
1210 @ <input type="submit" name="submit" value="Submit">
1211 }else{
1212 @ <input type="submit" name="submit" value="Submit" disabled>
1213 }
1214 forum_render_debug_options();
 
 
 
 
 
 
 
 
 
 
 
1215 @ </form>
1216 forum_emit_js();
1217 style_finish_page();
1218 }
1219
@@ -1273,13 +1302,15 @@
1302 && (!whitespace_only(zContent) || isDelete)
1303 ){
1304 int done = 1;
1305 const char *zMimetype = PD("mimetype",DEFAULT_FORUM_MIMETYPE);
1306 if( P("reply") ){
1307 done = forum_post(0, fpid, 0, 0, zMimetype, zContent,
1308 forum_post_flags());
1309 }else if( P("edit") || isDelete ){
1310 done = forum_post(P("title"), 0, fpid, 0, zMimetype, zContent,
1311 forum_post_flags());
1312 }else{
1313 webpage_error("Missing 'reply' query parameter");
1314 }
1315 if( done ) return;
1316 }
@@ -1360,21 +1391,11 @@
1391 }
1392 @ <input type="submit" name="cancel" value="Cancel">
1393 if( (P("preview") && !whitespace_only(zContent)) || isDelete ){
1394 @ <input type="submit" name="submit" value="Submit">
1395 }
1396 forum_render_debug_options();
 
 
 
 
 
 
 
 
 
 
1397 @ </form>
1398 forum_emit_js();
1399 style_finish_page();
1400 }
1401
1402

Keyboard Shortcuts

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